【问题标题】:Updating a nested mongodb collection using a cursor使用游标更新嵌套的 mongodb 集合
【发布时间】:2014-01-31 04:39:22
【问题描述】:

我是 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 文档站点没有讨论更新函数中的 set 选项。除非我使用它,否则我相信 mongodb 会更新整个文档。

通过传入 _id 来调用带有查询选项的更新似乎是不必要的,因为我刚刚进行了查询并且有记录的句柄。我可以通过不再查询更新来以某种方式使用光标在那里进行更新吗?

【问题讨论】:

    标签: python mongodb


    【解决方案1】:

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

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

    现在我将运行两条更新语句,首先添加导师“Mark”,然后添加“Jackson”:

    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"}})
    

    每个更新语句只影响“students”数组中一个子文档的“mentor”字段。

    【讨论】:

      【解决方案2】:

      我不太确定问题是什么,确切地说。简而言之:是的,您必须更新“父”对象,是的,您可以使用$set 或替换整个文档,这将是默认行为。区别主要在于锁定、并发和所有权问题,这有点复杂。以下是关于您的一些担忧的更多细节:

      使用游标更新嵌套的 mongodb 集合

      请注意,没有“嵌套集合”,只有嵌入文档。这很重要,因为 mongodb 中的一等公民始终是实际文档本身。例如,find() 将返回文档,而不仅仅是嵌入文档的子集。您可以进行投影,但这只是一种输出转换,可以这么说。

      我可以对课程的集合执行 find()。我得到了一个光标。

      您得到一个游标,但由于您查询的是主键,因此只能有一个匹配项(主键是唯一的),即您可以使用 findOne() 并且您不需要迭代单个结果.

      例如每个文档包含每个班级的一组学生。

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

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

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

      通过传入 _id 来调用带有查询选项的更新似乎是不必要的,因为我刚刚进行了查询并且有记录的句柄

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

      【讨论】:

      • 我相信他要问的是“我们是否必须通过一些查询路径从根目录导航到嵌入文档”?还是“有某种类似指针的方式直接检索嵌入的文档并进行更新”?
      猜你喜欢
      • 2021-12-05
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-11-04
      • 2015-05-06
      相关资源
      最近更新 更多