node.js mongo 可以插入数组数据吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13588342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:43:38  来源:igfitidea点击:

Can mongo upsert array data?

node.jsmongodb

提问by ThomasReggi

I have a mongo document like this.

我有一个这样的 mongo 文档。

{
    "_id" : ObjectId("50b429ba0e27b508d854483e"),
    "array" : [
        {
            "id" : "1",
            "letter" : "a"
        },
        {
            "id" : "2",
            "letter" : "b"
        }
    ],
    "tester" : "tom"
}

I want to be able to insert and update the arraywith a single mongo command and not use a conditional within a find()then run insert()and update()depending on the presence of the object.

我希望能够array使用单个 mongo 命令插入和更新,而不是在find()then run 中使用条件,insert()并且update()取决于对象的存在。

The idis the item I want to be the selector. So if I update the array with this:

id是我想成为选择器的项目。所以如果我用这个更新数组:

{
    "id" : "2",
    "letter" : "c"
}

I have to use a $setstatement

我必须使用$set声明

db.soup.update({
    "tester":"tom",
    'array.id': '2'
}, {
    $set: {
        'array.$.letter': 'c'
    }
})

And if I want to insert a new object into the array

如果我想在数组中插入一个新对象

{
    "id" : "3",
    "letter" : "d"
}

I have to use a $pushstatement

我必须使用$push声明

db.soup.update({
    "tester":"tom"
}, {
    $push: {
        'array': {
            "id": "3",
            "letter": "d"
        }
    }
})

I need a sort of upsert for an array item.

我需要一种数组项的 upsert。

Do I have to do this programmatically or can I do this with a single mongo call?

我必须以编程方式执行此操作还是可以通过单个 mongo 调用执行此操作?

采纳答案by Stennie

I'm not aware of an option that would upsert into an embedded array as at MongoDB 2.2, so you will likely have to handle this in your application code.

我不知道有一个选项可以像 MongoDB 2.2 那样插入到嵌入式数组中,因此您可能必须在应用程序代码中处理这个问题。

Given that you want to treat the embedded array as sort of a virtual collection, you may want to consider modelling the array as a separate collection instead.

鉴于您想将嵌入的数组视为一种虚拟集合,您可能需要考虑将数组建模为一个单独的集合。

You can't do an upsert based on a field value within an embedded array, but you could use $addToSetto insert an embedded document if it doesn't exist already:

您不能根据嵌入数组中的字段值执行 upsert,但$addToSet如果嵌入的文档尚不存在,则可以使用它来插入:

db.soup.update({
    "tester":"tom"
}, {
    $addToSet: {
        'array': {
            "id": "3",
            "letter": "d"
        }
    }
})

That doesn't fit your exact use case of matching by idof the array element, but may be useful if you know the expected current value.

这不适合您匹配id数组元素的确切用例,但如果您知道预期的当前值可能会很有用。

回答by Rob Watts

I just ran into this problem myself. I wasn't able to find a one-call solution, but I found a two-call solution that works when you have a unique value in your array elements. Use the $pullcommand first, which removes elements from an array, and then $push.

我自己刚刚遇到了这个问题。我无法找到单次调用的解决方案,但我找到了一种两次调用的解决方案,当您的数组元素具有唯一值时,该解决方案有效。首先使用$pull从数组中删除元素的命令,然后使用$push.

db.soup.update({
    "tester":"tom"
}, {
    $pull: {
        'array': {
            "id": "3"
        }
    }
})
db.soup.update({
    "tester":"tom"
}, {
    $push: {
        'array': {
            "id": "3",
            "letter": "d"
        }
    }
})

This should work when the document doesn't exist, when the document exists but the entry in the array doesn't exist, and when the entry exists.

这应该在文档不存在、文档存在但数组中的条目不存在以及条目存在时起作用。

Again, this only works if you have something, like the idfield in this example, that should be unique across elements of the array.

同样,这仅在您有一些东西时才有效,例如id本例中的字段,它在数组的元素中应该是唯一的。

回答by G-Wiz

You can achieve upserts of embedded document sets in some cases if you can restructure your documents to use objects instead of arrays. I just answered this on another questionbut will adapt it here for convenience.

在某些情况下,如果您可以重构文档以使用对象而不是数组,则可以实现嵌入文档集的更新插入。我刚刚在另一个问题上回答了这个问题,但为了方便起见,我会在这里进行调整。



An example document would be

一个示例文档是

{
    tester: 'tom',
    items: {
        '1': 'a',
        '2': 'b'
    }
}

To upsert an item with id3 and value 'c', you'd do

要使用id3 和值 'c'插入一个项目,你会这样做

db.coll.update(
    { tester: 'tom' }, 
    { $set: { 'items.3': 'c' } }
)

One drawback is that querying for field names (using the $existsquery operator) requires scanning. You can get around this by adding an extra array field that stores the property names. This field can be indexed and queried normally. Upserts become

一个缺点是查询字段名称(使用$exists查询运算符)需要扫描。您可以通过添加一个存储属性名称的额外数组字段来解决此问题。该字段可以正常索引和查询。Upsert 成为

db.coll.update(
    { tester: 'tom' }, 
    { 
        $set: { 'items.3': 'c' },
        $addToSet: { itemNames: 3 }
    }
)

(Keep in mind $addToSetis O(n).) When removing a property, you have to pull it from the array as well.

(记住$addToSet是 O(n)。)当删除一个属性时,你也必须将它从数组中拉出来。

db.widgets.update(
    { tester: 'tom' }, 
    { 
        $unset: { 'items.3': true },
        $pull: { itemNames: 3 }
    }
)

回答by Shan

Hey You can do by using array filters option. You can refer here https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-arrayfilters.

嘿,您可以使用数组过滤器选项来完成。您可以在此处参考 https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-arrayfilters

   db.getCollection('soup').update({'tester':tom}, { $set: { "collection.$[element].letter" : 'c' } },
   {
     arrayFilters: [ { "element.id": 2 } ]
   })

回答by lukas_o

The question is from 2012. I had a look into the mongo documentation: https://docs.mongodb.com/manual/reference/method/Bulk.find.upsertwhich Rob Watts mentioned in a comment, but it is very sparse.

问题来自 2012 年。我查看了 mongo 文档:https: //docs.mongodb.com/manual/reference/method/Bulk.find.upsert,Rob Watts 在评论中提到,但它非常稀疏。

I found an answer here: https://stackoverflow.com/a/42952359/1374488

我在这里找到了答案:https: //stackoverflow.com/a/42952359/1374488