无法推断查询字段以在插入时设置错误

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)

有没有办法让它发挥作用?不可能?

谢谢 :)

Bla*_*ven 2

这不是处理此问题的“最漂亮”方法,但当前对选择运算符的限制意味着您需要将 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 实际上可以是一个空数组。

只是要记住一些事情。