1

我正在分析文本。这些文本有注释(例如“章节”、“风景”……)。这些注释在我的 MongoDB 集合annotations中,例如

{
  start: 1,
  stop: 10000,
  type: chapter,
  details: {
    number: 1,
    title: "Where it all began"
  }
},
{
  start: 10001,
  stop: 20000,
  type: chapter,
  details: {
    number: 2,
    title: "Lovers"
  }
},
{
  start: 1,
  stop: 5000,
  type: scenery,
  details: {
    descr: "castle"
  }
},
{
  start: 5001,
  stop: 15000,
  type: scenery,
  details: {
    descr: "forest"
  }
}

挑战 1:对于文本中的给定位置,我想找到所有注释。例如查询字符1234应该告诉我,

  • 它在第一章内
  • 它发生在城堡里

挑战 2:我也喜欢查询范围。例如查询字符形式9800 to 10101应该告诉我,它触及chapter 1chapter 2并且scenery forest.

挑战 3:与挑战 2类似我只想匹配那些完全被查询范围覆盖的注释。例如查询字符形式9800 to 30000应该只返回文档chapter 2

对于挑战 1,我尝试简单地使用$ltand $gt。例如:

db.annotations.find({start: {$lt: 1234}, stop: {$gt: 1234}});

但我意识到,start即使我有 and 的复合索引,也只使用start键的索引stop。有没有办法为我提到的三个问题创建更充分的索引?

我很快想到了地理空间索引,但我还没有使用它们。我也只需要它的一维版本。

4

1 回答 1

3

对于Challenge 1,您正在使用的查询是合适的,尽管您可能希望使用$lte$gte具有包容性。

db.annotations.find({ "start": { "$lt": 1234 }, "stop": { "$gt": 1234 }});

关于索引,它选择使用索引start而不是复合索引的原因与复合索引的树结构有关,Rob Moore 在这个答案中很好地解释了这一点。请注意,如果您使用 ,它仍然可以使用复合索引hint(),但是查询优化器发现使用索引更快,然后清除与子句start范围不匹配的结果。stop

对于挑战 2,您只需要使用显式$or子句来涵盖在stop边界内、何时start在边界内以及何时startstop包含边界的情况。

db.annotations.find({
    "$or": [
        { "stop": { "$gte": 9800, "$lte": 10101 }},
        { "start": { "$gte": 9800, "$lte": 10101 }},
        { "start": { "$lt": 9800 }, "stop": { "$gt": 10101 }}
    ]
});

对于Challenge 3 ,您可以使用与Challenge 1中的查询非常相似的查询,但要确保文档完全被给定的边界所覆盖。

db.annotations.find({ "start": { "$gte": 9800 }, "stop": { "$lte": 30000 }});
于 2015-02-27T20:36:24.003 回答