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

Cannot infer query fields to set error on insert

我正在尝试使用 "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
    });

我想做的是: "Find specific match with specified users, lang and category... if not found, insert a new one with specified data"

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 }

有没有办法让它工作? 不可能?

谢谢:)

这不是处理此问题的 "prettiest" 方法,但当前对选择运算符的限制意味着您需要使用带有 $where.

的 JavaScript 表达式

为便于示例,用您的变量替换值:

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
    }
);

您可能会怀疑,这里的 "culprit" 是 positional $ operator,即使您的操作没有使用它。

这个问题具体是因为 $all 正在寻找数组中 "two" 位置的可能匹配项。如果需要 "positional" 运算符,引擎无法计算出(目前)显示哪个位置。该位置可以说是 "first" 与其他操作一致的匹配,但它目前不是这样工作的。

用 JavaScript 表达式替换逻辑可以避免这种情况,因为 JavaScript 逻辑无论如何都不能 return 匹配的位置。这使得表达式有效,然后您可以 "create" 和新文档中包含这两个元素的数组,或者检索包含 "both" 这些元素以及其他查询条件的文档。


P.S有点担心你的"sort"。您可能已经添加了它,因为它是 "mandatory" 到方法中,但是如果您确实希望它与 "more than one" 文档匹配并且需要 "sort" 来确定要获取哪个,那么您的逻辑是有点瑕疵。

当对 "find or create" 执行此操作时,您确实 需要 在查询中指定 "all" 的 "unique" 键约束。如果你不这样做,那么你很可能 运行 进入重复键错误。

如果您实际上不需要 "pick" 来自多个的结果,那么排序实际上可以是一个空数组。

只是要记住一些事情。