1

实施社交游戏,其中每个配置文件都可能与其他配置文件有许多挑战。
每个挑战只有两个相关的配置文件,称为对手

在我当前的模式设计中,我有挑战集合每个文档看起来像......

{
"_id" : ObjectId("51e8de5be4b0131df7db33c6"),
"state" : "ACTIVE",
"move" : "b0fe109d9663a87e8450ed1299ae8927",
"creationTime" : ISODate("2013-07-19T06:36:11.228Z"),
"lastUpdateTime" : ISODate("2013-07-19T11:18:44.856Z"),
"round" : 1,
"opponent1" : {
     "pid" : "b0fe109d9663a87e8450ed1299ae8927",
     "firstName" : "",
     "lastName" : "",
     "imageUrl" : "",
     "unique" : "",
     "gender" : "male"
},
"opponent2" : {
     "pid" : "4fc84459576623099eeb96329c1243de",
     "firstName" : "",
     "lastName" : "",
     "imageUrl" : "",
     "unique" : "",
     "gender" : "male"
}

挑战对于谁在请求它是无状态的,这意味着对手 1 和对手 2 将获得相同的文档。

当我想检索特定的配置文件挑战时,我正在使用$or运算符

Query:{ "$or" : [ { "opponent1.pid" : "profileID"} , { "opponent2.pid" : "profileID"}]}
Sort:{ "lastUpdateTime" : -1}

我有如下嵌套索引

{ "opponent1.pid":1}
{ "opponent2.pid":1}

问题是有一个开放的错误https://jira.mongodb.org/browse/SERVER-1205
阻止上述查询使用索引(因为 $or 和 sort 的组合)并且查询非常慢.

有没有办法在保留在当前模式中的同时不使用 $or 运算符并使上述查询运行得更快?

所有这些问题让我开始思考是否应该添加新的集合(我们称之为Challenges_rel),它将每个配置文件与他的挑战相关联(将挑战集合标准化一点),但看起来像 un-mongo 方法不是吗?有没有更好的架构设计来满足我的卑微需求?

非常感谢您的回答!

4

1 回答 1

1

https://jira.mongodb.org/browse/SERVER-1205https://jira.mongodb.org/browse/SERVER-3071计划在 MongoDB 2.5.x(2.6 发行版)中修复。那应该直接帮助你。同时,如果您可以修改架构以将对手存储为数组,则可以将其作为索引查询执行。我将您的文档修改为

{
        "_id" : 1,
        "state" : "ACTIVE",
        "move" : "b0fe109d9663a87e8450ed1299ae8927",
        "creationTime" : ISODate("2013-07-19T06:36:11.228Z"),
        "lastUpdateTime" : ISODate("2013-07-19T11:18:44.856Z"),
        "round" : 1,
        "opponents" : [
        {
                "pid" : "b0fe109d9663a87e8450ed1299ae8927",
                "firstName" : "",
                "lastName" : "",
                "imageUrl" : "",
                "unique" : "",
                "gender" : "male"
        },
        {
                "pid" : "4fc84459576623099eeb96329c1243de",
                "firstName" : "",
                "lastName" : "",
                "imageUrl" : "",
                "unique" : "",
                "gender" : "male"
        }
        ]
}

我还存储了另外 2 个 _id 为 3 和 4 的文档,我在其中更改了元素中的 pid(以证明它确实执行了 or)。现在查询使用索引

> db.foo.find({"opponents.pid":{$in:["b0fe109d9663a87e8450ed1299ae8927", "4fc844
59576623099eeb96329c1243de"]}}).sort({lastUpdateTime:-1}).explain()
{
        "cursor" : "BtreeCursor opponents.pid_1_lastUpdateTime_-1 multi",
        "isMultiKey" : true,
        "n" : 3,
        "nscannedObjects" : 4,
        "nscanned" : 4,
        "nscannedObjectsAllPlans" : 8,
        "nscannedAllPlans" : 8,
        "scanAndOrder" : true,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "opponents.pid" : [
                        [
                                "4fc84459576623099eeb96329c1243de",
                                "4fc84459576623099eeb96329c1243de"
                        ],
                        [
                                "b0fe109d9663a87e8450ed1299ae8927",
                                "b0fe109d9663a87e8450ed1299ae8927"
                        ]
                ],
                "lastUpdateTime" : [
                        [
                                {
                                        "$maxElement" : 1
                                },
                                {
                                        "$minElement" : 1
                                }
                        ]
                ]
        },
        "server" : "sridhar-PC:27017"
}
于 2013-07-19T22:10:03.340 回答