我试图实现" getOrCreate"使用" findAndModify"的行为。 我使用本机驱动程序在nodejs中工作。
我有:
var matches = db.collection("matches");
matches.findAndModify({
//query
users: {
$all: [ userA_id, userB_id ]
},
lang: lang,
category_id: category_id
},
[[ "_id", "asc"]], //order
{
$setOnInsert: {
users: [userA_id, userB_id],
category_id: category_id,
lang: lang,
status: 0
}
},
{
new:true,
upsert:true
}, function(err, doc){
//Do something with doc
});
我想做的是: "查找与指定用户,lang和类别的特定匹配...如果找不到,请插入具有指定数据的新用户"
Mongo抛出了这个错误:
Error getting/creating match { [MongoError: exception: cannot infer query fields to set, path 'users' is matched twice]
name: 'MongoError',
message: 'exception: cannot infer query fields to set, path \'users\' is matched twice',
errmsg: 'exception: cannot infer query fields to set, path \'users\' is matched twice',
code: 54,
ok: 0 }
有没有办法让它发挥作用? 这不可能吗?
谢谢:)
答案 0 :(得分:2)
处理此问题并不是“最漂亮”的方法,但目前对选择运算符的限制意味着您需要使用$where
的JavaScript表达式。
为了便于举例,用你的vars代替值:
matches.findAndModify(
{
"$where": function() {
var match = [1,2];
return this.users.filter(function(el) {
return match.indexOf(el) != -1;
}).length >= 2;
},
"lang": "en",
"category_id": 1
},
[],
{
"$setOnInsert": {
"users": [1,2],
"lang": "en",
"category_id": 1
}
},
{
"new": true,
"upsert": true
},
function(err,doc) {
// do something useful here
}
);
正如您可能怀疑的那样,这里的“罪魁祸首”是positional $
operator,即使您的操作没有使用它。
问题特别是因为$all
正在寻找阵列中“两个”位置的可能匹配。如果需要“位置”操作员,则发动机不能(当前)出现哪个位置。该位置应该可以说是与其他操作一致的“第一”匹配,但它目前不是那样的。
用JavaScript表达式替换逻辑会绕过这一点,因为JavaScript逻辑无论如何都无法返回匹配的位置。这使表达式有效,然后您可以使用新文档中的两个元素“创建”和数组,或者检索包含“两个”这些元素以及其他查询条件的文档。
P.S有点担心你的“排序”。您可能已添加它,因为它对方法是“强制性的”,但是如果您可能希望这与“多个”文档相匹配并需要“排序”以确定哪一个得到,那么您的逻辑就会有轻微缺陷。 / p>
执行此操作以“查找或创建”时,您确实需要在查询中指定“所有”“唯一”键约束。如果不这样做,则可能会在轨道上遇到重复的键错误。
如果你实际上不需要从许多人那里“挑选”一个结果,那么排序实际上可以是一个空数组。
要记住一些事情。