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

时间:2015-07-07 00:15:49

标签: javascript mongodb mongodb-query node-mongodb-native

我试图实现" 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 }

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

谢谢:)

1 个答案:

答案 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>

执行此操作以“查找或创建”时,您确实需要在查询中指定“所有”“唯一”键约束。如果不这样做,则可能会在轨道上遇到重复的键错误。

如果你实际上不需要从许多人那里“挑选”一个结果,那么排序实际上可以是一个空数组。

要记住一些事情。