Pip*_*ipe 6 javascript mongodb mongodb-query node-mongodb-native
我正在尝试使用"findAndModify"来实现"getOrCreate"行为.我正在使用本机驱动程序在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
});
Run Code Online (Sandbox Code Playgroud)
我想要做的是:"找到与指定用户,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 }
Run Code Online (Sandbox Code Playgroud)
有没有办法让它发挥作用?不可能?
谢谢 :)
这不是处理此问题的“最漂亮”方法,但当前对选择运算符的限制意味着您需要将 JavaScript 表达式与$where
.
为了方便示例,将您的变量替换为值:
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
}
);
Run Code Online (Sandbox Code Playgroud)
正如您可能怀疑的那样,这里的“罪魁祸首”是位置$
运算符,即使您的操作没有使用它。
问题的具体原因$all
是在数组中的“两个”位置寻找可能的匹配。如果需要“位置”操作员,引擎(目前)无法计算出要呈现的位置。该位置可以说应该是与其他操作一致的“第一”匹配,但目前并没有这样工作。
用 JavaScript 表达式替换逻辑可以避免这个问题,因为 JavaScript 逻辑无论如何都无法返回匹配的位置。这使得表达式有效,然后您可以在新文档中“创建”并使用这两个元素进行数组,或者检索包含“这两个”这些元素以及其他查询条件的文档。
PS 有点担心你在这里的“排序”。您可能已经添加了它,因为它是该方法的“强制”,但是,如果您确实可能希望它与“多个”文档匹配,并且需要“排序”来找出要获取的文档,那么您的逻辑就略有缺陷。
当执行此操作“查找或创建”时,您确实需要在查询中指定“所有”“唯一”键约束。如果不这样做,那么您很可能会遇到重复的按键错误。
如果您实际上不需要从多个结果中“挑选”一个结果,那么 Sort 实际上可以是一个空数组。
只是要记住一些事情。
归档时间: |
|
查看次数: |
777 次 |
最近记录: |