【问题标题】:How can I return the element I'm looking for inside a nested array?如何在嵌套数组中返回要查找的元素?
【发布时间】:2020-11-09 06:32:50
【问题描述】:

我有一个这样的数据库:

[
   {
      "universe":"comics",
      "saga":[
         {
            "name":"x-men",
            "characters":[
               {
                  "character":"wolverine",
                  "picture":"618035022351.png"
               },
               {
                  "character":"cyclops",
                  "picture":"618035022352.png"
               }
            ]
         }
      ]
   },
   {
      "universe":"dc",
      "saga":[
         {
            "name":"spiderman",
            "characters":[
               {
                  "character":"venom",
                  "picture":"618035022353.png"
               }
            ]
         }
      ]
   }
]

通过这段代码,我设法更新了数组中的一个对象。特别是character: wolverine的对象

db.mydb.findOneAndUpdate({
        "universe": "comics",
        "saga.name": "x-men",
        "saga.characters.character": "wolverine"
    }, {
        $set: {
            "saga.$[].characters.$[].character": "lobezno",
            "saga.$[].characters.$[].picture": "618035022354.png",

        }
    }, {
        new: false
    }

)

它返回我所有的文档,我只需要匹配的文档

我想返回我已更新的对象,而不必对数据库进行更多查询。

注意

我被告知我的代码不能正常工作,显然我的查询更新了这个错误,我想知道如何修复它并获取与这些搜索条件匹配的对象。

换句话说,我怎样才能得到这个输出:

           {
              "character":"wolverine",
              "picture":"618035022351.png"
           }

在单个查询中使用过滤器

    {
     "universe": "comics",
     "saga.name": "x-men",
     "saga.characters.character": "wolverine"
    }

我的 MongoDB 知识使我无法更正此问题。

【问题讨论】:

  • 尝试提供 new:true 而不是 false。
  • 不行,它会返回我所有的文档,我只需要匹配的文档
  • 您可以尝试使用projection 参数 - 定义为“要返回的字段子集。”
  • @prasad_ 我知道,虽然我不知道该怎么做,但我知道我应该使用 agreattions,但在这种情况下我正在更新......
  • (1) 您的更新语句看起来不正确 - 使用的语法需要 arrayFilters。 (2)$[]数组更新所有位置操作符更新数组的所有元素。要更新特定的数组元素,您需要使用$[id] 位置过滤运算符 $ 位置运算符。 (3) 是的,你可以使用Updates with Aggregation Pipeline,我认为在投影的情况下可能没有区别。

标签: mongodb


【解决方案1】:

使用shell方法findAndModify来满足你的需要。

但是在 MongoDb 中进行投影时,您不能多次使用位置字符 $,因此您可能必须在客户端自己跟踪它。

使用arrayFilters 来更新深层嵌套的子文档,而不是位置运算符$[]

下面是一个有效的查询 -

var query = {
    universe: 'comics'
};

var update = {
    $set: {
        'saga.$[outer].characters.$[inner].character': 'lobezno',
        'saga.$[outer].characters.$[inner].picture': '618035022354.png',
    }
};

var fields = {
    'saga.characters': 1
};

var updateFilter = {
    arrayFilters: [
        {
            'outer.name': 'x-men'
        },
        {
            'inner.character': 'wolverine'
        }
    ]
};

db.collection.findAndModify({
    query,
    update,
    fields,
    arrayFilters: updateFilter.arrayFilters
    new: true
});

【讨论】:

  • 非常感谢您的帮助,但是如果您在这里看到 cmets,您会看到用户告诉我可以直接从 mongodb 返回匹配的对象,正是出于这个原因,我问了这个题。顺便说一句,“外”、“内”可以是任何词,还是我总是必须使用它们?
  • @yavg outerinner 可以是任何你喜欢的标识符,我只是发现它们在这种情况下有意义
  • @yavg 如果只有一个数组级别,这是可能的。使用$elemMatch 运算符
  • 谢谢您,我对您的回答非常满意,因此在我的情况下,在进行更新时绝对不可能返回单个对象。
  • @yavg 当数组仅嵌套在 1 级而不是多级时,这是可能的。见this答案
【解决方案2】:
  • 如果我正确理解您的问题,您的更新按预期工作,您的问题是它返回整个文档,您不想查询数据库只是为了返回这两个字段。

  • 为什么不直接从更新返回的文档中提取字段?这样做时您不会进入数据库。

    var extractElementFromResult = null;
    if(result != null) {
       extractElementFromResult = result.saga
          .filter(item => item.name == "x-men")[0]
          .characters
         .filter(item => item.character == "wolverine")[0];
    }

【讨论】:

  • 同一个查询一定可以,我不想做其他操作。
猜你喜欢
  • 2020-05-30
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 2022-06-11
  • 2020-02-19
  • 2013-08-25
  • 2021-10-14
  • 1970-01-01
相关资源
最近更新 更多