MongoDB“;过滤的;索引:可能吗?

MongoDB“;过滤的;索引:可能吗?,mongodb,indexing,Mongodb,Indexing,仅当要编制索引的字段之一具有特定值时,才可以为集合的某些文档编制索引吗 让我举例说明: 集合“posts”包含数百万个文档,所有文档的定义如下: {     "network": "network_1",     "blogname": "blogname_1",     "post_id": 1234,     "post_slug": "abcdefg" } 我可以创建两个单独的索引(network/blogname/post_id和network/b

仅当要编制索引的字段之一具有特定值时,才可以为集合的某些文档编制索引吗

让我举例说明:

集合“posts”包含数百万个文档,所有文档的定义如下:

{     "network": "network_1",     "blogname": "blogname_1",     "post_id": 1234,     "post_slug": "abcdefg" } 我可以创建两个单独的索引(network/blogname/post_id和network/blogname/post_slug),但是我会得到巨大的内存浪费,因为索引中50%的数据永远不会被使用

有没有办法创建“过滤”索引

例如: (注意WHERE参数)


您可以尝试在所有字段上创建索引(network/blogname/post\u id/post\u slug)

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

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

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

要执行此操作,请向包含的文档中添加一个新字段,其中包含一个包含您搜索的字段的对象:

{
    "network": "network_1",
    "blogname": "blogname_1",
    "post_id": 1234,
    "post_slug": "abcdefg"
    "network_1_index_key": {
        "blogname": "blogname_1",
        "post_id": 1234
    }
}
您的ensureIndex命令将索引字段网络索引键:

 db.posts.ensureIndex( { network_1_index_key: 1 }, { sparse: true } )
 db.posts.find ({ 
                    network_1_index_key: { 
                        blogname: "blogname_1", 
                        post_id: 1234 
                    } 
                })
应该使用此索引的查找查询现在必须查询字段网络索引键的确切对象:

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

只有当您想要索引的文档只是集合的一小部分时,这样做才有意义。当它大约占一半时,我只会创建一个常规索引并使用它,因为更大的文档大小可能会减少索引大小减少带来的收益。

从MongoDB v3.2开始,支持部分索引。文档:

事实上,在MongoDB 3.2+中,您可以根据创建索引的条件设置部分过滤表达式

示例

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

请参阅文档

这在Mongodbb中还不可能,但这正是Ligio想要避免的。索引“network/blogname/post_id/post_slug”将不包括在“network/blogname/post_slug”上找到的内容。我在我的收藏中创建了相同的索引,它对我很有用。你能发送你收藏的信息吗?db.posts.stats()和db.posts.find({network:“network_1”blogname“blog_1”,post_id:1234})。explain()?Philipp,Ligio希望避免创建两个索引。我认为你的建议现在是唯一可能的解决方案,但我需要更新数以百万计的现有文档,并检查工作集是否适合RAM@Ligio也许一些服务器端javascript可以完成这项工作?当您在转换大量文档时遇到任何问题时,您应该创建一个新问题。由于引入了
partialFilterExpression
(请参阅其他答案,MongoDB 3.2+),因此不推荐使用此答案