mongo索引

索引
自动创建和手工创建

db.stu.drop();
db.stu.insert({"name":"张三","sex":"男","age":18,"score":70,"address":"河南"});
db.stu.insert({"name":"李四","sex":"女","age":20,"score":60,"address":"山东"});
db.stu.insert({"name":"王五","sex":"男","age":17,"score":44,"address":"江苏"});
db.stu.insert({"name":"赵六","sex":"男","age":21,"score":80,"address":"山东"});
db.stu.insert({"name":"孙七","sex":"女","age":23,"score":50,"address":"湖北"});
db.stu.insert({"name":"tom","sex":"男","age":24,"score":20,"address":"海南"});
db.stu.insert({"name":"lucy","sex":"女","age":21,"score":62,"address":"浙江"});
db.stu.insert({"name":"jack","sex":"男","age":20,"score":90,"address":"美国"});
db.stu.insert({"name":"smith","sex":"男","age":19,"score":88,"address":"美国"});
View Code

查询默认状态下的stu集合索引内容
db.stu.getIndexes();

> db.stu.getIndexes();
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.stu"
        }
]

v:索引版本
_id:1 表示升序

索引创建
db.集合.ensureIndex({列:1})
1表示升序 -1降序
db.stu.ensureIndex({"age":-1});

> db.stu.ensureIndex({"age":-1});
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
db.stu.getIndexes();
> db.stu.getIndexes();
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.stu"
        },
        {
                "v" : 2,
                "key" : {
                        "age" : -1
                },
                "name" : "age_-1",
                "ns" : "test.stu"
        }
]
View Code

这时索引名是自动命名的。命名规范: 字段名称_索引排序模式
索引使用分析

db.stu.find({"age":21}).explain();
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.stu",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "age" : {
                "$eq" : 21
            }
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "age" : -1
                },
                "indexName" : "age_-1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "age" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "age" : [
                        "[21.0, 21.0]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "centos1",
        "port" : 27000,
        "version" : "3.4.4",
        "gitVersion" : "888390515874a9debd1b6c5d36559ca86b44babd"
    },
    "ok" : 1
}
View Code

"stage" : "IXSCAN"

在非索引的列上

> db.stu.find({"score":{"$gt":60}}).explain();
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.stu",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "score" : {
                "$gt" : 60
            }
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "score" : {
                    "$gt" : 60
                }
            },
            "direction" : "forward"
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "centos1",
        "port" : 27000,
        "version" : "3.4.4",
        "gitVersion" : "888390515874a9debd1b6c5d36559ca86b44babd"
    },
    "ok" : 1
}
View Code

"stage" : "COLLSCAN"

db.stu.find({"$or":[
    {"age":{"$gt":21}},
    {"score":{"$gt":60}}
    ]}).explain();

此时age上有索引,score上没有,使用的是全表扫描
"stage" : "COLLSCAN",

这时可以使用符合索引
db.stu.ensureIndex({"age":-1,"score":-1},{"name":"age_-1_score_-1"})

执行查询
db.stu.find({"$or":[
    {"age":{"$gt":21}},
    {"score":{"$gt":60}}
    ]}).explain();

"stage" : "COLLSCAN",
db.stu.find({"$or":[
    {"age":21},
    {"score":80}
    ]}).explain();
依然
"stage" : "COLLSCAN"

强制使用索引

db.stu.find({"$or":[
    {"age":21},
    {"score":80}
    ]}).hint({"age":-1,"score":-1}).explain();

"stage" : "IXSCAN"
db.stu.find({"$or":[
    {"age":21},
    {"score":80}
    ]}).hint({"age":-1,"score":1}).explain();
会报错
db.stu.find({"$or":[
    {"age":{"$gt":21}},
    {"score":{"$gt":60}}
    ]}).hint({"age":-1,"score":-1}).explain();

stage" : "IXSCAN"

删除索引
db.stu.dropIndex({"age":-1,"score":-1});
删除全部索引(除了_id外)
db.stu.dropIndexes();

 唯一索引

db.stus.ensureIndex({"name":1},{"unique":true});
> db.stu.getIndexes();
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "hk.stu"
    }
]

db.stu.insert({"name":"smith","sex":"男","age":19,"score":88,"address":"美国"});
> db.stu.ensureIndex({"name":1},{"unique":true});
{
    "ok" : 0,
    "errmsg" : "E11000 duplicate key error collection: hk.stu index: name_1 dup key: { : "smith" }",
    "code" : 11000,
    "codeName" : "DuplicateKey"
}
> 
db.stu.remove({ "_id" : ObjectId("5943194f2e32953979ce4b4d")});
WriteResult({ "nRemoved" : 1 })
> db.stu.ensureIndex({"name":1},{"unique":true});
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

> db.stu.getIndexes()
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "hk.stu"
    },
    {
        "v" : 2,
        "unique" : true,
        "key" : {
            "name" : 1
        },
        "name" : "name_1",
        "ns" : "hk.stu"
    }
]
View Code

过期索引 信息若干时间后过期

db.phones.ensureIndex({"time":1},{expireAfterSeconds:10});
//设置索引在10s后过期
db.phones.insert({"tel":"18600880451","code":"111","time":new Date()});
db.phones.insert({"tel":"18600880452","code":"112","time":new Date()});
db.phones.insert({"tel":"18600880453","code":"113","time":new Date()});
db.phones.insert({"tel":"18600880454","code":"114","time":new Date()});
db.phones.insert({"tel":"18600880455","code":"115","time":new Date()});
10秒后(不准确)
db.phones.find()
数据会消失

 全文索引

设置全文检索(必须先有数据,后加索引,drop后必须重建索引)

实现模糊查询
表示全文索引 $text 判断符
数据的查询使用$search 运算符
1.查询指定关键字: {"$search":"查询关键字"}
2.查询多个关键字(或关系):{"$search":"关键字1 关键字2 ..."}
3.查询多个关键字(与关系):{"$search":""关键字1" "关键字2" ..."}
4.查询多个关键词(排除某一个):{"$search":"关键词1 关键词2 .... -关键词3"}
var data=[
{"title":"apple","con":"this fruit is  apple"},
{"title":"pear","con":"this fruit is  pear"},
{"title":"peach","con":"this fruit is  peach"},
{"title":"apple pear","con":"two fruit"},
{"title":"pear apple peach","con":"three fruit"},
{"title":"pear,apple,peach","con":"three fruit"},
{"title":"apple_1","con":"fruit"},
];
db.fruit.insert(data);
db.fruit.ensureIndex({"title":"text"});

多个能设置权重
{"weights":{"title":2,"con":1}

查询title里含有apple的
db.fruit.find({"$text":{"$search":"apple"}})
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca7"), "title" : "pear apple peach", "con" : "three fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca6"), "title" : "apple pear", "con" : "two fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca8"), "title" : "pear,apple,peach", "con" : "three fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca3"), "title" : "apple", "con" : "this fruit is  apple" }
查询有apple或者pear
db.fruit.find({"$text":{"$search":"apple pear"}})
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca4"), "title" : "pear", "con" : "this fruit is  pear" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca3"), "title" : "apple", "con" : "this fruit is  apple" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca8"), "title" : "pear,apple,peach", "con" : "three fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca6"), "title" : "apple pear", "con" : "two fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca7"), "title" : "pear apple peach", "con" : "three fruit" }
查询有apple而且pear的
db.fruit.find({"$text":{"$search":""apple" "pear""}})
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca8"), "title" : "pear,apple,peach", "con" : "three fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca6"), "title" : "apple pear", "con" : "two fruit" }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca7"), "title" : "pear apple peach", "con" : "three fruit" }
查询有apple pear没有peach的
db.fruit.find({"$text":{"$search":""apple" "pear" -peach"}})
{ "_id" : ObjectId("59445bfd3bdbe9486ee00ca0"), "title" : "apple pear", "con" : "two fruit" }

还可以使用相似度的打分来判断检索成果
为结果打分,分越高越准确

db.fruit.find({"$text":{"$search":"apple pear"}},{"score":{"$meta":"textScore"}})
排序
db.fruit.find({"$text":{"$search":"apple pear"}},{"score":{"$meta":"textScore"}}).sort({"score":{"$meta":"textScore"}})
> db.fruit.find({"$text":{"$search":"apple pear"}},{"score":{"$meta":"textScore"}}).sort({"score":{"$meta":"textScore"}})
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca6"), "title" : "apple pear", "con" : "two fruit", "score" : 1.5 }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca7"), "title" : "pear apple peach", "con" : "three fruit", "score" : 1.3333333333333333 }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca8"), "title" : "pear,apple,peach", "con" : "three fruit", "score" : 1.3333333333333333 }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca4"), "title" : "pear", "con" : "this fruit is  pear", "score" : 1.1 }
{ "_id" : ObjectId("59445eb93bdbe9486ee00ca3"), "title" : "apple", "con" : "this fruit is  apple", "score" : 1 }

全文索引的限制:
一个集合只能创建一个全文索引,每次查询只能指定一个$text查询
$text不能出现在$nor查询中
查询如果包含了$text,$hint不起作用
不支持中文全文检索

地理信息索引

1.2d平面索引
2.2dsphere球面索引
2d 坐标保存的就是经纬度坐标

例子:定义一个商铺集合
db.shop.insert({"loc":[10,10]});
db.shop.insert({"loc":[10,11]});
db.shop.insert({"loc":[13,10]});
db.shop.insert({"loc":[30,40]});
db.shop.insert({"loc":[50,80]});
db.shop.insert({"loc":[100,110]});
为shop添加2d索引
db.shop.ensureIndex({"loc":"2d"});
2种查询方式
$near 查询距离某个点最近的坐标点
$geoWithin  查询某个形状内的点
db.shop.find({"loc":{"$near":[10,11]}})
> db.shop.find({"loc":{"$near":[10,11]}})
默认前100个
{ "_id" : ObjectId("5944748d2e861d522342cb87"), "loc" : [ 10, 11 ] }
{ "_id" : ObjectId("5944748d2e861d522342cb86"), "loc" : [ 10, 10 ] }
{ "_id" : ObjectId("5944748d2e861d522342cb88"), "loc" : [ 13, 10 ] }
{ "_id" : ObjectId("5944748d2e861d522342cb89"), "loc" : [ 30, 40 ] }
{ "_id" : ObjectId("5944748d2e861d522342cb8a"), "loc" : [ 50, 80 ] }
{ "_id" : ObjectId("5944748e2e861d522342cb8b"), "loc" : [ 100, 110 ] }
设置范围3个点内的
db.shop.find({"loc":{"$near":[10,11],"$maxDistance":3}})
> db.shop.find({"loc":{"$near":[10,11],"$maxDistance":3}})
{ "_id" : ObjectId("5944748d2e861d522342cb87"), "loc" : [ 10, 11 ] }
{ "_id" : ObjectId("5944748d2e861d522342cb86"), "loc" : [ 10, 10 ] }

在2d索引里支持最大距离,不支持最小距离
设置查询范围
使用 $geoWithin
矩形范围 {"$box":[[x1,y1],[x2,y2]]}
圆形范围 {"$center":[[x1,y1],r]}
多边形 {"$polygon":[[x1,y1],[x2,y2],[x3,y3] .....]}

1.
db.shop.find({"loc":{"$geoWithin":{"$box":[[9,11],[13,20]]}}})
{ "_id" : ObjectId("5944748d2e861d522342cb87"), "loc" : [ 10, 11 ] }
2.
db.shop.find({"loc":{"$geoWithin":{"$center":[[9,10],3]}}})
{ "_id" : ObjectId("5944748d2e861d522342cb86"), "loc" : [ 10, 10 ] }
{ "_id" : ObjectId("5944748d2e861d522342cb87"), "loc" : [ 10, 11 ] }
runCommand() 执行特定命令
db.runCommand({"geoNear":"shop",near:[10,10],maxDistance:3,num:2})
{
    "results" : [
        {
            "dis" : 0,
            "obj" : {
                "_id" : ObjectId("5944748d2e861d522342cb86"),
                "loc" : [
                    10,
                    10
                ]
            }
        },
        {
            "dis" : 1,
            "obj" : {
                "_id" : ObjectId("5944748d2e861d522342cb87"),
                "loc" : [
                    10,
                    11
                ]
            }
        }
    ],
    "stats" : {
        "nscanned" : 32,
        "objectsLoaded" : 2,
        "avgDistance" : 0.5,
        "maxDistance" : 1,
        "time" : 47
    },
    "ok" : 1
}
原文地址:https://www.cnblogs.com/HKUI/p/6965464.html