我在分析文字。那些文本有注释(例如“章节”,“风景”,......)。这些注释在我的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 1
,chapter 2
和scenery forest
。
挑战3 :与挑战2 相比我只想匹配查询范围完全覆盖的那些注释。例如,查询9800 to 30000
字符只应返回文档chapter 2
。
对于挑战1 ,我尝试使用$lt
和$gt
。 e.g:
db.annotations.find({start: {$lt: 1234}, stop: {$gt: 1234}});
但我意识到,只使用了密钥start
的索引,即使我有start
和stop
的复合索引。有没有办法为我提到的三个问题创建更多适当的索引?
我很快就想到了地理空间索引,但我还没有使用它们。我也只需要它的一维版本。
答案 0 :(得分:3)
对于挑战1 ,您使用的查询是合适的,但您可能希望$lte
和$gte
包含在内。
db.annotations.find({ "start": { "$lt": 1234 }, "stop": { "$gt": 1234 }});
关于索引,它选择使用start
上的索引而不是复合索引的原因与复合索引的树结构有关,Rob Moore在this answer中很好地解释了这一点。请注意,如果您使用hint()
,它仍然可以使用复合索引,但查询优化器会更快地使用start
上的索引,然后清除与该范围不匹配的结果stop
条款。
对于挑战2 ,您只需要使用明确的$or
子句来涵盖stop
在start
范围内start
范围内的情况边界以及stop
和db.annotations.find({
"$or": [
{ "stop": { "$gte": 9800, "$lte": 10101 }},
{ "start": { "$gte": 9800, "$lte": 10101 }},
{ "start": { "$lt": 9800 }, "stop": { "$gt": 10101 }}
]
});
何时包含边界。
db.annotations.find({ "start": { "$gte": 9800 }, "stop": { "$lte": 30000 }});
对于挑战3 ,您可以使用与挑战1 中的查询非常类似的查询,但确保文档完全由给定范围覆盖。
{{1}}