按标签搜索效率如何?

时间:2017-08-14 06:32:32

标签: mongoose

情况:

我有100万用户,我想通过标签搜索它们。

以下是架构:

const Account = new Schema({
  tags: { type: [String], default: ['cats'] }
})

这是第一个查询:

const query = { tags: 'cats'}
const fields = { _id: 0 }
const options = { skip: 0, limit: 5 }

Account.find(query, fields, options)

调用find方法Mongoose后,将开始搜索并返回它匹配的前5个条目。在这种情况下的表现是最佳的。

这是第二个查询:

const query = { tags: 'cats'}
const fields = { _id: 0 }
const options = { skip: 500 000, limit: 5 }

Account.find(query, fields, options)

在这种情况下发生的事情对我很感兴趣。

Mongoose首先匹配500 000个条目然后返回接下来的5个条目吗?

或者以某种方式跳过'跳跃'到500 000元素而不必事先将它们全部匹配?

我试图了解这个过程的效率如何以及我是否可以某种方式改进它。你有什么建议吗?

2 个答案:

答案 0 :(得分:2)

有趣。我的理解是Find这里的查询功能与Select非常相似,其中在跳过它们之前首先通过500,000个值会效率低下。

因此,我建议实现一种称为多级索引的东西。基本上创建嵌套索引系统虽然占用数据空间,但非常有效,特别是对于您不希望直接实现树的顺序搜索实践。在移动到存储的数据块之前,创建一组更通用的外部索引,然后分别将它们链接到内部索引。

实现这一点应该不会太困难,并且应该大大改善遍历的数量。希望这会有所帮助。

答案 1 :(得分:2)

是的,它首先匹配500,000个条目。

来自MongoDB权威指南第2版:

  

$ skip接受一个数字n,并从结果集中丢弃前n个文档。与“普通”查询一样,对于大型跳过效率不高,因为它必须找到必须跳过的所有匹配项,然后将其丢弃。

您可以使用explain():

从Mongo shell详细检查您的查询

https://docs.mongodb.com/manual/reference/method/cursor.explain/

例如:

// Create a dummy collection
var tagTypes = ['cats', 'dogs', 'chickens']
    for (i=0; i < 1000; i++) {
        let tag = tagTypes[Math.floor(Math.random()*tagTypes.length)]
        db.people.insert({"tags" : [tag]})
    }
然后解释一下

db.people.find({"tags" : "cats"}).skip(100).limit(10).explain("executionStats”)

totalDocsExamined向您显示它正在匹配正在跳过的所有内容

"executionStats" : {
...
    "totalDocsExamined" : 420

如果要在标签上创建索引:

db.people.ensureIndex({ "tags" : 1 })

再次运行它你会得到:

"executionStats" : {
...
    "totalDocsExamined" : 110