【问题标题】:MongoDB project updated record in a nested array in "findAndModify" queryMongoDB 项目在“findAndModify”查询中更新了嵌套数组中的记录
【发布时间】:2015-11-25 21:06:43
【问题描述】:

我正在尝试在嵌套数组中查找记录,对其进行修改,然后进行投影。

假设我有以下收藏:

{
    "_id" : ObjectId("56558dfc45a06f51decb4ab7"),
    "arr" : [ 
        {
            "cond" : 1.0000000000000000,
            "upd" : 2.0000000000000000
        }, 
        {
            "cond" : 2.0000000000000000,
            "upd" : 3.0000000000000000
        }, 
        {
            "cond" : 4.0000000000000000,
            "upd" : 5.0000000000000000
        }, 
        {
            "cond" : 6.0000000000000000,
            "upd" : 7.0000000000000000
        }, 
        {
            "cond" : 8.0000000000000000,
            "upd" : 9.0000000000000000
        }
    ]
}

我想找到“cond=4”所在的记录,更新为“upd=55”并返回记录。

我尝试了以下查询:

db.tests.findAndModify({
    query:{
        "arr": {"$elemMatch": {"cond":4}}
    },
    update: {
        "$set": {"arr.$": {"cond": 4, "upd": 55, "new": true}}
    },
    fields: {"arr.$":1}
})

它很好地执行了更新,但我收到以下结果:

{
    "_id" : ObjectId("56558dfc45a06f51decb4ab7"),
    "arr" : [ 
        {}, 
        {}, 
        {}, 
        {}, 
        {}
    ]
}

*我使用的是 MongoDB 版本:3.0.7

【问题讨论】:

  • 随着更新“upd”:55,您正在添加新字段“new”:true。对吗?

标签: mongodb


【解决方案1】:

您还可以尝试将 positional $ 运算符与 findAndModify() 方法一起使用。运算符将标识要更新的数组中的元素,而无需明确指定该元素在数组中的位置。请注意,数组字段必须作为查询文档的一部分出现,并且要返回对更新所做的修改的文档,请使用新选项,这样您的更新就会像

db.tests.findAndModify({
    query: {
        "arr.cond": 4
    },
    update: {
        "$set": {"arr.$.upd": 55 }
    },
    new : true,
    fields: { "arr": 1, "_id": 0 }   
})

将产生输出:

{
    "arr": [
        {
            "cond" : 1,
            "upd" : 2
        },
        {
            "cond" : 2,
            "upd" : 3
        },
        {
            "cond" : 4,
            "upd" : 55
        },
        {
            "cond" : 6,
            "upd" : 7
        },
        {
            "cond" : 8,
            "upd" : 9
        }
    ]
}

由于要返回更新后的文档,带有位置的$ projection操作符只能用在find()方法或findOne()方法的投影文档中,所以findAndModify()field 选项不会使用 $ projection 运算符投影数组的该部分。

一种解决方法是在返回的 arr 字段上使用原生 JavaScript filter() 方法

var result = db.tests.findAndModify({
    query: {
        "arr.cond": 4
    },
    update: {
        "$set": {"arr.$.upd": 55 }
    },
    new : true,
    fields: { "arr": 1, "_id": 0 }   
})

var updated = []
if (result && result.arr) updated = result.arr.filter(function (item) { return item.cond == 4; });
printjson(updated);

这将打印出来

[ { "cond" : 4, "upd" : 55 } ]

-- 更新--

或者您在下面的 cmets 中建议的 $elemMatch 投影:

var result = db.tests.findAndModify({
    query: {
        "arr.cond": 4
    },
    update: {
        "$set": {"arr.$.upd": 55 }
    },
    new : true,
    fields: {"arr": {"$elemMatch": { "cond": 4 } }, "_id": 0 }   
})

printjson(result);

输出

{ "arr" : [ { "cond" : 4, "upd" : 55 } ] }

【讨论】:

  • 在这种情况下,我可以使用:fields: {"arr": {"$elemMatch": {"cond":4}}}。但这意味着 mongo 引擎将执行另一个过滤器,而不是使用它拥有的索引。
  • @skme 虽然不太确定 mongo 是否使用 $elemMatch 投影执行另一个过滤器,但这个电话很好。
  • 如果有人想将某些嵌套字段更新为单个值,这似乎是一个过于具体的解决方案。但是如何更新嵌套在数组中的整个对象呢?
猜你喜欢
  • 2020-10-22
  • 2016-09-13
  • 2011-07-12
  • 2015-08-13
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多