[英]How to get the index of an array element in older versions on Mongodb?
我正在使用 Mongo 版本 2.2.33。 这是一个大型项目,主要是遗留代码,更新内容不取决于我。 如果我有一个更新版本的 Mongo,我会使用 $indexOfArray,但既然我不能,我怎么能达到同样的目的呢?
这是我在意识到我们使用的是哪个版本的 mongo 之前编写的代码:
exports.getActionHistoryIndex = function (historyArray, deviceId, cb) {
db.actions.aggregate({$indexOfArray: {historyArray, deviceId}}, function (err, index) {
if (err) {
return cb(err)
} else {
return cb(null, index)
}
})
}
当我调用该函数时,如下所示:
actionRepo.getActionHistoryIndex(action.history, device._id, (err, res) => {
if (err) console.log(err)
console.log(res)
})
我收到此错误,因为 $indexOfArray 在 3.8 之后可用,我认为:
name: 'MongoError',
message: 'Unrecognized pipeline stage name: \'$indexOfArray\'',
ok: 0,
errmsg: 'Unrecognized pipeline stage name: \'$indexOfArray\'',
code: 40324,
codeName: 'Location40324' }
undefined
有没有一种简单的方法来实现这一目标? 基本上,问题是我有一个 db 集合,其中包含一个包含对象的数组。 我需要能够在数组中的对象中搜索某个_id
,然后编辑同一对象中的另一个属性。 所以我的计划是获取正确对象的索引,然后使用索引更新需要更改的属性。
任何帮助表示赞赏。
编辑:这是来自action
集合的示例文档。
_id : ObjectId('ABC')
history: [Array]
0: {Object}
device_id: ObjectId("123")
triggered: false
1: {Object}
device_id: ObjectId("456")
triggered: true
收到用户输入后,我需要更改triggered
布尔值。 我有操作文档 ObjectId,我有对应于history
数组中不同对象的 device_id。 所以我正在寻找一个查询/更新,它将允许我更改triggered
布尔值。
EDIT2:这是我阅读答案后的功能:
exports.updateHistory = function (action, deviceId, triggered, cb) {
console.log(action._id + ' || action._id')
console.log(deviceId + ' || deviceId')
console.log(triggered + ' || triggered')
db.actions.updateOne(
{_id: action._id, 'history.device_id': deviceId},
{$set: { 'history.$.triggered': triggered }},
{w: 1},
function (err, results) {
if (err) {
return cb(err)
}
return cb(null, results)
})
}
所有日志语句都是正确的,我没有收到任何错误,但我的文档根本没有更改。 对于三个不同的action
文档,此函数被调用 3 次。 所有 3 的triggered
值当前为 false。 此函数运行时,传入的triggered
值为true
,但不会更新文档。 有什么建议?
实际上,您以错误的方式处理问题。 数组本质上是动态的。 如果您的应用程序是实时的并且正在发生交互,那么当您从查询中获取它时,无法保证您正在更新的索引将完全相同。因为有些人可能已经插入或从中删除了文档。
至于你的问题,你可以这样做:
db.collection.update({"_id" : <parent_id>, "history.device_id" : "<you-passed-device-id>"},
{$set : {history.$.triggered: false} },
false ,
true);
不确定您的 mongo 服务器版本中是否引入了https://docs.mongodb.com/manual/reference/operator/update/positional/ 。
这样您就不会依赖于索引并直接更新您需要的对象。
请尝试 :
db.yourCollectionName.updateOne({"_id" : ObjectId('ABC'),
'history.device_id':ObjectId("123")}, { $set: { "history.$.triggered" : false } })
从上面我们使用.updateOne()
因为我们只是通过传递唯一的_id :ObjectId('ABC')
更新特定对象。 传递这个也有利于使用索引键匹配准确的一个文档,并且它确保您实际上正在更改正确的动作文档 - 以防万一相同的device_id
存在于多个动作文档的历史数组中!! $
运算符实际上将更新传入过滤器的数组中的第一个匹配对象/元素,否则如果您需要修改与过滤器查询匹配的所有元素,那么您可以在 >=3.6 版本上尝试$[]
。
参考: mongoDB $(更新)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.