gpt4 book ai didi

node.js - 为什么 mongodb 中的 addToSet 在数组字段中不起作用?

转载 作者:太空宇宙 更新时间:2023-11-03 23:51:37 24 4
gpt4 key购买 nike

集合中的文档有一个子文档的数组字段,每个子文档都有一个计数器,该计数器应增加到三个,但如果数组没有具有给定键的子文档,则应使用以下命令创建它默认值。

$addToSet 的文档说:

Behavior

$addToSet only ensures that there are no duplicate items added to the set and does not affect existing duplicate elements. $addToSet does not guarantee a particular ordering of elements in the modified set.

Missing Field

If you use $addToSet on a field is absent in the document to update, $addToSet creates the array field with the specified value as its element.

问题是,如果数组字段不存在,则不会在文档中创建它,如文档中所述。

这是我当前用来完成操作的:

// increase counter in element of array if element exist and counter is less than 3
collection.updateOne({
key_1,
"array.key_2": key_2,
"array.counter": {$lt: 3}
}, {
$inc: {"array.$.counter": 1}
})
.then(res => {
console.log("!!!!1:", res.modifiedCount, res.upsertedId, res.upsertedCount, res.matchedCount);

if (res.matchedCount) return res.matchedCount;

// create element in array with the default values,
// also create the array field if it doesn't exist
collection.updateOne({
key_1
}, {
$addToSet: {
array: {key_2, counter: 1}
}
})
.then(res => {
console.log("!!!!2:", res.modifiedCount, res.upsertedId, res.upsertedCount, res.matchedCount);
return res.matchedCount;
})
.catch(e => console.log(e))
})
.catch(e => console.log(e))


在第二个查询中使用 upsert ,如果数组字段不存在,它会创建它,但是当 array.counter 在后续调用中达到 3 以增加其值时,该操作在数组中创建一个新的子文档,其 array.key_2array.date 具有相同的值,尽管使用 array.counter 但可以有效地复制条目code> 设置为 1 而不是 3。

我使用的是 mongo 版本 4.2.1

更新:

下面是尝试对第二个子文档运行操作之前的示例文档:

{
"key_1": 1,
"array": [
{
"key_2": 1,
"counter" 1
}, {
"key_2": 2,
"counter" 3
}
]
}

这是我使用 upsert 时得到的结果:

{
"key_1": 1,
"array": [
{
"key_2": 1,
"counter" 1
}, {
"key_2": 2,
"counter" 3
}, {
"key_2": 2,
"counter" 1
}
]
}


该操作正在复制数组中的第二个子文档,但如果未使用 upsert ,则不会创建数组字段(如果该字段尚未在父文档中),这与 的预期行为相反>$addToSet 来自文档中的内容。

更新2

以下是重现该问题的步骤:

在将 key_1 设置为 1 并禁用 upsert 的情况下运行该操作。所有查询均不会修改文档。未创建 array 字段。

{
"key_1": 1
}

启用upsert并再次运行该操作。 array 字段在第二个查询中创建:

{
"key_1": 1,
"array": [
{
"key_2": 1,
"counter" 1
}
]
}

再次运行该操作两次。第一个查询修改文档两次:

{
"key_1": 1,
"array": [
{
"key_2": 1,
"counter" 3
}
]
}

再次运行该操作。第一个查询不会修改文档。第二个查询创建一个重复项:

{
"key_1": 1,
"array": [
{
"key_2": 1,
"counter" 3
}, {
"key_2": 1,
"counter" 1
}
]
}

最佳答案

请尝试这个:

var key_2Value = 2;

var firstFilterQuery = {
key_1: 1,
array: {
$elemMatch: {
"key_2": key_2Value,
"date": 'someDate',
"conter": { $lte: 3 }
}
}
}

var secondFilterQuery = {
key_1: 1,
"array.key_2": {$ne: key_2Value}
}

var defaultDoc = {key_2 : key_2Value, "date": 'someDefaultDate',counter: 1}

查询:

collection.bulkWrite([
{
updateOne:
{
"filter": firstFilterQuery,
"update": { $inc: { "array.$.conter": 1 } }
}
}, {
updateOne:
{
"filter": secondFilterQuery,
"update": { $push: { array: defaultDoc }
}
}
}
])

通过上述查询,您可以在一次数据库调用中实现您想要的目标(在任何给定情况下,只有一个“updateOne”应该更新数据库),输出应类似于:

{
"acknowledged" : true,
"deletedCount" : 0.0,
"insertedCount" : 0.0,
"matchedCount" : 1.0,
"upsertedCount" : 0.0,
"insertedIds" : {},
"upsertedIds" : {}
}

关于node.js - 为什么 mongodb 中的 addToSet 在数组字段中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59216674/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com