简体   繁体   English

在 MongoDB 中使用 $ 运算符更新或插入文档

[英]Update or insert document using $ operator in MongoDB

I have a database where the general form of the documents look like so我有一个数据库,其中文档的一般形式如下所示

    id: String,
    day: Number,
    counter: Number
    arrs: [{
        name: String,
        hr: Number,
        stuff: {}
    }]

So I will be creating/updating a new document for each new day and for each new hour and each name, so what I want to use is fineOneAndUpdate where I check if id is equal to an id, if the day is equal to the current day, if the hr is equal to the current hr, and if the name is equal to the object I want to update.因此,我将为每个新的一天、每个新的小时和每个名称创建/更新一个新文档,所以我要使用的是fineOneAndUpdate ,我检查 id 是否等于一个 id,如果这一天等于当前天,如果小时等于当前小时,如果名称等于 object 我想更新。 Then, I want to increment stuff which can contain wildcard keys.然后,我想增加可以包含通配符键的stuff So the query I currently have is this.所以我目前的查询是这样的。

    Site.findOneAndUpdate({id: 123456, day: 1586390400, "arrs.hr": 16, "arrs.name": "Bob"},{
        $inc: {
            counter: 1,
            "arrs.$.stuff.${wildcardname}": 1
        }
    },
    {
        upsert: true
    }, function(err, result){
        if (err) {
            console.log(err)
        }
    });
}

So, if I have an empty db I expect to have this document after the query above所以,如果我有一个空数据库,我希望在上面的查询之后有这个文档

    id: 123456,
    day: 1586390400,
    counter: 1
    arrs: [{
        name: "Bob",
        hr: 16,
        stuff: {wildcardname: 1}
    }]

So if I were to run it again (within the same day + hr + name) with a different wildcardname I would then just update the document above so it would turn into因此,如果我要使用不同的wildcardname名称再次运行它(在同一天 + hr + 名称内),我将只更新上面的文档,这样它就会变成

    id: 123456,
    day: 1586390400,
    counter: 2
    arrs: [{
        name: "Bob",
        hr: 16,
        stuff: {wildcardname: 1, wildcardname2: 1}
    }]

But I keep getting Error: The positional operator did not find the match needed from the query.但我不断收到Error: The positional operator did not find the match needed from the query. . . So after some investigating I found this in the docs所以经过一番调查后,我在文档中发现了这一点

Do not use the positional operator $ with upsert operations because inserts will use the $ as a field name in the inserted document.不要将位置运算符 $ 用于 upsert 操作,因为插入将使用 $ 作为插入文档中的字段名称。

But I'm not entirely sure how else to do this otherwise.但我不完全确定否则该怎么做。 I don't want to have to make 2 calls to check if the document exists and create it, and another to update if it does exist.我不想进行 2 次调用来检查文档是否存在并创建它,如果它确实存在则另一个来更新。

Any help will be appreciated!任何帮助将不胜感激!

The $ operator refers to the specific array element that was matched by the query. $运算符引用查询匹配的特定数组元素。 If there was no document matched, then there was no element matched, so it can't really be expected to refer to anything.如果没有匹配的文档,那么就没有匹配的元素,所以不能指望它引用任何东西。

If you are using MongoDB 4.2+ you can use the pipeline form of the update command and define a pipeline that will create the array if it doesn't exist, or find and update the element if it does.如果您使用的是 MongoDB 4.2+,您可以使用更新命令的管道形式并定义一个管道,如果它不存在则将创建数组,或者如果存在则查找并更新元素。 Upsert will pass the newly created document through the pipeline. Upsert 将通过管道传递新创建的文档。

If you are using an older version, you'll need to run it as an update without upsert, and check the number of documents matched, then insert the document separately if nothing matched.如果您使用的是旧版本,则需要在不使用 upsert 的情况下将其作为更新运行,并检查匹配的文档数量,如果没有匹配,则单独插入文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM