【问题标题】:What's the most economical alternative to multiple positional identifiers in MongoDB?MongoDB 中多个位置标识符最经济的替代方案是什么?
【发布时间】:2019-07-19 17:35:07
【问题描述】:

我有一个名为 authors 的集合,其架构如下:

authors: {
  _id,
  firstName,
  lastName,
  posts: [
    post 1: {...},
    post 2: {...},
    post 3: {
      _id,
      title,
      content,
      tags: [
        tag 1: {...},
        tag 2: {...},
        tag 3: {
          _id,
          name,
          description,
        },
      ],
    },
  ],
}

可以看出,postsauthors 集合中的对象数组。该数组中的每个对象依次具有标签,即另一个对象数组。每个标签对象都有三个字段:_idnamedescription

我正在尝试编写一个 GraphQL 突变来更新集合中匹配文档的这个 name 字段。

    const updatedTagInAuthor = await Author
  .updateMany({ 'posts.tags._id': args.newTagInfo._id },
    {
      $set: {
        'posts.$.tags.$.name': args.newTagInfo.name,
        'posts.$.tags.$.description': args.newTagInfo.description,
      },
    }, opts);

上面的 sn-p 显然失败了,因为 MongoDB 不允许在查询中使用多个位置元素 ($)。那么是否有任何经济的替代方案来完成我想做的事情?

我尝试了 MongoDB 建议的 ArrayFilter 方法:

           const updatedTagInAuthor = await Author.update(
              {},
              { $set: { 'posts.$[].tags.$[tag].name': args.newTagInfo.name } },
              { arrayFilters: [{ 'tag._id': args.newTagInfo._id }], multi: true }
            );

但这会引发以下错误:

无法读取未定义的属性“castForQuery”

还是一头雾水!

【问题讨论】:

    标签: mongodb mongoose mongodb-query


    【解决方案1】:

    这些是我正在使用我给出的查询类型更新的文档,

    {"name" : "Steve","details" : [ {
            "work" : [ {
                    "Company" : "Byjus",
                    "id" : 1,
                    "country" : "India"
                }, 
                {
                    "Company" : "Vodafone",
                    "id" : 2,
                    "country" : "UK"
                }]
        }]},{"name" : "Virat","details" : [ {
            "work" : [ {
                    "Company" : "Byjus",
                    "id" : 1,
                    "country" : "India"
                }, 
                {
                    "Company" : "Verizon",
                    "id" : 3,
                    "country" : "US"
                }]
        }]}
    
    QUERY:
    
    db.getCollection('Users').update({"details": {"$elemMatch": {"work.id": 1}}}, {'$set': {'details.$[].work.$.Company': 'Boeing', 'details.$[].work.$.country': 'US'} }, {multi: true});
    

    这和你问的很相似吧? 尝试将这两个文档插入一个名为 User 的集合中,然后直接在 Mongo CONSOLE 中尝试上述查询,而不是在 GUI 中。完全使用 Query 而不仅仅是 $set 方法。

    【讨论】:

      【解决方案2】:

      试试这个,

      Author.update({"posts": { "$elemMatch": { "tags.id": args.newTagInfo._id } }}, 
          {'$set': {'posts.$[].tags.$.name': args.newTagInfo.name, 'posts.$[].tags.$.description': args.newTagInfo.description} }, 
          {multi: true});
      

      【讨论】:

      • 不更新任何东西,但也不抛出任何错误。
      • 我已经用 { "$elemMatch": { "tags.id": args.newTagInfo._id } 更新了 $elemMatch在它有 { "$elemMatch": { "tags.id": 1 } 之前。可能就是这个错误。
      • 我已经注意到这一点并相应地修改了我的查询。但问题不在于那部分,因为我原来的.updateMany({ 'posts.tags._id': args.newTagInfo._id }, 也能够查找正确的文档。我无法使用 $set 表达式。就像我说的那样,您的解决方案不会引发错误,但也不会更新集合中的任何内容。
      • 您使用的是什么版本的 Mongo DB?我是用 Mongo 4 完成的,如果您使用的是 Mongo DB 4,请在 Mongo 控制台中尝试此代码。
      • 我正在使用运行 4.0.6 版的 Mongo Atlas。
      猜你喜欢
      • 2017-06-11
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 1970-01-01
      • 2015-12-25
      • 2021-11-13
      • 2018-12-01
      相关资源
      最近更新 更多