MongoDB“过滤”索引:有可能吗?

时间:2013-08-29 07:45:04

标签: mongodb indexing

是否可以为集合中的某些文档编制索引“仅当”要编入索引的字段之一具有特定值?

让我用一个例子来解释:

集合“posts”有数百万个文档,ALL定义如下:

    {
        "network": "network_1",
        "blogname": "blogname_1",
        "post_id": 1234,
        "post_slug": "abcdefg"
    }

我们假设帖子的分布在network_1和network_2

上平均分配

我的应用程序OFTEN根据“网络”的值选择查询类型(尽管有时我需要来自两个网络的数据):

例如:

www.test.it/network_1/blog_1/**postid**/1234/
 -> db.posts.find ({network: "network_1" blogname "blog_1", post_id: 1234})

www.test.it/network_2/blog_4/**slug**/aaaa/
 -> db.posts.find ({network: "network_2" blogname "blog_4" post_slug: "yyyy"})

我可以创建两个单独的索引(network / blogname / post_id和network / blogname / post_slug)但是我会浪费大量的RAM,因为索引中50%的数据永远不会被使用。

有没有办法创建一个“过滤”的索引?

实施例: (注意WHERE参数)

db.posts.ensureIndex ({network: 1 blogname: 1, post_id: 1}, {where: {network: "network_1"}})

db.posts.ensureIndex ({network: 1 blogname: 1, post_slug: 1}, {where: {network: "network_2"}})

4 个答案:

答案 0 :(得分:3)

确实可以在MongoDB 3.2+中使用它们称之为 partialFilterExpression ,您可以根据创建的索引设置条件。

示例

db.users.createIndex({ "userId": 1, "project": 1 }, 
{ unique: true, partialFilterExpression:{ 
  userId: { $exists: true, $gt : { $type : 10 } } } })

请参阅Partial Index文档

答案 1 :(得分:1)

从MongoDB v3.2开始,支持部分索引。文档:https://docs.mongodb.org/manual/core/index-partial/

答案 2 :(得分:0)

这是可能的,但它需要一种在文档中创建冗余的解决方法,要求您重写查找查询并将查找限制限制为精确匹配。

MongoDB支持sparse indexes,它仅索引给定字段所在的文档。您可以使用此功能仅通过将此字段添加到要编制索引的文档来索引集合的一部分。

坏消息是稀疏索引只能包含一个字段。但好消息是,该字段还可以包含具有多个字段的对象,因此您仍然可以在此字段中存储要搜索的所有数据。

为此,请在包含的文档中添加一个新字段,其中包含一个包含您搜索字段的对象:

{
    "network": "network_1",
    "blogname": "blogname_1",
    "post_id": 1234,
    "post_slug": "abcdefg"
    "network_1_index_key": {
        "blogname": "blogname_1",
        "post_id": 1234
    }
}

您的ensureIndex命令会将字段network_1_index_key编入索引:

 db.posts.ensureIndex( { network_1_index_key: 1 }, { sparse: true } )

应该使用此索引的查询查询现在必须查询字段network_1_index_key的确切对象:

 db.posts.find ({ 
                    network_1_index_key: { 
                        blogname: "blogname_1", 
                        post_id: 1234 
                    } 
                })

只有当您要编制索引的文档只是集合的一小部分时,才会这样做。当它大约一半时,我会创建一个常规索引并使用它,因为较大的文档大小可以减少索引大小减小的收益。

答案 3 :(得分:-3)

您可以尝试在所有字段上创建索引(network / blogname / post_id / post_slug)