MongoDB / Mongoose索引使查询更快或更慢?

时间:2015-07-31 05:03:26

标签: node.js mongodb mongoose

我有一个这样的文章模型:

var ArticleSchema = new Schema({

    type: String
    ,title: String
    ,content: String
    ,hashtags: [String]

    ,comments: [{
        type: Schema.ObjectId
        ,ref: 'Comment'
    }]

    ,replies: [{
        type: Schema.ObjectId
        ,ref: 'Reply'
    }]

    , status: String
    ,statusMeta: {
        createdBy: {
            type: Schema.ObjectId
            ,ref: 'User'
        }
        ,createdDate: Date
        , updatedBy: {
            type: Schema.ObjectId
            ,ref: 'User'
        }
        ,updatedDate: Date

        ,deletedBy: {
            type: Schema.ObjectId,
            ref: 'User'
        }
        ,deletedDate: Date

        ,undeletedBy: {
            type: Schema.ObjectId,
            ref: 'User'
        }
        ,undeletedDate: Date

        ,bannedBy: {
            type: Schema.ObjectId,
            ref: 'User'
        }
        ,bannedDate: Date
        ,unbannedBy: {
            type: Schema.ObjectId,
            ref: 'User'
        }

        ,unbannedDate: Date
    }
}, {minimize: false})

当用户创建或修改article时,我将创建主题标签

ArticleSchema.pre('save', true, function(next, done) {
    var self = this
    if (self.isModified('content')) {
        self.hashtags = helper.listHashtagsInText(self.content)
    }
    done()
    return next()
})

例如,如果用户写"Hi, #greeting, i love #friday",我会将['greeting', 'friday']存储在主题标签列表中。

我正在考虑为主题标签创建一个索引,以便更快地对主题标签进行查询。但是从猫鼬手册中,我发现了这个:

  

当您的应用程序启动时,Mongoose会自动调用   ensureIndex用于架构中的每个已定义索引。猫鼬会打电话   依次为每个索引的ensureIndex,并在其上发出'index'事件   所有ensureIndex调用成功或存在时的模型   一个错误。虽然很适合开发,但建议使用此行为   在生产中被禁用,因为索引创建可能会导致重大问题   绩效影响。通过设置autoIndex禁用该行为   您的架构选项为false。

http://mongoosejs.com/docs/guide.html

mongoDB / Mongoose的索引更快还是更慢?

此外,即使我创建像

这样的索引
  hashtags: { type: [String], index: true }

如何在查询中使用索引?或者对于像以下的普通查询来说,它会变得更加神奇:

   Article.find({hashtags: 'friday'})

2 个答案:

答案 0 :(得分:5)

你读错了

你错误地引用了那里引用的块的意图,.ensureIndex()(现在已被弃用,但仍被mongoose代码调用)在上下文中实际执行此操作。

在mongoose中,您可以在架构或模型级别定义适合您的设计的索引。 mongoose“自动”为你做的是在每个注册的模型上连接它,然后为所提供的索引定义调用适当的.ensureIndex()方法。

这实际上是做什么的?

好吧,在大多数情况下,在您之前已启动应用程序且运行.ensureIndexes()方法之后绝对没有。这有点夸大其词,但它或多或少都是真的。

由于已在服务器集合上创建了索引定义,因此次要调用不会执行任何操作。即,它不会丢弃索引并“重新创建”。因此,一旦索引本身被创建,实际成本基本上就没有了。

创建索引

因此,由于mongoose只是标准API之上的一个层,因此createIndex()方法包含所发生情况的所有细节。

这里要考虑一些细节,例如索引构建可以在“后台”中进行,虽然这对您的应用程序的干扰较小,但它确实需要付出代价。值得注意的是,“background”生成的索引大小将大于在前台构建的索引大小,阻止其他操作。

此外,所有索引都需要付出代价,特别是在磁盘使用方面,以及在集合数据本身之外编写附加信息的额外成本。

索引的优点是“搜索”索引中包含的值比搜索整个集合并匹配可能的条件要快得多。

这些是与索引相关的基本“权衡”。

部署模式

回到文档中的quoted block,这个建议背后有一个真正的意图。

在部署模式中尤其如此,特别是数据迁移按此顺序执行操作:

  1. 将数据填充到相关集合/表格
  2. 启用与您的需求相关的集合/表数据的索引
  3. 这是因为索引创建涉及成本,并且如前所述,希望从索引构建中获得最佳大小,并避免每个文档插入也具有编写索引条目的开销。当你正在批量做这个“负载”时。

    这就是索引的用途,这些是成本和收益,并解释了mongoose文档中的信息。

    总的来说,我建议在Database Indexes上阅读它们是什么以及它们的作用。想想走进图书馆找书。入口处有一张卡片索引。你走遍图书馆找到你想要的书吗?或者你在卡片索引中查找它以找到它的位置?该索引花了一些时间来创建并保持更新,但它节省了“你”在整个图书馆走动的时间,以便你可以找到你的书。

答案 1 :(得分:2)

这可能就是你要找的东西

https://www.npmjs.com/package/mongoose-text-search