Mongodb 使用 $or 在分片环境中更新

Mongodb update in sharded environment using $or

我在分片环境中执行了更新,例如:

db.collection.update({$or:[{a:2,b:3},{a:3,b:2}]},{$set:{x:5}})

但我收到此错误消息:

update { q: { $or: [ {a:2,b:3},{a:3,b:2} ] }, u: {$set:{x:5}}, multi: false, upsert: false } does not contain _id or shard key for pattern { a: 1.0, b: 1.0 }

我如何使用片键上的 $or 谓词执行这种更新?

谢谢

这里的主要问题是,如果没有更新语句的 "multi" 参数,您的 $or 条件就没有多大意义。至少分片条件逻辑是这么认为的,即使您的意图是只匹配单个文档。

在与 mongos 路由器一起使用的分片管理器的 "mind" 中,期望您要么针对单个分片或键范围,要么要求访问可能的品种或碎片。

这里是actual code的处理方式供参考:

// Validate that single (non-multi) sharded updates are targeted by shard key or _id
if (!updateDoc.getMulti() && shardKey.isEmpty() && !isExactIdQuery(updateDoc.getQuery())) {
    return Status(ErrorCodes::ShardKeyNotFound,
                  stream() << "update " << updateDoc.toBSON()
                           << " does not contain _id or shard key for pattern "
                           << _manager->getShardKeyPattern().toString());
}

因此,正如您应该在 "if" 条件中清楚地看到的那样,这里的期望是查询中有 "shard key" 的定义,或者至少有一个确切的 _id 以促进精确匹配。

因此,关于使此对分片更新有效的两个规定是:

  1. 在带有查询条件的分片键中的可能值上包含一个 "range"。我不知道您的分片键,所以我无法真正提供样本。但基本上:

    { 
        "shardKey": { "$gt": minShardKey, "$lt": maxShardKey },
        "$or": [
           { "a": 2, "b": 3 },
           { "a": 3, "b": 2 }
        ]
    }
    

    作为查询条件,其中 minShardkeymaxShardKey 指的是该键在范围内(在同样假设的 "shardKey" 字段上)的最小和最大可能值为了让经理认为你真的打算搜索所有分片。

  2. 像这样在更新中包含 "multi" 选项:

     db.collection.update(
        { "$or":[
            { "a": 2, "b": 3 },
            { "a": 3, "b": 2 }
        ]},
        { "$set": { "x":5 } },
        { "multi": true }
     )
    

    这使得选择 "possibly" 匹配多个,因此无需目标分片键即可有效地搜索分片。

在任何一种情况下,您至少 "intend" 搜索分片中的条件以找到符合您给定条件的东西或 "things" 的逻辑得到满足。

作为附加说明,然后还要考虑"upsert"操作有类似的限制,一般原则是需要解决分片键,否则操作无效,因为需要指示要插入新数据的分片。