2014-01-31 37 views
0

我是mongodb的新手,我正在使用它来存储嵌套的文档。例如。每个文档都包含每个班级的学生数组。我正在尝试更新每个阵列节点中的信息。有没有更好的方法来做到这一点,而不是一次更新每个数组元素?使用游标更新嵌套的mongodb集合

下面是我收集的记录 -

{ 
    “_id” : “23343” , 
    “class” : “Physics”, 
    “students”: [ 
     { “id” : “2412” , “name” : "Alice", “mentor” : 0 }, 
     { “id” : “2413” , “name” : "Bob, “mentor” : 0 }, 
    ] 
} 

有多个记录,这样的收藏。

我有这些课程的列表,我需要更新每条记录。例如,我让学生的数组,上面记录着更新这样的 -

{ 
    “_id” : “23343” , 
    “class” : “Physics”, 
    “students”: [ 
     { “id” : “2412” , “name” : "Alice", “mentor” : "Mark" }, 
     { “id” : “2413” , “name” : "Bob, “mentor” : "Jackson" }, 
    ] 
} 

什么是更新记录的最好方法?

我正在使用python。直觉上,我可以在课程的集合上做一个find()。我得到一个游标。我可以为每个游标做一个。我相信mongodb更新update()上的整个文档。

for record in courseCollection.find(): 
    recordId = record['_id'] 
    updatedList = getUpdatedStudentList(record['students']) 
    updatedRecord = prepareUpdatedRecord(updatedList) 
    courseCollection.update({'_id' : recordId}, updateList) 

pymongo文档站点不会讨论update函数中的set选项。除非我使用它,否则我相信MongoDB会更新整个文档。

通过传递_id调用更新与查询选项似乎没有必要,因为我只是做了查询,并有记录的句柄。我可以以某种方式使用光标在那里做更新通过不再执行更新的查询?

回答

0

我不太确定这个问题到底是什么。简而言之:是的,您必须更新“父”对象,是的,您可以使用$set或替换整个文档,这将是默认行为。差别主要在于锁定,并发和拥有,这有点复杂。下面是关于你的一些顾虑更详细一点:

使用游标

请注意,没有“嵌套集合”,只有嵌入文档更新嵌套的MongoDB集合。这很重要,因为mongodb中的头等公民始终是实际的文档本身。例如,find()将返回文档,而不是单独的嵌入式文档的子集。你可以做预测,但这只是一个输出转换,可以这么说。

我可以在课程的集合上做find()。我得到一个游标。

你得到一个光标,但因为你是主键查询只能有一个匹配(主键是唯一的),即你可以使用findOne(),你不需要重复单结果。

例如,每个文档都包含每个班级的学生数组。

这些通常应该是参考给学生,即应该有一个单独的学生集合,因为你不想失去该学生,因为它暂时没有分配到任何课程。

pymongo文档站点不会介绍update函数中的set选项。除非我使用它,否则我相信MongoDB会更新整个文档。

确实如此。您可以在文档的students阵列上执行$set。这可以避免覆盖任何其他字段,如class。另一方面,如果其他人在您使用编辑学生时更改了class,那么更新仍然有意义吗?不明确的所有权是我对嵌入式文档的首要关注。

而且通过传递_id调用带有查询选项更新似乎是不必要的,因为我只是做了查询,并有一个句柄记录

...但究竟是一个手柄记录?句柄是一个不可变的,唯一的,通常很短的标识符。就像身份证。 _id的句柄。我不知道python,但我想你可以编写一个方法,它接受一个指向数据库对象的指针并执行更新,知道每个数据库对象都必须有一个名为_id的字段。但是从数据库的角度来看,代码中的指针不是句柄,而是id。

1

您可以在更新中使用the $ operator和$ elemMatch。让我们通过插入文档开始:

collection.insert({ 
    "_id": "23343", 
    "class": "Physics", 
    "students": [ 
     {"id": "2412", "name": "Alice", "mentor": 0}, 
     {"id": "2413", "name": "Bob", "mentor": 0}]}) 

现在,我将运行两个更新语句,先加入导师“标记”,然后在“禅师”:

collection.update(
    # Query portion. 
    {"_id": "23343", "students": {"$elemMatch": {"id": "2412"}}}, 
    # Update portion; $ is the position of the matching student. 
    {"$set": {"students.$.mentor": "Mark"}}) 

collection.update(
    # Query portion. 
    {"_id": "23343", "students": {"$elemMatch": {"id": "2413"}}}, 
    {"$set": {"students.$.mentor": "Jackson"}}) 

每个更新语句影响只是“ “学生”数组中的一个子文档的“导师”字段。