猿教程 Logo

.Net连接MongoDb:索引子文档

阿里云服务器,每月低至7.8元,项目演示即建站必备,比腾讯云更便宜,并且不需学生认证,从此链接购买有效:去购买

介绍

在上一篇文章中,我们研究了如何使用客户端shell对MongoDb中的数组进行索引。 我们看到JSON语法中没有什么特别的,它与在标量字段中添加索引时相同。 尽管索引数组字段有一个限制。 我们不能索引两个或更多的数组字段,一次只能一个。 索引尽可能多的标量字段可以加一个数组字段,但不能超过这一点。

在这篇文章中,我们将看到如何在子文档中索引字段。

深度索引

回想一下,我们有一个具有以下结构的餐厅集合:

{
        "_id" : ObjectId("56edc2ff03a1cd840734dba8"),
        "address" : {
                "building" : "2780",
                "coord" : [
                        -73.98241999999999,
                        40.579505
                ],
                "street" : "Stillwell Avenue",
                "zipcode" : "11224"
        },
        "borough" : "Brooklyn",
        "cuisine" : "American ",
        "grades" : [
                {
                        "date" : ISODate("2014-06-10T00:00:00Z"),
                        "grade" : "A",
                        "score" : 5
                },
                {
                        "date" : ISODate("2013-06-05T00:00:00Z"),
                        "grade" : "A",
                        "score" : 7
                },
                {
                        "date" : ISODate("2012-04-13T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                },
                {
                        "date" : ISODate("2011-10-12T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                }
        ],
        "name" : "Riviera Caterer",
        "restaurant_id" : "40356018"
}

假设我们想找到每个至少有一个C级的餐厅。 当我们查询子文档时,我们可以使用我们之前看到的点符号来做到这一点:

db.restaurants.find({"grades.grade" : "C"})

count()函数会告诉我们有这样的文件有2709个。

在子文档中的字段上构建索引也遵循点符号:

db.restaurants.createIndex({"grades.grade" : 1})

我们运行explain命令来检查我们的新索引是否在使用中:

db.restaurants.explain(true).find({"grades.grade" : "C"})

实际上它用于查询执行:

"inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 2709,
                                
                                "keyPattern" : {
                                        "grades.grade" : 1
                                },
                                "indexName" : "grades.grade_1",
                                "isMultiKey" : true,

从索引扫描中返回2709个文档,也是扫描的文档总数:

"executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 2709,
                "totalDocsExamined" : 2709,

那很简单,对吧?

在我们继续之前,我想提两件事。

上面的inputStage片段显示了一个名为isMultiKey的属性,我还没有解释。 我应该在上一篇关于数组索引的文章中这样做,但是我错过了。 数组索引在MongoDb中称为多键索引。 我们在上述情况下的子文档也是一个分数数组,因此称为“grade.grade_1”的索引是一个多键索引。 在这种情况下,查询将显示isMultiKey:true,否则将为false。

另外我们可以提到的是如何获取一个集合的索引列表。 getIndexes函数帮助我们实现:

db.restaurants.getIndexes()

上述查询返回3个索引:_id字段中的默认索引,然后是我们刚刚创建的索引,我们之前在本系列中创建的一个是在自治市和美食领域的复合索引:

[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "model.restaurants"
        },
        {
                "v" : 1,
                "key" : {
                        "borough" : 1,
                        "cuisine" : 1
                },
                "name" : "borough_1_cuisine_1",
                "ns" : "model.restaurants"
        },
        {
                "v" : 1,
                "key" : {
                        "grades.grade" : 1
                },
                "name" : "grades.grade_1",
                "ns" : "model.restaurants"
        }
]

好的,我们现在来看看一个更复杂的查询。 我们想提取所有至少有一个B级的餐厅,得分为19,如下所示:

{
                        "date" : ISODate("2013-10-09T00:00:00Z"),
                        "grade" : "B",
                        "score" : 19
}

我们以前看过$ elemMatch运算符,我们需要再次使用它:

db.restaurants.find({"grades" : {$elemMatch : {"grade" : "B", "score" : 19}}})

计数功能告诉我们,有1067个餐馆符合这个标准。

让我们看看解释功能给我们的是什么:

db.restaurants.explain(true).find({"grades" : {$elemMatch : {"grade" : "B", "score" : 19}}})

有两个阶段 第一阶段是使用我们创建的索引的索引扫描。 它返回8283个文件,对应于至少有一个B级的餐厅:

"inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 8283                                
                                "keyPattern" : {
                                        "grades.grade" : 1
                                },
                                "indexName" : "grades.grade_1",
                                "isMultiKey" : true,

下一个阶段检查这些文件,并返回其中的1067个。 所以8283的1067年至少有一个B级,得分为19分:

"executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1067,
                "executionTimeMillis" : 32,
                "totalKeysExamined" : 8283,
                "totalDocsExamined" : 8283

我们删除上述索引,并将其替换为等级子文档的成绩和分数字段上的复合索引:

db.restaurants.dropIndex({"grades.grade" : 1})
db.restaurants.createIndex({"grades.grade" : 1, "grades.score" : 1})

运行与上述相同的说明命令

db.restaurants.explain(true).find({"grades" : {$elemMatch : {"grade" : "B", "score" : 19}}})

...确实会告诉我们,总共只扫描了1067份文件,即复合索引涵盖了总扫描情况:

"executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1067,
                "executionTimeMillis" : 9,
                "totalKeysExamined" : 1067,
                "totalDocsExamined" : 1067,

我们将在下一篇文章中看一些索引选项。

阿里云服务器,每月低至7.8元,项目演示即建站必备,比腾讯云更便宜,并且不需学生认证,从此链接购买有效: 去购买


版权声明:本站所有教程均为本站原创或翻译,转载请注明出处,请尊重他人劳动果实。请记住本站地址:www.yuanjiaocheng.net (猿教程) 作者:卿文刚
本文标题: C#环境
本文地址:http://www.yuanjiaocheng.net/CsharpMongo/34.html