1

我有一个包含大约 5 亿个文档的集合,其中似乎没有对其中的特定子集强制执行唯一性约束。唯一性约束适用于复合索引。

此集合的索引:

db.elements.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.elements"
        },
        {
                "v" : 1,
                "key" : {
                        "sessionId" : 1
                },
                "name" : "sessionId_1",
                "ns" : "test.elements"
        },
        {
                "v" : 1,
                "key" : {
                        "sessionId" : 1,
                        "modelFolder" : 1,
                        "modelName" : 1
                },
                "name" : "sessionId_1_modelFolder_1_modelName_1",
                "ns" : "test.elements",
                "options" : {
                        "unique" : true
                }
        },
        {
                "v" : 1,
                "key" : {
                        "id" : 1
                },
                "name" : "id_1",
                "ns" : "test.elements",
                "options" : {
                        "unique" : false
                }
        },
        {
                "v" : 1,
                "key" : {
                        "uniqueId" : 1
                },
                "name" : "uniqueId_1",
                "ns" : "test.elements"
        }
]

当我运行以下查询时,尽管在索引“sessionId_1_modelFolder_1_modelName_1”的复合索引字段上进行了查询匹配,但我得到了重复(由于 IP 问题而编辑了特定字段值):

var gs = (
    db
    .elements
    .aggregate(
        [
          {
            $match : {
              "sessionId" : (specific sessionId value),
              "modelName" : (specific modelName value),
              "modelFolder" : (specific modelFolder value)
            }
          },
          {
            $group : {
              _id : "$id",
              total : { $sum : 1 }
            }
          }
        ]  
      )
  );

gs.forEach(
    function(g) { printjson(g); }
  );

输出的子集:

{ "_id" : 1394912, "total" : 2 }
{ "_id" : 1394916, "total" : 2 }
{ "_id" : 1394914, "total" : 2 }
{ "_id" : 1394909, "total" : 2 }
{ "_id" : 1394877, "total" : 2 }
{ "_id" : 1394908, "total" : 2 }
{ "_id" : 1394900, "total" : 2 }
{ "_id" : 1394906, "total" : 2 }
{ "_id" : 1394907, "total" : 2 }
{ "_id" : 1394876, "total" : 2 }
{ "_id" : 1394904, "total" : 2 }
{ "_id" : 1394902, "total" : 2 }
{ "_id" : 1394903, "total" : 2 }
{ "_id" : 1394881, "total" : 2 }
{ "_id" : 1394859, "total" : 2 }
{ "_id" : 1394901, "total" : 2 }
{ "_id" : 1394878, "total" : 2 }
{ "_id" : 1394880, "total" : 2 }
{ "_id" : 1394857, "total" : 2 }
{ "_id" : 1394875, "total" : 2 }

我已经杀死了这个文档子集的批量插入,然后稍后重新批量插入它们,但我很惊讶这以某种方式允许重复。我是疯了还是在某些条件下这可能?

4

1 回答 1

0

_id 对于 mongodb 中的集合是唯一的。

如果我们在分片环境中,可能会出现重复的 id。

为了避免重复,使用 {unique: true} 选项来确保底层索引强制唯一性,只要唯一索引是分片键的前缀。

如果不使用“unique: true”选项,则分片键不必是唯一的。

参考:

https://docs.mongodb.com/manual/sharding/

_id 上的重复文档(在 mongo 中)

阅读这篇文章以获取有关跨不同集合的重复 _id 的更多信息

于 2016-11-01T09:27:02.550 回答