mongo添加到嵌套数组如果条目不包含两个匹配的字段 [英] mongo add to nested array if entry does not contain two fields that match

查看:186
本文介绍了mongo添加到嵌套数组如果条目不包含两个匹配的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个mongo文档,其中包含一个名为history的数组:

I have a mongo document that contains an array called history:

{
    "_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
    "email" : "email@address",
    "__v" : 0,
    "history" : [ 
        {
            "name" : "Test123",
            "organisation" : "Rat",
            "field" : 4,
            "another": 3
        }
    ]
}

我要向每个历史对象添加字段或更新字段 IF 名称和组织匹配,但是如果他们不匹配,我想添加一个新对象到查询的名称和组织的数组,并在必要时将其他字段添加/更新到对象。

I want to add fields to each history object or update fields IF the name AND organisation match, however if they don't, I want to add a new object to the array with the queried name and organisation and add/update the other fields to the object when necessary.

所以:

这个查询找到一个匹配的查询:

This query, finds one that matches:

db.users.find({ 
    email:"email@address",
    $and: [
        { "history.name": "Test123", "history.organisation": "Rat"}
    ]
})

如果在数组中不存在history.name和history.organization的组合,我很难获取更新/ upsert工作。

However, I'm struggling to get the update/upsert to work IF that combination of history.name and history.organisation dont exist in the array.

我认为我需要do is a:

What I think I need to do is a :

如果这个历史记录名称不等于'Test123',并且历史记录组织不等于'Rat',那么使用这些字段向数组添加一个对象和更新查询中提供的任何其他字段。

"If this history name does not equal 'Test123' AND the history organisation does not equal 'Rat' then add an object to the array with those fields and any other field provided in the update query."

我试过:

db.users.update({ 
    email:"email@address",
    $and: [
        { "history.name": "Test123", "history.organisation": "Rat"}
    ]
}, {
    history: { name: "Test123"},
    history: { organisation: "Rat"}
}, {upsert:true})

但这给了我 E11000重复键错误index:db.users。$ email_1 dup键:{:null}

任何帮助非常感激。

感谢社区!

推荐答案

不可能用单个原子更新恐怕,做一些满足这两个条件的更新操作。

Not possible with a single atomic update I'm afraid, you would have to do a couple of update operations that satisfy both conditions.

将更新逻辑分成两个不同的更新操作,第一个需要使用位置 $ c $ c> history 数组和 $ set 更新现有字段。此操作遵循逻辑 更新字段(如果名称与组织匹配)

Break down the update logic into two distinct update operations, the first one would require using the positional $ operator to identify the element in the history array you want and the $set to update the existing fields. This operation follows the logic update fields IF the name AND organisation match

现在, findAndModify() 此操作的方法,因为它可以返回更新的文档。默认情况下,返回的文档不包括对更新所做的修改。

Now, you'd want to use the findAndModify() method for this operation since it can return the updated document. By default, the returned document does not include the modifications made on the update.

所以,装备这个武器库,你可以在下一个操作中探测你的第二个逻辑ie 如果数组中不存在history.name和history.organisation的组合,请更新 。使用这个第二个
更新操作,您需要使用

So, armed with this arsenal, you can then probe your second logic in the next operation i.e. update IF that combination of "history.name" and "history.organisation" don't exist in the array. With this second update operation, you'd need to then use the $push operator to add the elements.

例如,当我们有与现有历史数组匹配的文档时,它将只执行一次更新操作,但如果文档不匹配,则 findAndModify() 方法将返回null,在第二次更新操作中使用此逻辑将文档推送到数组:

Take for instance when we have documents that match the existing history array, it will just do a single update operation, but if the documents do not match, then the findAndModify() method will return null, use this logic in your second update operation to push the document to the array:

var doc = {
        "name": "Test123",
        "organisation": "Rat"
    }, // document to update. Note: the doc here matches the existing array
    query = { "email": "email@address" }; // query document

query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
    "query": query,
    "update": { 
        "$set": { 
            "history.$.name": doc.name,
            "history.$.organisation": doc.organisation
        }
    }
}); // return the document modified, if there's no matched document update = null

if (!update) {
    db.users.update(
        { "email": query.email },
        { "$push": { "history": doc } }
    );
}

对匹配的文档执行此操作后,查询集合将产生相同的

After this operation for documents that match, querying the collection will yield the same

db.users.find({ "email": "email@address" });

输出

{
    "_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
    "email" : "email@address",
    "__v" : 0,
    "history" : [ 
        {
            "name" : "Test123",
            "organisation" : "Rat",
            "field" : 4,
            "another" : 3
        }
    ]
}






现在考虑不匹配的文档:


Now consider documents that won't match:

var doc = {
        "name": "foo",
        "organisation": "bar"
    }, // document to update. Note: the doc here does not matches the current array
    query = { "email": "email@address" }; // query document

query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
    "query": query,
    "update": { 
        "$set": { 
            "history.$.name": doc.name,
            "history.$.organisation": doc.organisation
        }
    }
}); // return the document modified, if there's no matched document update = null

if (!update) {
    db.users.update(
        { "email": query.email },
        { "$push": { "history": doc } }
    );
}

查询此文档的此集合

db.users.find({ "email": "email@address" });

会产生


$ b

Output:

{
    "_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
    "email" : "email@address",
    "__v" : 0,
    "history" : [ 
        {
            "name" : "Test123",
            "organisation" : "Rat",
            "field" : 4,
            "another" : 3
        }, 
        {
            "name" : "foo",
            "organisation" : "bar"
        }
    ]
}

这篇关于mongo添加到嵌套数组如果条目不包含两个匹配的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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