Node.js mongo能否插入阵列数据?

Node.js mongo能否插入阵列数据?,node.js,mongodb,Node.js,Mongodb,我有一个像这样的mongo文档 { "_id" : ObjectId("50b429ba0e27b508d854483e"), "array" : [ { "id" : "1", "letter" : "a" }, { "id" : "2", "letter" : "b" } ], "tester" : "

我有一个像这样的mongo文档

{
    "_id" : ObjectId("50b429ba0e27b508d854483e"),
    "array" : [
        {
            "id" : "1",
            "letter" : "a"
        },
        {
            "id" : "2",
            "letter" : "b"
        }
    ],
    "tester" : "tom"
}
我希望能够使用单个mongo命令插入和更新
数组
,并且不在
find()
中使用条件,然后根据对象的存在运行
insert()
update()

id
是我想要作为选择器的项。因此,如果我使用以下内容更新阵列:

{
    "id" : "2",
    "letter" : "c"
}
我必须使用
$set
语句

db.soup.update({
    "tester":"tom",
    'array.id': '2'
}, {
    $set: {
        'array.$.letter': 'c'
    }
})
db.soup.update({
    "tester":"tom"
}, {
    $push: {
        'array': {
            "id": "3",
            "letter": "d"
        }
    }
})
如果我想在数组中插入一个新对象

{
    "id" : "3",
    "letter" : "d"
}
我必须使用
$push
语句

db.soup.update({
    "tester":"tom",
    'array.id': '2'
}, {
    $set: {
        'array.$.letter': 'c'
    }
})
db.soup.update({
    "tester":"tom"
}, {
    $push: {
        'array': {
            "id": "3",
            "letter": "d"
        }
    }
})
我需要一种数组项的upsert


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

我不知道有哪个选项会像MongoDB 2.2那样插入嵌入式阵列,因此您可能必须在应用程序代码中处理此问题

假定要将嵌入数组视为虚拟集合的类型,则可能需要考虑将数组建模为单独的集合。 您不能基于嵌入数组中的字段值执行upsert,但如果嵌入文档不存在,您可以使用它来插入该文档:

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

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

我自己也遇到了这个问题。我找不到一次调用的解决方案,但我找到了一个两次调用的解决方案,当数组元素中有一个唯一的值时,它就可以工作。首先使用
$pull
命令从数组中删除元素,然后使用
$push

db.soup.update({
    "tester":"tom"
}, {
    $pull: {
        'array': {
            "id": "3"
        }
    }
})
db.soup.update({
    "tester":"tom"
}, {
    $push: {
        'array': {
            "id": "3",
            "letter": "d"
        }
    }
})
当文档不存在时,当文档存在但数组中的条目不存在时,以及当条目存在时,这应该可以工作


同样,这只适用于在数组元素之间具有唯一性的内容(如本例中的
id
字段)的情况。

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


一个例子是

{
    tester: 'tom',
    items: {
        '1': 'a',
        '2': 'b'
    }
}
要向上插入id为
3且值为“c”的项,需要执行以下操作

db.coll.update(
    { tester: 'tom' }, 
    { $set: { 'items.3': 'c' } }
)
一个缺点是查询字段名(使用
$exists
查询运算符)需要扫描。您可以通过添加一个额外的存储属性名的数组字段来解决这个问题。此字段可以正常索引和查询。上升的部分变成

db.coll.update(
    { tester: 'tom' }, 
    { 
        $set: { 'items.3': 'c' },
        $addToSet: { itemNames: 3 }
    }
)
(请记住,
$addToSet
是O(n)。)删除属性时,还必须将其从数组中拉出

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

嘿,你可以使用数组过滤器选项。 你可以在这里查阅


问题来自2012年。我查看了mongo文档:Rob Watts在评论中提到了该文档,但它非常稀少


我在这里找到了答案:

请注意,对嵌入式文档提供某种形式的“虚拟收藏”支持是一种流行的要求。。您可以在MongoDB问题跟踪器中投票/观看。谢谢,在DocumentAddA
$exists
签入
$push
查询中使用两个字段进行搜索时,它工作得很好。因此,如果两次调用之间出现问题,它将失败。几年后,我也在寻找解决此问题的方法。有更新吗?@DauleDK快速搜索发现:你认为批量查找upsert可以在一次查询中解决此问题吗?这是可行的,但请注意,你将失去按ID索引项目的能力,因为mongo没有办法在给定子对象的所有键上创建索引。mongo仍然没有我在使用mongo的每个项目中多次遇到的基本功能,这让我感到惊讶:/这将非常有用,但在我看来,它只有在更新对象和数组过滤器中的标识符相同时才起作用,例如:
db.collection.update({'tester':'tom'},{$set:{“array.$[element].letter:“c”},{arrayFilters:[{“element.letter:”b“})
-这没有多大帮助。此外,文档中提到的
upsert
选项允许您在不匹配的情况下插入新文档,并且不向数组中添加新元素,因此这并不能解决OPs问题。