mongo架构设计 - 组合$或和sort的错误

时间:2013-07-19 18:17:34

标签: mongodb sorting indexing database-schema

实施社交游戏,其中每个个人资料可能会对其他个人资料提出许多挑战 每个挑战只有两个相关的配置文件,称为对手

在我目前的架构设计中,我有挑战集合,每个文档看起来都像......

{
"_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"
}

对谁来说,挑战是无国籍的,这意味着opponent1和opponent2将获得相同的文件。

当我想要检索特定的配置文件时,我使用 $或运算符

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

我有嵌套索引,如下所示

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

事情是有一个开放的错误https://jira.mongodb.org/browse/SERVER-1205
这阻止了上述查询使用索引(因为$或和sort的组合)和查询非常慢。

是否有办法在保留当前架构时不使用$或运算符并使上述查询运行得更快?

所有这些问题让我想到我是否应该添加新的集合(让我们称之为 challenge_rel ),这会将每个配置文件与他的挑战联系起来(将挑战集合规范化一点)但似乎没有 - mongo方法不是吗?是否有更好的架构设计满足我的谦逊需求?

非常感谢您的回答!

1 个答案:

答案 0 :(得分:1)

预计将在MongoDB 2.5.x(2.6发行版)中修复

https://jira.mongodb.org/browse/SERVER-1205https://jira.mongodb.org/browse/SERVER-3071。这应该直接帮助你。与此同时,如果您可以修改架构以将对手存储为数组,则可以将其作为索引查询执行。 我将上面的文档修改为

{
        "_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"
        }
        ]
}

我还用_id 3和4存储了2个其他文档,其中我更改了元素中的pid(以证明它实际上是或者)。 现在查询使用索引

> 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"
}