【问题标题】:Sub Document Indexing in MongoDBMongoDB中的子文档索引
【发布时间】:2014-07-25 23:21:23
【问题描述】:

考虑 MongoDB 中代表调查响应的文档集合,其结构与此类似:

{
    _id: ...  
    surveryId: ...  
    created: ...  
    answers: {  
        "53ac9a031703670858aff600": "Yes",  
        "53b1e8961703670aa858e4ec": "18364537",  
        "53b1e8961703670aa858e4ee": "88422",  
        ...  
        "53b1e8961703670aa858e50a": NumberLong(2)  
    }  
}  

答案子文档中的每个条目代表用户对调查中单个问题的回答,调查中可能有数百个问题。此外,调查问题由用户创建,因此答案子文档的键可能因文档而异(即另一个文档可能不包含“53ac9a031703670858aff600”)。问题本身存储在单独的调查集合中。

为了能够快速检索调查回复(即显示问题 A 被回答为“是”的所有调查回复),我尝试添加以下索引:

db.responses.ensureIndex({"answers": 1})

但是,在构建此索引时,我收到错误“Btree::insert: key too large to index”,表示索引条目的总大小超过 1024 字节。

我的问题有两个:

  1. 有没有办法批量索引答案子文档,以便我可以发出类似db.responses.find({"answers.53ac9a031703670858aff600": "Yes"}) 的查询并且该查询命中索引?

  2. 如果我无法创建涵盖整个答案子文档的索引,我有哪些选择可以确保可以使用索引检索任何调查答案?我应该考虑为回复设计新的文档吗?

访问此数据的应用程序是使用官方 MongoDB 驱动程序的 .NET 应用程序。

【问题讨论】:

    标签: .net mongodb optimization indexing


    【解决方案1】:

    您正在使用 MongoDB 反模式:值键。

    不要使用值(在这种情况下是来自另一个集合的 ObjectId)作为(子)文档的键。

    1. 很难对其进行任何高级查询,因为有许多运算符可以处理值,但几乎没有一个运算符可以处理键
    2. 无法建立索引,因为您只能在已知键上创建索引。

    不要使用包含大量未知字段的对象,而是使用键值对数组:

    answers: [  
        { "question": "53ac9a031703670858aff600", "answer": "Yes" },
        { "question": "53b1e8961703670aa858e4ec", "answer": "18364537" },
        { "question": "53b1e8961703670aa858e4ee", "answer": "88422" },
        { "question": "53b1e8961703670aa858e50a", "answer": NumberLong(2) }
    ]
    

    然后,您可以在answers.question 上创建索引以快速查找任何问题,或者在两个字段上创建复合索引以快速查找特定的问题/答案组合。如果您想避免重复,请创建一个结合_idanswers.question 的唯一复合索引。

    【讨论】:

    • 对可能也在使用 .NET 驱动程序的未来查看者的说明:我们将 answers 数组建模为 Dictionary 并且能够告诉 .NET Mongo 驱动程序进行序列化使用 [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] 属性将答案字典的内容如上所示。
    猜你喜欢
    • 2018-10-27
    • 2017-01-11
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 2016-03-15
    • 2015-03-26
    • 2014-03-27
    • 1970-01-01
    相关资源
    最近更新 更多