Mongodb - 多文本索引:索引键模式太大错误代码67

时间:2014-08-16 01:23:23

标签: mongodb indexing mongodb-query nosql

我有以下Mongodb数据库结构:

{ 
    "_id" : "519817e508a16b447c00020e", 
    "keyword" : "Just an example query", 
    "rankings" : 
    {
        results:
        {
            "1" : { "domain" : "example1.com", "href" : "http://www.example1.com/"},
            "2" : { "domain" : "example2.com", "href" : "http://www.example2.com/"},
            "3" : { "domain" : "example3.com", "href" : "http://www.example3.com/"},
            "4" : { "domain" : "example4.com", "href" : "http://www.example4.com/"},
            "5" : { "domain" : "example5.com", "href" : "http://www.example5.com/"},
            ...
            ...
            "99" : { "domain" : "example99.com", "href" : "http://www.example99.com/"}
            "100" : {"domain" : "example100.com", "href" : "http://www.example100.com/"}
        }, 
        "plus":"many", 
        "other":"not", 
        "interesting" : "stuff", 
        "for": "this question"
    }
}

In a previous question,我问如何索引文本,以便我可以搜索关键字和域名,例如:

db.ranking.find({ $text: { $search: "\"example9.com\" \"Just an example query\""}})  

John Petrone的精彩回答是:

db.ranking.ensureIndex(
{
    "keyword": "text",
    "rankings.results.1.domain" : "text",
    "rankings.results.2.domain" : "text",
    ...
    ...
    "rankings.results.99.domain" : "text",
    "rankings.results.100.domain" : "text"
}

然而,如果当我得到10个结果时效果很好,我会遇到一个太大的"索引键模式"当我尝试索引100个结果时,来自Mongo shell的代码67出错。

所以最大的问题是:

如何(地狱)我可以解决那个"索引键模式太大"错误?


编辑:2014年8月18日 文件结构澄清

{ 
    "_id" : "519817e508a16b447c00020e", #From Mongodb
    "keyword" : "Just an example query", 
    "date" : "2014-03-28"
    "rankings" :
    {
            "1" : { "domain" : "example1.com", "href" : "http://www.example1.com/", "plus" : "stuff1"},
            ...
            "100" : {"domain" : "example100.com", "href" : "http://www.example100.com/"plus" : "stuff100"}"}
    }, 
    "plus":"many", 
    "other":"not", 
    "interesting" : "stuff", 
    "for": "this question"
}

2 个答案:

答案 0 :(得分:1)

建议的结构存在问题:

{
 keyword" : "Just an example query", 
 "rankings" :
    [{"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
     ...{ "rank" : 99, "domain" : "example99.com", "href" : "example99.com“}
 ]}
}

虽然你现在可以做到

db.ranking.ensureIndex({"rankings.href":"text", "rankings.domain":"text"}) 

然后运行以下查询:

db.ranking.find({$text:{$search:"example1"}});

这将返回匹配数组元素的整个数组文档。

您可能需要考虑引用,以便每个排名结果都是一个单独的文档,并引用关键字和其他元数据,以避免重复大量信息。

因此,您有一个关键字/元数据文档,如:

{_id:1, "keyword":"example query", "querydate": date, "other stuff":"other meta data"},
{_id:2, "keyword":"example query 2", "querydate": date, "other stuff":"other meta data 2"}

然后是结果文件,如:

{keyword_id:1, {"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
... keyword_id:1, {"rank" : 99, "domain" : "example99.com", "href" : "example99.com"},
 keyword_id:2, {"rank" : 1, "domain" : "example1.com", "href" : "example1.com"},
 ...keyword_id:2, {"rank" : 99, "domain" : "example99.com", "href" : "example99.com"}}

其中keyword_id链接回(引用)关键字/元数据表 - 显然,实际上,_ids看起来像“_id”:“519817e508a16b447c00020e”,但这只是为了便于阅读。您现在可以一起或单独索引keyword_id,domain和href,具体取决于您的查询类型,并且您将无法获得index key pattern too large error并且您将只获得一个匹配的文档而不是返回整个数组。

我不清楚你需要模糊/正则表达式搜索的位置,以及你是在搜索元数据还是只搜索href和域名,但我认为这种结构应该是一种更清晰的方式来开始考虑索引,而不是最大化在索引上,和以前一样。它还允许您将正常索引上的查找与文本索引组合在一起,具体取决于您的查询模式。

在考虑您的文件结构时,您可能会发现这个答案MongoDB relationships: embed or reference?很有用。

答案 1 :(得分:1)

那么,这是我的解决方案: 我决定坚持使用一个过于简单的修改嵌入式文档:用包含等级的数组替换包含实际等级的字典键,并且就是这样:

{ 
  "_id" : "519817e508a16b447c00020e", #From Mongodb
  "keyword" : "Just an example query", 
  "date" : "2014-03-28"
  "rankings" :
  [
    { 
      "domain" : "example1.com", "href" : "http://www.example1.com/", "plus" : "stuff1", "rank" : 1
    },
    ...
    {
      "domain" : "example100.com", "href" : "http://www.example100.com/"plus" : "stuff100", "rank" : 100
    }
  ]
  "plus":"many", 
  "more":"uninteresting", 
  "stuff" : "for", 
  "this": "question"
}

然后,我可以使用例如:

选择整个文档
> db.ranking.find({"keyword":"how are you doing", "rank_date" : "2014-08-27”)

或者通过使用Mongodb 2.6中的精彩投影和新功能获得单个结果:-D

> db.collection.find({ "rank_date" : "2014-04-09", "rankings.href": "http://www.example100.com/" }, { "rankings.$": 1 })

  [
    { 
      "domain" : "example100.com", "href" : "http://www.example100.com/", "plus" : "stuff100", "rank" : 100
    },
  ]

甚至直接获得一个网址排名:

> db.collection.find({"rank_date" : "2014-04-09", "rankings.href": "http://www.example5.com/"}, { "rankings.$": 1 })[0]['rankings'][0]['rank']
5

最后,我还在创建一个基于url的索引:

> db.collection.ensureIndex( {"rankings.href" : "text"} )

使用索引,我可以搜索单个网址,部分网址,子网域或整个域名,这样就很棒了:

> db.collection.find({ $text: { $search: "example5.com"}})

这就是它!非常感谢大家的帮助,特别是@JohnBarça:-D