我在蒙古有以下数据结构:
{
"_id": "L7ucxMsTSfTDtctnt",
"lectures": [
{
"_id": "Tfr3DMxavZwP5yy6F",
"notes": [
{
"slide": 1,
"notes": "First Note",
"timestamp": "2015-05-18T20:18:36.510Z"
},
{
"slide": 2,
"notes": "Another note",
"timestamp": "2015-05-18T20:18:36.510Z"
}
]
}
]
}
我正在尝试做一个三重翻转和一个数组推送。如果外部_id不存在,创建它,否则更新它。如果lecture _id不存在,创建它,否则更新它。如果notes _id不存在,创建对象并push到notes数组,否则更新它。
有可能做这么复杂的事情吗?我可以分三个单独的步骤来完成,但是我经常调用这个函数,并且担心性能。
如果你能在3个步骤中做到这一点,那将是相当令人印象深刻的…见鬼,仅仅是试图用该模式编写一个查询来返回单个notes对象就会伤到我的大脑。(试试吧,你不会喜欢的)。
对象数组模式在第二层之后开始变得非常麻烦。通常最好使用一个新的集合或将其存储为子文档(doc.lectures['alsfjljfldjf5084534']
),因为这样你就有一个内存地址可以引用,而不是敲你的头试图执行一个嵌套的$elemmatch
。
无论如何,回答你的问题,它只是一个upsert,因为它只有一个文档。当你想到整件事是1个文档时,你就更容易理解了。去拿医生吧!将其保存为JS对象。修改对象&那就把整个事情搞砸。不要担心传输几个额外的重复数据字节。用疯狂的迭代查询来找到你想要编辑的文档中的特定点,这会让你的数据库非常费力。
在这个特殊的情况下,你已经得到了正确的ER模型(一个类有很多讲座,一个讲座有很多笔记),但是,根据你的查询模式,你可能想把类放在它们自己的集合&将d类作为FK包含在你的讲座集合中。然后,可以选择将notes作为子文档,以便于访问。
在这样做时,获取一个note对象非常简单,如下所示:Lectures.findOne({notesID: '234asfj'})
。当然,你失去了原子性,但这是一个很小的代价。
doc = {}; //empty object
subDocId = Random.id(); //ref for subdoc
doc[subDocId] = {
notes: 1,
text: 'foo'
}; // create subdoc
Lecture.insert(doc); //insert subdoc
或
var doc = Lectures.findOne(); //get it
doc["Tfr3DMxavZwP5yy6F"] = {foo:1, bar:2} //mod it
Lecture.insert(doc); //upload it