Mongooseとは
どんな種類のデータを保存できるかを定義する「スキーマ」を持つモデルを構築できる。
モデルはjavasrciptにおけるクラスのようなもの。
Mongooseはモデルを使って、データベースクエリの組織化を行う。
よく使うクエリメソッド
find : マッチするドキュメントの配列を返す。
Human.find({name:"taro" }, (err, result)=> {
//処理結果
});
findOne : 配列でなく一つのドキュメントを返す。 例) Human.findOne({name: "Taro"})
findById : ObjectIdeで一致するオブジェクトを返す。 例)Human.findOne("kjfkajjdfkjagkja")
remove : データーベースにあるドキュメントを削除する。
find().pretty() : .pretty()をつけることにより結果がインデントされる。
```
これらのクエリはプロミスを返すので、結果処理には then や catchでつなげる必要がある。
Node.jsアプリケーションにMongooseを設定する。
//mongooseをロード
const mongoose = require("mongoose");
//データーベース接続を設定
mongoose.connect(
"mongodb://<username>:<password>@localhost:27017/<dbname>",
{userNewParser:true}
);
mongoose.set("useCreateIndex", true);
//データーベースをdb変数に代入
const db = mongoose.connection;
//接続メッセージをログに出力する
db.once("open",()=>{
console.log("success connect");
});
スキーマを作る
mongoose.Schemaメソッドのコンストラクタにパラメーター(オブジェクト)を与えることによって、スキーマオブジェクトを構築できる。
const mongoose = require("mongoose");
const humanSchema = new mongoose.Schema({
name:String,
age:Number
});
スキーマのデータ型について
https://mongoosejs.com/docs/schematypes.html
仮想属性を設定する
const humanSchema = new mongoose.Schema({
name:String,
age:Number
});
humanSchema.virtual("info").get(function () { //実際の属性としてはデーターベースに保存されないが、インスタンスから取り出せる。
return `${this.name} ${this.age}`;
});
バリデーションを設定する
"use strict";
const mongoose = require("mongoose");
const humanSchema = new mongoose.Schema({
name: { //nameのバリューにオブジェクトで渡す。
type: String,
required: true, //必須
unique: true //ユニーク
},
age: {
type: Number,
min: [18, "Too short"],//最小値エラーメッセージ を設定
max: 99 //最大値
}
});
module.exports = mongoose.model("Human", humanSchema);
スキーマをモデルに適用する。
const Human = mongoose.model("Human", humanSchema)
//mongoose.modelメソッドに("モデル名", スキーマ)を引数に与えて、実体化してHumanに格納する。
エクスポート
module.exports = mongoose.model("Human", humanSchema);
スキーマにインスタンスメソッドを設定する。(getInfoと言う名のメソッドを設定)
humanSchema.methods.getInfo = function () {
return `Name: ${this.name} Age: ${this.age}`;
};
モデルからオブジェクトを作る。
new → saveの方法
let human1 = new Human({ //newキーワードでオブジェクトを生成。
name: "Taro",
age:20
});
human1.save((error, savedDocument) => { //saveメソッドで保存
//引数に、エラー処理、または返されるデーターの処理をコールバック関数で渡す。
if (error){
console.log(error)
}
console.log(savedDocument);
createの方法
Human.create({
name: "Taro",
age:20
},
function(error,savedDocument){
if (error){
console.log(error)
}
console.log(savedDocument);
}
};
//createは、newとsaveを一気に行う。(パラメータ, コールバック)が引数。
フックを設定する。
humanSchema.pre("save", function(next) {
//saveされる前に実施する処理
//この中でのthisは呼び出し元、つまりhumanSchemaが格納される。
next();
}
モデルを組織化する
モデルファイルにスキーマとモデルを定義する。
const mongoose = require("mongoose");
const humanSchema = mongoose.Schema({ //mongoose.Schemaメソッドでスキーマを作る
name:String,
age:Number
});
module.exports = mongoose.model("Human", humanSchema);
//mongoose.modelメソッドでスキーマをHumanモデルに適用しエクスポート
他のファイルからHumanモデルを呼び出す。
const Human = require("./models/human");
モデル間のリレーションを設定する
"use strict";
const mongoose = require("mongoose");
const humanSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true
},
age: {
type: Number,
min: [18, "Too short"],
max: 99 //最大値
}
father: { //Fatherモデルに所属//単数形
type: mongoose.Schema.Types.ObjectId, //外部キー
ref: "Father" //参照モデル
}
children: [{ //Childモデルを所有//複数形//配列リテラルで囲む
type: mongoose.Scheme.Types.ObnectId,
ref: "Child"
}]
});
module.exports = mongoose.model("Human", humanSchema);
実際にドキュメント同士を関連づける
//所有の場合
human1.children.push(child1);
human1.save();
//human1インスタンスのchildrenプロパティにchild1ドキュメントを追加
//もしくは、直接ObjectIDを追加する。
human1.children.push("オブジェトID");
human1.save();
//所属の場合
human1.father = father1;
human1.save();
関連付いたドキュメントを取得する。
Human.populate(human1, "children"); //human1に紐づくchildドキュメントを連結してオブジェクト化する。
親を指定して、関連づいたドキュメントを取得する。
Human.findOne({ name: "taro" }).populate({"children" }).exec((error, data) => {
console.log(data);
}
)
データベース内のドキュメントを検索する
const Human = require("./models/human");
Human.findOne({name:"Taro"}).where("age":20);
//findOne(合致するものを取得).where(絞り込み条件);
クエリを実行する
let query = Human.findOne({name:"Taro"}).where("age":20);
query.exec((error, data)=>{ //execで実行し、処理を引数にとる。返るデータはdataに渡す。
if(data){
console.log(data.name)
}
);
検索とアップデートを同時に行う
<モデル>.findByIdAndUpdate(<id>, {
$set: <オブジェクト>//$setのバリューの値でアップデート
})
検索と削除を同時に行う
<モデル>.findByIdAndRemove(<id>)
プロミスを使うための設定
mongoose.Promise = global.Promise
シードモジュールの作成
const mongoose = require("mongoose"); //モジュールロード
const Human = require("./models/Human.js");
//保存するモデルの読み込み必要
mongoose.connect( //接続設定
"mongodb://localhost:27017/my_db",
{userNewParser:true}
);
mongoose.set("useCreateIndex", true);
mongoose.connection;
const humans = [ //シードデーター
{name:"Taro",
age:20
},
{name:"Ken",
age:30
},
{name:"Jiro",
age:40
}
];
Human.deleteMany() //既存のデータをクリア
.exec()
.then(() => {
console.log("Empty"); //確認用ログ
});
let commands = []; //シーダー配列用
humans.forEeach((c)=> { //commands配列にシーダーをループで全て追加
commands.push(Human.create({
name:c.name,
email:c.age
}));
});
Promise.all(commands) //全てのプロミス解決後の処理
.then(r => {
console.log(JSON.stringify(r));
mongoose.connection.close();
})
.catch(error => {
console.log($error);
});