zoukankan      html  css  js  c++  java
  • MongoDB 常见的查询索引

    常见的查询索引


    _id索引


            _id 索引是绝大多数集合默认建立的索引。对于每一个插入的数据。MongoDB 会自己主动生成一条唯一的 _id 字段。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    > db.jerome_2.collection.insert({x:2})
    WriteResult({ "nInserted" : 1 })
    > db.jerome_2.collection.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "_id" : 1
            },
            "name" "_id_",
            "ns" "jerome.jerome_2.collection"
        }
    ]
    > db.jerome_2.collection.findOne()
    "_id" : ObjectId("557004f1f2824fa15224e20b"), "x" : 2 }

    单键索引


            单键索引是最普通的索引,与_id 索引不同。单键索引不会自己主动创建。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    > db.jerome_2.collection.ensureIndex({x:1}) # 创建单键索引
    {
        "createdCollectionAutomatically" false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
    }
    > db.jerome_2.collection.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "_id" : 1
            },
            "name" "_id_",
            "ns" "jerome.jerome_2.collection"
        },
        {
            "v" : 1,
            "key" : {
                "x" : 1
            },
            "name" "x_1",
            "ns" "jerome.jerome_2.collection"
        }
    ]
    > db.jerome_2.collection.find({x:1}) #使用创建的索引查询
    "_id" : ObjectId("557005a5f2824fa15224e20c"), "x" : 1, "y" : 2, "z" : 3 }


    多键索引


            多键索引和单键索引创建形式同样,差别在于字段的值。

            单键索引:值为一个单一的值,比如字符串,数字或者日期。
            多键索引:值具有多个记录,比如数组。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    > db.jerome_2.collection.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "_id" : 1
            },
            "name" "_id_",
            "ns" "jerome.jerome_2.collection"
        },
        {
            "v" : 1,
            "key" : {
                "x" : 1
            },
            "name" "x_1",
            "ns" "jerome.jerome_2.collection"
        }
    ]
    > db.jerome_2.collection.find()
    "_id" : ObjectId("557004f1f2824fa15224e20b"), "x" : 2 }
    "_id" : ObjectId("557005a5f2824fa15224e20c"), "x" : 1, "y" : 2, "z" : 3 }
    > db.jeroem_2.collection.insert({x:[1,2,3,4,5]}) #插入一条数组数据,对于这条数据来讲。mongodb为其创建了一个多键索引
    WriteResult({ "nInserted" : 1 })

    复合索引

        
            当我们的查询条件不仅仅有一个时。就须要建立复合索引。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    > db.jerome_2.collection.ensureIndex({x:1,y:1}) #创建
    {
        "createdCollectionAutomatically" false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
    }
    > db.jerome_2.collection.find({x:1,y:2}) #使用
    "_id" : ObjectId("557005a5f2824fa15224e20c"), "x" : 1, "y" : 2, "z" : 3 }

    过期索引


            过期索引是在一段时间后会过期的索引。在索引过期后,对应的数据会被删除。这适合存储一些在一段时间之后会失效的数据。比方用户的登陆信息、存储的日志等。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    > db.jerome_2.collection.ensureIndex({time:1},{expireAfterSeconds:30}) #创建过期索引,过期时间30秒
    {
        "createdCollectionAutomatically" false,
        "numIndexesBefore" : 3,
        "numIndexesAfter" : 4,
        "ok" : 1
    }
    > db.jerome_2.collection.insert({time:new Date()}) #插入数据測试
    WriteResult({ "nInserted" : 1 })
    > db.jerome_2.collection.find()
    "_id" : ObjectId("557004f1f2824fa15224e20b"), "x" : 2 }
    "_id" : ObjectId("557005a5f2824fa15224e20c"), "x" : 1, "y" : 2, "z" : 3 }
    "_id" : ObjectId("55700b17f2824fa15224e20e"), "time" : ISODate("2015-06-04T08:23:51.531Z") }
    > db.jerome_2.collection.find()
    "_id" : ObjectId("557004f1f2824fa15224e20b"), "x" : 2 }
    "_id" : ObjectId("557005a5f2824fa15224e20c"), "x" : 1, "y" : 2, "z" : 3 }
    "_id" : ObjectId("55700b17f2824fa15224e20e"), "time" : ISODate("2015-06-04T08:23:51.531Z") }
    > db.jerome_2.collection.find() #时间过了就找不到了
    "_id" : ObjectId("557004f1f2824fa15224e20b"), "x" : 2 }
    "_id" : ObjectId("557005a5f2824fa15224e20c"), "x" : 1, "y" : 2, "z" : 3 }

    使用限制

            1. 存储在过期索引字段的值必须是指定的时间类型。

    (必须是ISODate或者ISODate数组,不能使用时间戳。否则不能被自己主动删除)

            2. 假设指定了ISODate数组。则依照最小的时间进行删除。
            3. 过期索引不能是复合索引。
            4. 删除时间不是精确的。(删除过程是由后台程序没60s跑一次,并且删除也须要一些时间,所以存在误差)

    全文索引


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    > db.jerome_2.ensureIndex({"article":"text"}) #创建全文可搜索索引
    {
        "createdCollectionAutomatically" true,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
    }
    > db.jerome_2.insert({"article":"aa bb cc dd ee"}) #插入測试数据
    WriteResult({ "nInserted" : 1 })
    > db.jerome_2.insert({"article":"aa bb rr gg zz"})
    WriteResult({ "nInserted" : 1 })
    > db.jerome_2.insert({"article":"aa bb"})
    WriteResult({ "nInserted" : 1 })
    > db.jerome_2.insert({"article":"aa bb cc zz ff ww"})
    WriteResult({ "nInserted" : 1 })
    > db.jerome_2.find({$text:{$search:"aa"}}) #查找
    "_id" : ObjectId("5572904271c0bbd90f4ce0e2"), "article" "aa bb rr gg zz" }
    "_id" : ObjectId("5572903371c0bbd90f4ce0e1"), "article" "aa bb cc dd ee" }
    "_id" : ObjectId("5572905671c0bbd90f4ce0e4"), "article" "aa bb cc zz ff ww" }
    "_id" : ObjectId("5572904771c0bbd90f4ce0e3"), "article" "aa bb" }
    > db.jerome_2.find({$text:{$search:"ff"}})
    "_id" : ObjectId("5572905671c0bbd90f4ce0e4"), "article" "aa bb cc zz ff ww" }
    > db.jerome_2.find({$text:{$search:"aa bb cc"}}) #空格表示或
    "_id" : ObjectId("5572904271c0bbd90f4ce0e2"), "article" "aa bb rr gg zz" }
    "_id" : ObjectId("5572903371c0bbd90f4ce0e1"), "article" "aa bb cc dd ee" }
    "_id" : ObjectId("5572905671c0bbd90f4ce0e4"), "article" "aa bb cc zz ff ww" }
    "_id" : ObjectId("5572904771c0bbd90f4ce0e3"), "article" "aa bb" }
    > db.jerome_2.find({$text:{$search:"aa bb -cc"}}) #-cc 表示不包括cc
    "_id" : ObjectId("5572904271c0bbd90f4ce0e2"), "article" "aa bb rr gg zz" }
    "_id" : ObjectId("5572904771c0bbd90f4ce0e3"), "article" "aa bb" }
    > db.jerome_2.find({$text:{$search:""aa" "bb" "cc""}}) #加引號,表示与
    "_id" : ObjectId("5572903371c0bbd90f4ce0e1"), "article" "aa bb cc dd ee" }
    "_id" : ObjectId("5572905671c0bbd90f4ce0e4"), "article" "aa bb cc zz ff ww" }

    全文索引类似度

            $meta操作符:{score:{$meta:"textScore"}},返回结果的类似度,与 sort 一起使用能够达到非常好的有用效果。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    > db.jerome_2.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}) #score越高,类似度越高。
    "_id" : ObjectId("5572904271c0bbd90f4ce0e2"), "article" "aa bb rr gg zz""score" : 1.2 }
    "_id" : ObjectId("5572903371c0bbd90f4ce0e1"), "article" "aa bb cc dd ee""score" : 1.2 }
    "_id" : ObjectId("5572905671c0bbd90f4ce0e4"), "article" "aa bb cc zz ff ww""score" : 1.1666666666666667 }
    "_id" : ObjectId("5572904771c0bbd90f4ce0e3"), "article" "aa bb""score" : 1.5 }
    > db.jerome_2.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}}) #依据score进行排序
    "_id" : ObjectId("5572904771c0bbd90f4ce0e3"), "article" "aa bb""score" : 1.5 }
    "_id" : ObjectId("5572903371c0bbd90f4ce0e1"), "article" "aa bb cc dd ee""score" : 1.2 }
    "_id" : ObjectId("5572904271c0bbd90f4ce0e2"), "article" "aa bb rr gg zz""score" : 1.2 }
    "_id" : ObjectId("5572905671c0bbd90f4ce0e4"), "article" "aa bb cc zz ff ww""score" : 1.1666666666666667 }

    使用限制

            1. 每次查询仅仅能指定一个$text查询
            2. $text查询不能出如今$nor查询中
            3. 查询中假设包括了$text。hint不再起作用
            4. MongoDB 索引如今还不支持中文

    地理位置索引


    概念:
            将一些点的位置存储在 MongoDB 中。创建索引后,能够依照位置来查找其它点。

     


    分类:
            1. 2d 索引。用于存储和查找平面上的点。
            2. 2dsphere 索引,用于存储和查找球面上的点。

     


    查找方式:
            1. 查找距离某个点一定距离内的点。
            2. 查找包括在某区域内的点。

    2d索引
        
    1. $near查询
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    > db.location.ensureIndex({"w":"2d"}) #创建2d索引
    > db.location.insert({w:[1,1]}) #插入測试数据。经纬度[经度,纬度]。

    取值范围:经度[-180,180] 纬度[-90,90]

    WriteResult({ "nInserted" : 1 })
    > db.location.insert({w:[1,2]})
    WriteResult({ "nInserted" : 1 })
    > db.location.insert({w:[2,3]})
    WriteResult({ "nInserted" : 1 })
    > db.location.insert({w:[100,80]})
    WriteResult({ "nInserted" : 1 })
    > db.location.find({w:{$near:[1,1]}}) #查询距离某个点近期的点
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    "_id" : ObjectId("5572a97aaba41684d6e8826f"), "w" : [ 100, 80 ] }
    > db.location.find({w:{$near:[1,1],$maxDistance:2}}) #能够使用maxDistance限制(near不能使用minDistance)
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }

    2. $geoWithin查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    > db.location.find({w:{$geoWithin:{$box:[[0,0],[3,3]]}}}) #矩形
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    > db.location.find({w:{$geoWithin:{$box:[[1,2],[2,3]]}}})
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    > db.location.find({w:{$geoWithin:{$center:[[0,0],100]}}}) #圆形。100是半径
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }
    > db.location.find({w:{$geoWithin:{$center:[[0,0],1000]}}})
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    "_id" : ObjectId("5572a97aaba41684d6e8826f"), "w" : [ 100, 80 ] }
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }
    > db.location.find({w:{$geoWithin:{$polygon:[[0,0],[0,1],[2,5],[6,1]]}}}) #多边形查询(各个点围成的多边形的范围)
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }
    > db.location.find({w:{$geoWithin:{$polygon:[[0,0],[0,1],[2,5],[6,1000],[1001,0]]}}})
    "_id" : ObjectId("5572a970aba41684d6e8826e"), "w" : [ 2, 3 ] }
    "_id" : ObjectId("5572a97aaba41684d6e8826f"), "w" : [ 100, 80 ] }
    "_id" : ObjectId("5572a961aba41684d6e8826c"), "w" : [ 1, 1 ] }
    "_id" : ObjectId("5572a965aba41684d6e8826d"), "w" : [ 1, 2 ] }

    3. 使用geoNear查询

    geoNear使用runCommand命令进行使用
    db.runCommand(
        {getNear:<collection>,
        near:[x,y],
        minDistance:(对2d索引无效)
        maxDistance:
        num:
    }
    )
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    > db.runCommand({geoNear:"location",near:[1,2],maxDistance:10,num:1})
    {
        "results" : [
            {
                "dis" : 0,
                "obj" : {
                    "_id" : ObjectId("5572a965aba41684d6e8826d"),
                    "w" : [
                        1,
                        2
                    ]
                }
            }
        ],
        "stats" : {
            "nscanned" : NumberLong(1),
            "objectsLoaded" : NumberLong(1),
            "avgDistance" : 0,
            "maxDistance" : 0,
            "time" : 2
        },
        "ok" : 1
    }

    2dsphere 球面地理位置索引

            概念:球面地理位置索引。
            创建方式:db.collection.ensureIndex({w:"2dsphere"})
            位置表示方式:
                GeoJson:描写叙述一个点。一条直线,多边形等形状
            格式:{type:"",coordinates:[<coordinates>]}
            支持$minDistance与$maxDistance

    创建索引比較重要属性介绍


    格式
        db.collection.ensureIndex({param},{param}) #第二个參数是索引的属性

    比較重要的属性有:名字、唯一性、稀疏性、是否定时删除


    1. 名字,name指定:db.collection.ensureIndex({},{name:""})

        默认命名格式是例如以下这种
        单键索引。1和-1,命名是依据key+_1/-1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    > db.jerome_2.ensureIndex({x:1})
    > db.jerome_2.ensureIndex({y:-1})
    > db.jerome_2.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "_id" : 1
            },
            "name" "_id_",
            "ns" "jerome.jerome_2"
        },
        {
            "v" : 1,
            "key" : {
                "x" : 1
            },
            "name" "x_1",
            "ns" "jerome.jerome_2"
        },
        {
            "v" : 1,
            "key" : {
                "y" : -1
            },
            "name" "y_-1",
            "ns" "jerome.jerome_2"
        }


        复合索引
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    > db.jerome_2.ensureIndex({x:1,y:-1})
    > db.jerome_2.ensureIndex({x:1,y:-1,z:1})
    > db.jerome_2.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "x" : 1,
                "y" : -1
            },
            "name" "x_1_y_-1",
            "ns" "jerome.jerome_2"
        },
        {
            "v" : 1,
            "key" : {
                "x" : 1,
                "y" : -1,
                "z" : 1
            },
            "name" "x_1_y_-1_z_1",
            "ns" "jerome.jerome_2"
        }
    ]

    MongoDB 对索引限制是125字节,所以我们须要自己定义索引名字。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    > db.jerome_2.ensureIndex({x:1,y:1,z:1,m:1},{name:"normal_index"})
    > db.jerome_2.getIndexes()
    [
        {
            "v" : 1,
            "key" : {
                "x" : 1,
                "y" : 1,
                "z" : 1,
                "m" : 1
            },
            "name" "normal_index",
            "ns" "jerome.jerome_2"
        }
    ]
    > db.jerome_2.dropIndex("normal_index")
    "nIndexesWas" : 7, "ok" : 1 }

    2. 唯一性。unique 指定:db.collection.ensureIndex({},{unique:true/false})

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    > db.jerome.ensureIndex({m:1,n:1},{unique:true})
    {
        "createdCollectionAutomatically" true,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
    }
    > db.jerome.insert({m:1,n:2})
    WriteResult({ "nInserted" : 1 })
    > db.jerome.insert({m:1,n:2})
    WriteResult({
        "nInserted" : 0,
        "writeError" : {
            "code" : 11000,
            "errmsg" "insertDocument :: caused by :: 11000 E11000 duplicate key error index: jerome.jerome.$m_1_n_1  dup key: { : 1.0, : 2.0 }"
        }
    })

    3. 稀疏性,sparse 指定:db.collection.ensureIndex({},{sparse:true/false})


            默认创建的索引是不稀疏的。

    由于 MongoDB 没有固定的格式,插入的时候可能插入不存在的字段。比方x:1,MongoDB 会为这条不存在的字段创建索引。假设不希望发现这种事情能够指定稀疏索引为 true,就不会为不存在的字段创建索引了。

    能够降低磁盘占用和增大插入速度。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    > db.jerome.insert({"m":1})
    WriteResult({ "nInserted" : 1 })
    > db.jerome.insert({"n":1})
    WriteResult({ "nInserted" : 1 })
    > db.jerome.find({m:{$exists:true}}) #exists查找数据集合中一个字段存在或者不存在的记录
    "_id" : ObjectId("55729ec1aba41684d6e8826a"), "m" : 1 }
    "_id" : ObjectId("55729d5caba41684d6e88268"), "m" : 1, "n" : 2 }
    > db.jerome.ensureIndex({m:1},{sparse:true}) #创建稀疏索引
    {
        "createdCollectionAutomatically" false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
    }
    > db.jerome.find({m:{$exists:false}}) #MongoDB内部问题。所以找得到,通过以下强制指定索引
    "_id" : ObjectId("55729ec7aba41684d6e8826b"), "n" : 1 }
    > db.jerome.find({m:{$exists:false}}).hint("m_1"#以下这条记录。不存在m字段,所以不会创建索引。所以查不到记录 
            注意:不能在稀疏索引上查找这个字段不存在的记录。

    4. 是否定时删除


            过期索引,前面已介绍。


    參考

            1. 慕课网
  • 相关阅读:
    如何降低微服务测试成本?我的经验之谈
    Serverless 在 SaaS 领域的最佳实践
    技术干货 | “选图预览并上传”的场景如何解?全网最全方案汇总来了
    SRE技术保障平台-盯屏中心TAC: 混合云一站式告警运维平台
    DTCC 2020 | 阿里云王涛:阿里巴巴电商数据库上云实践
    中值滤波算法 C
    python logger.debug_python中的logger模块讲解
    唯一值
    接触jeecgBoot低代码开发
    php数字操作
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6762469.html
Copyright © 2011-2022 走看看