私は、MongooseでNode.jsとMongoDBを使用するのはかなり新しいです。現在、私はかなり厄介な問題に直面しています。これまでに思いついたものよりも優れた解決策があると確信しています。
問題は、埋め込まれたドキュメントを更新するための「良い」方法が見つからないことです。これが私のシナリオです:
- リストコンテナを作成する
- N個のListItemを作成し、それらをList-containerに追加します
- ListItemXの値を見つけて更新します
これは非常に簡単ですが、とにかく単純に、私はすべて運が悪かったのです。
これが私がこれまでに持っているものです。これは2つの解決策であり、どちらも機能しますが、どちらもある時点でListItemを反復処理する必要がありますが、これは本当にやりたくないことです。
ShoppingListItem = new Schema({
listID : ObjectId
,ingredient : [Ingredient]
,count : Number
});
ShoppingList = new Schema({
name : String
,userID : ObjectId
/* Embedded documents solution */
,items : [ShoppingListItem]
/* No embedded documents solution */
/*,items : [{
ingredient : [Ingredient]
,count : Number
}]*/
});
ShoppingList.methods.addItem = function addItem(newItem, cb){
var __self = this;
var _id = __self._id;
/**
* Embedded documents solution (Need to both maintain the embedded document source PLUS manually update the actual embedded document)
**/
ShoppingListItem.findOne({'listID' : _id, 'ingredient.name' : newItem.ingredient.name}, function(err, item){
if(!item){
var item = new ShoppingListItem({
listID : _id
,ingredient : [newItem.ingredient]
,count : newItem.count
});
item.save(function(err, saved){
__self.items.push(saved);
__self.save(cb);
});
}else{
item.count += newItem.count;
item.save(function(err, saved){
//Iterate through all ListItems to update the embedded document to reflect the changed "source" document
for(var i = 0; i < __self.items.length; ++i){
if(__self.items[i]._id.equals(saved._id)){
__self.items[i] = saved;
}
}
__self.markModified('items');
__self.save(cb);
});
}
});
/**
* No embedded documents solution (Only need to maintain the internal objects)
**/
/*
var existing = __self.items.filter(function(item){ return item.ingredient.name.equals == newItem.ingredient.name;});
if(existing.length > 0){
existing[0].count += newItem.count;
}else{
__self.items.push(newItem)
}
__self.markModified('items');
__self.save(cb);
*/
}
上記の2つのソリューションのうち、コードが最も少ないので、後者の方が「エレガント」なソリューションだと思います。ただし、MongoDBのクエリは、配列をフィルタリングするよりもドキュメントを検索する方が高速であるため、最初の方法を使用できるようにしたいと思います。私の最後の考えは、MongooseのDBRef機能を利用しようとすることでしたが、それをソリューションに適用する方法がわかりません。
それで、長い質問は短いです:「コピーを埋め込む」のではなく、ドキュメントを「リンク」する方法はありますか(これは私が埋め込まれたドキュメントを見る方法です)?
よろしくお願いします!
編集:上記のソリューションは両方とも機能しますが、大規模で非常に効率的であるとは思えません(たとえば、リスト内の1.000.000以上のアイテム)