読者です 読者をやめる 読者になる 読者になる

MongooseでのCRUDと謎挙動

const Mongoose = require("mongoose");
const Schema = Mongoose.Schema;
Mongoose.connect("mongodb://localhost:27017/sample");
const Person = Mongoose.model("person",  // <-この"person"が後で問題になる
    new Schema({
        created: {type: Date, default: Date.now},
        name: String
    })
);
export {Person};

こんな風に適当なPersonスキーマを作って、

const Express = require("express");
import {Person} from "./Models";
const APIRoute = Express.Router();
APIRoute.post("/person", (req, res) => {
    let upsertPerson = new Person(req.body);
    Person.findOneAndUpdate(
        {_id: upsertPerson._id},
        upsertPerson,
        {upsert: true},
        (error) => { /*割愛。*/ res.sendStatus(200);}
    );
});

APIRoute.delete("/person", (req, res) => {
    let deletePerson = new Person(req.body);
    deletePerson.remove((error) => { /*割愛。*/ res.sendStatus(200);});
});

APIRoute.get("/person", (req, res) => {
    Person.find().limit(10).sort({_id: -1})
        .exec((error, list) => {/*割愛。*/ res.send(list);});
});

export default APIRoute;

expressの本体は以下。

const Express = require("express");
const bodyParser = require("body-parser");
import APIRoute from "./routes/APIRoute";
app.use(bodyParser.json());
app.use("/api", APIRoute);
app.listen(8080);

送信側は、Reactのコンポーネントの中から抜粋。

//前略
    changePerson(person, remove) {
        const method = remove ? "del" : "post";
        SuperAgent[method]("/api/person")
            .set("Content-Type", "application/json")
            .send(person)
            .end((err, res) => {
                if (res.statusCode == 200) {
                    this.loadList();
                } else {
                    this.setState({error: err});
                }
            });
    },

    loadList() {
        SuperAgent.get("/api/people")
            .end((err, res) => {
                if (res.statusCode == 200) {
                    this.setState({list: res.body});
                } else {
                    this.setState({error: err});
                }
            });
    },
//後略

これでちゃんとデータのCRUDができますが。。。謎挙動が一つ。こんだけ"person"を連呼しているのに、Mongo上に作られるCollectionの名前が複数形の"people"になる!これが仕様なのですが、わざわざ何でこんなことをするのか、mongooseの実装ポリシーがわからない。あまりにも謎すぎてググったら、やはり皆が頭を悩ませていました。例えば"Activity"を指定したら"Activities"になるし、単数形と複数形が同じ単語の場合は変換されないという無駄に芸が細かい。

ということで、冒頭のスキーマコードではCollection名を設定する以下の箇所を正すべき?正さないべき?直さなくても動きますし、mongoの実際のコレクション名と設計は別のことですけどね。直さない方がいいのかなぁ。

const Person = Mongoose.model("people", // <-"person"を"people"に変更?しなくても良い