我怎样才能使“更新"?mongodb 在更新嵌套数组的字段时停止? [英] how can I make the "updated" of mongodb stop when updating a field of a nested array?

查看:39
本文介绍了我怎样才能使“更新"?mongodb 在更新嵌套数组的字段时停止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的数据库:

<代码> {宇宙":漫画",传奇":[{名称":x战警",字符":[{字符":金刚狼",图片":618035022351.png"},{字符":金刚狼",图片":618035022352.png"}]}]},{宇宙":dc",传奇":[{名称":蜘蛛侠",字符":[{字符":毒液",图片":618035022353.png"}]}]}

使用此代码,我更新了 name: wolverine:

的字段

db.getCollection('collection').findOneAndUpdate({宇宙":漫画"},{$set:{saga.$[outer].characters.$[inner].character":lobezno",saga.$[outer].characters.$[inner].picture":618035022354.png";}},/*{传奇人物":1},*/{数组过滤器":[{outer.name":x战警"},{inner.character":金刚狼"}],多":假})

我只想更新第一个匹配的对象,然后停止它.

例如,如果我有一个包含 100,000 个元素的数组,并且匹配的对象位于第十个位置,他将更新该记录,但他将继续遍历整个数组,这对我来说似乎是无效的虽然他已经做了更新.

注意:如果我使用 Universe.saga.characters 内的_id 进行更新而不是使用name 进行更新,它仍然会遍历其余的元素.

我该怎么做?

解决方案

使用 arrayFilters 条件更新

我不认为它会通过循环查找和更新,并且集合是否有 100,000 个子文档并不重要,因为这里在 $[] 并提到:

  • $[] 定义一个标识符以仅更新那些与 arrayFilters 中的相应过滤器文档匹配的数组元素

  • 在更新文档中,使用 $[] 过滤位置运算符来定义标识符,然后您可以在数组过滤器文档中引用该标识符.但是,如果标识符未包含在更新文档中,请确保您不能拥有用于标识符的数组过滤器文档.

使用_id

更新

你的观点,

<块引用>

注意:如果我使用 universe.saga.characters 内的 _id 进行更新而不是使用名称进行更新,它仍然会循环通过其余的元素.

MongoDB 肯定会使用 _id 索引.这是关于答案db-update-query-performance">MongoDB 更新查询性能,从这里您将更好地了解上述要点

使用索引字段更新

您可以根据更新命令的查询部分创建索引,这里MongoDB 索引并且索引策略解释了为什么索引很重要,

在你的例子中,让我们看看例子:

<块引用>

示例 1: 如果文档有 2 个子文档,并且当您更新并检查 explain("executionStats"),假设更新需要1秒,

快速使用Mongo Playground (本平台不支持更新查询)

<块引用>

示例 2: 如果文档有 1000 个子文档,并且当您更新和检查 explain("executionStats"),可能需要 1 秒以上,

如果在字段(universesaga.characters.charactersaga.characters.picture)上提供索引,那么肯定会花费更少那时通常没有索引,索引的主要好处是它会直接指向索引字段.

快速使用Mongo Playground (本平台不支持更新查询)

为您的字段创建索引

db.maxData.createIndex({宇宙":1,saga.characters.character":1,saga.characters.picture":1})

<块引用>

更多的实验使用上面2个带索引和不带索引的示例数据,检查executionStats你会更清楚.

I have a database like this:

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

And with this code, I update the field where name: wolverine:

db.getCollection('collection').findOneAndUpdate(
  {
    "universe": "comics"
  },
  {
    $set: {
      "saga.$[outer].characters.$[inner].character": "lobezno",
      "saga.$[outer].characters.$[inner].picture": "618035022354.png"
    }
  },
  /*{
    "saga.characters": 1
  },*/
  {
    "arrayFilters": [
      {
        "outer.name": "x-men"
      },
      {
        "inner.character": "wolverine"
      }
    ],
      "multi":false
  }

)

I want to just update the first object where there is a match, and stop it.

For example, if I have an array of 100,000 elements and the object where the match is, is in the tenth position, he will update that record, but he will continue going through the entire array and this seems ineffective to me even though he already did the update.

Note: if I did the update using an _id inside of universe.saga.characters instead of doing the update using the name, it would still loop through the rest of the elements.

How can I do it?

解决方案

Update using arrayFilters conditions

I don't think it will find and update through loop, and It does not matter if collection have 100,000 sub documents, because here is nice explanation in $[<identifier>] and has mentioned:

  • The $[<identifier>] to define an identifier to update only those array elements that match the corresponding filter document in the arrayFilters

  • In the update document, use the $[<identifier>] filtered positional operator to define an identifier, which you then reference in the array filter documents. But make sure you cannot have an array filter document for an identifier if the identifier is not included in the update document.

Update using _id

Your point,

Note: if I did the update using an _id inside of universe.saga.characters instead of doing the update using the name, it would still loop through the rest of the elements.

MongoDB will certainly use the _id index. Here is the nice answer on question MongoDB Update Query Performance, from this you will get an better idea on above point

Update using indexed fields

You can create index according to your query section of update command, Here MongoDB Indexes and Indexing Strategies has explained why index is important,

In your example, lets see with examples:

Example 1: If document have 2 sub documents and when you update and check with explain("executionStats"), assume it will take 1 second to update,

quick use Mongo Playground (this platform will not support update query)

Example 2: If document have 1000 sub documents and when you update and check with explain("executionStats"), might be it will take more then 1 second,

If provide index on fields (universe, saga.characters.character and saga.characters.picture) then definitely it will take less time then usual without index, main benefit of index it will direct point to indexed fields.

quick use Mongo Playground (this platform will not support update query)

Create Index for your fields

db.maxData.createIndex({ 
    "universe": 1, 
    "saga.characters.character": 1, 
    "saga.characters.picture": 1
})

For more experiment use above 2 examples data with index and without index and check executionStats you will get more clarity.

这篇关于我怎样才能使“更新"?mongodb 在更新嵌套数组的字段时停止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆