笔记——MongoDB 5.0 数据库—详解

        MongoDB数据库操作存在由严格的语法格式,区分大小写。 

# 查看数据库
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
# 使用数据库
> use mydb
switched to db mydb

        实际上当前语句之后并不会创建数据库,只有在数据库中保存集合数据后才能够创建数据库。

创建集合

        db.createCollection("集合名称");
        但是很多时候在使用的过程中一般不这样操作,因、MongoDB是无模式的,一般都是直接向集合中保存一个数据。这时集合会自动创建。
        db.集合名称.insert(JSON串);

> db.createCollection("myclt")
{ "ok" : 1 }
# 查看集合
> show collections
myclt
> db.students.insert({"name":"赵一","age":20,"sex":"男","score":90});
WriteResult({ "nInserted" : 1 })
> show collections
myclt
students

查看具体集合数据

        db.集合名称.find(条件);
        db.集合名称.find():不带条件是查询集合中全部的数据

> db.students.find()
{ "_id" : ObjectId("61df9c7c5d74d37549b18e54"), "name" : "赵一", "age" : 20, "sex" : "男", "score" : 90 }
>

        从传统的数据表来看(集合就相当于表的结构),表的结构一旦定义就必须按照其定义的要求进行内容的编写。但MongoDB不同,MongoDB可用随意扩充数据。

        MongoDB集合中的内容可用由用户随意定义,完全不用考虑其他的数据结构,那么就需要必须明确,在MongoDB数据库中绝对没有不可能存在查看集合结构的操作。

        在MongoDB集合中的每一行记录都会自动生成一个""_id" : ObjectId("61df9c7c5d74d37549b18e54")"数据。

        "_id"的数据组成:时间戳 + 机器码 + 进程的PID + 计数器 。当前ID的信息是MongoDB自己为用户生成的。

         MongoDB的数据操作可用对JaveScript进行完美结合。

查看一个文档中的信息

        db.集合名称.findOne();

> db.students.insert({"name":"苟二","age":25,"sex":"女","score":70});;
WriteResult({ "nInserted" : 1 })
> db.students.findOne()
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
>

删除集合

        db.集合名称.drop()

删除数据库

        db.dropDatabase();删除当前所在的数据库,必须切换到要删除的数据库后,才可以删除。

数据操作

        只要是数据库绝对离不开最核心的功能:CURD;所以在MongoDB中对于数据的操作也是由支持的,需要注意的是,在MongoDB中除增加外,其他的都很麻烦。

保存数据

        db.集合名称.insert({"key":"value","key1":"value1"...}):可用实现对数据的增加操作。

        db.集合名称.insert([{数据1},{数据2}...]):保存多个数据的情况下,可用使用数据。

# 保存基本数据
> db.students.insert({"name":"张三","age":19,"sex":"男","score":50});
WriteResult({ "nInserted" : 1 })
# 保存数组数据
db.students.insert({"name":"李四","age":19,"sex":"男","score":50,"course":["C++","C#","Java","JavaScript","Vue"]});
WriteResult({ "nInserted" : 1 })

        当保存N个数据时,可用结合for循环来进行数据存储。如果数据很多的情况下,列表是不会全部列出。只会列出部分的数据。用 it 翻页查看。

数据查询

        在任何的数据库中,数据的查询操作都是最为繁琐的,而在MongoDB数据库中,对数据的查询支持非常到位。包含由:关系运算、逻辑运算、数组运算、正则运算等等。

        MongoDB对于数据的查询操作核心语法:db.集合名称.find({查询条件},[{设置显示的字段}])

> db.students.find({},{name:1,age:1,_id:0})
{ "name" : "赵一", "age" : 20 }
{ "name" : "苟二", "age" : 25 }
{ "name" : "张三", "age" : 19 }
{ "name" : "李四", "age" : 19 }

        对于数据的查询操作也是按照JSON形式设置的相等关系,在MongoDB的整个操作过程中都离不开JSON数据。

        对于设置的字段严格来讲就称为数据的投影操作。(投影:整个数据的部分数据拿出来就称之为投影操作)。若不需要显示的字段设置为“0”,而需要显示的字段设置为“1”。

pretty()

        对于数据的查询可以使用“pretty()”函数进行优雅展示。也就是利用pretty()可以实现对数据进行格式化的展示效果。

> db.students.find().pretty();
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
{
        "_id" : ObjectId("61df9df05d74d37549b18e55"),
        "name" : "苟二",
        "age" : 25,
        "sex" : "女",
        "score" : 70
}
{
        "_id" : ObjectId("61dfa08d5d74d37549b18e56"),
        "name" : "张三",
        "age" : 19,
        "sex" : "男",
        "score" : 50
}
{
        "_id" : ObjectId("61dfbd6b5d74d37549b18e57"),
        "name" : "李四",
        "age" : 19,
        "sex" : "男",
        "score" : 50,
        "course" : [
                "C++",
                "C#",
                "Java",
                "JavaScript",
                "Vue"
        ]
}

关系运算

        在MongoDB中支持的关系查询操作:大于($gt),大于等于($gte),小于($lt),小于等于($lte),不等于($ne),等于($eqkey:value

> db.students.find({"age":{"$gt":19}}).pretty()
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
{
        "_id" : ObjectId("61df9df05d74d37549b18e55"),
        "name" : "苟二",
        "age" : 25,
        "sex" : "女",
        "score" : 70
}
> db.students.find({"age":{"$lte":19}}).pretty()
{
        "_id" : ObjectId("61dfa08d5d74d37549b18e56"),
        "name" : "张三",
        "age" : 19,
        "sex" : "男",
        "score" : 50
}
{
        "_id" : ObjectId("61dfbd6b5d74d37549b18e57"),
        "name" : "李四",
        "age" : 19,
        "sex" : "男",
        "score" : 50,
        "course" : [
                "C++",
                "C#",
                "Java",
                "JavaScript",
                "Vue"
        ]
}
> db.students.find({"age":{"$ne":19}}).pretty()
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
{
        "_id" : ObjectId("61df9df05d74d37549b18e55"),
        "name" : "苟二",
        "age" : 25,
        "sex" : "女",
        "score" : 70
}

        当前这种条件的数据结构,在一个JSON结构中定义其它的JSON结构的形式就是BSON的数据结构。

逻辑运算

        在MongoDB中逻辑查询主要有三种类型:与($and)或($or)非($not$nor

> db.students.find({"age":{"$gte":19,"$lte":20}}).pretty()
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
{
        "_id" : ObjectId("61dfa08d5d74d37549b18e56"),
        "name" : "张三",
        "age" : 19,
        "sex" : "男",
        "score" : 50
}
{
        "_id" : ObjectId("61dfbd6b5d74d37549b18e57"),
        "name" : "李四",
        "age" : 19,
        "sex" : "男",
        "score" : 50,
        "course" : [
                "C++",
                "C#",
                "Java",
                "JavaScript",
                "Vue"
        ]
}
# 或的连接 需要为数据设置数组的过滤条件
> db.students.find({"$or":[{"age":{"$lt":20}},{"score":{"$lt":60}}]}).pretty();
{
        "_id" : ObjectId("61dfa08d5d74d37549b18e56"),
        "name" : "张三",
        "age" : 19,
        "sex" : "男",
        "score" : 50
}
{
        "_id" : ObjectId("61dfbd6b5d74d37549b18e57"),
        "name" : "李四",
        "age" : 19,
        "sex" : "男",
        "score" : 50,
        "course" : [
                "C++",
                "C#",
                "Java",
                "JavaScript",
                "Vue"
        ]
}
# $nor:求反。
> db.students.find({"$nor":[{"age":{"$lt":20}},{"score":{"$lt":60}}]}).pretty();
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
{
        "_id" : ObjectId("61df9df05d74d37549b18e55"),
        "name" : "苟二",
        "age" : 25,
        "sex" : "女",
        "score" : 70
}

模运算

        模的运算使用“$mod”来完成。语法:{"$mod":[数字,余数]}。利用求模运算可以编写一些数学的计算公式,实现一些更加准确的查询过程。

> db.students.find({"age":{"$mod":[20,5]}}).pretty();
{
        "_id" : ObjectId("61df9df05d74d37549b18e55"),
        "name" : "苟二",
        "age" : 25,
        "sex" : "女",
        "score" : 70
}

范围运算

        数据库都会存在有:在范围内($in)不在范围内($nin)

> db.students.find({"age":{"$in":[19,20,21]}}).pretty();
{
        "_id" : ObjectId("61df9c7c5d74d37549b18e54"),
        "name" : "赵一",
        "age" : 20,
        "sex" : "男",
        "score" : 90
}
{
        "_id" : ObjectId("61dfa08d5d74d37549b18e56"),
        "name" : "张三",
        "age" : 19,
        "sex" : "男",
        "score" : 50
}
{
        "_id" : ObjectId("61dfbd6b5d74d37549b18e57"),
        "name" : "李四",
        "age" : 19,
        "sex" : "男",
        "score" : 50,
        "course" : [
                "C++",
                "C#",
                "Java",
                "JavaScript",
                "Vue"
        ]
}

数组运算

        在MongoDB中是支持数组保存的,那么在查询中就需要针对于数组的数据进行匹配。针对此类包含有数组的数据,需要对数组数据进行判断,可以使用以下运算符:$all、$size、$slice、$elemMatch等。

        $all:查询的集合中包含有指定内容的数据。虽然$all可以用在数组上,同时也可以用于单个数据的匹配。

> db.students.find({"course":{"$all":["Java","C#"]}}).pretty();
{
        "_id" : ObjectId("61dfbd6b5d74d37549b18e57"),
        "name" : "李四",
        "age" : 19,
        "sex" : "男",
        "score" : 50,
        "course" : [
                "C++",
                "C#",
                "Java",
                "JavaScript",
                "Vue"
        ]
}
{
        "_id" : ObjectId("61dfd3615d74d37549b18e58"),
        "name" : "王五",
        "age" : 19,
        "sex" : "男",
        "score" : 80,
        "course" : [
                "C#",
                "Java",
                "Vue"
        ]
}
> db.students.find({"name":{"$all":["张三"]}}).pretty();
{
        "_id" : ObjectId("61dfa08d5d74d37549b18e56"),
        "name" : "张三",
        "age" : 19,
        "sex" : "男",
        "score" : 50
}

        既然集合中存在有数组的数据信息,那么数组就可以利用索引操作,使用“key.index”的方式来定义索引。

> db.students.find({"course.1":"Java"})
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : [ "C#", "Java", "Vue" ] }

        $size:数组的数量长度条件控制。

> db.students.find({"course":{"$size":3}})
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : [ "C#", "Java", "Vue" ] }

        进行以上数组的数据查询操作时,发现只要是内容符合条件,数组的内容都会展示出来。但若希望可以控制数组返回的数量,那么可以使用”$slice“进行控制操作。

# 正数 从前面取课程数量
> db.students.find({"age":19},{"course":{"$slice":3}})
{ "_id" : ObjectId("61dfa08d5d74d37549b18e56"), "name" : "张三", "age" : 19, "sex" : "男", "score" : 50 }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : [ "C++", "C#", "Java" ] }
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : [ "C#", "Java", "Vue" ] }

# 可为负数 从后面取课程数量
> db.students.find({"age":19},{"course":{"$slice":-2}})
{ "_id" : ObjectId("61dfa08d5d74d37549b18e56"), "name" : "张三", "age" : 19, "sex" : "男", "score" : 50 }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : [ "JavaScript", "Vue" ] }
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : [ "Java", "Vue" ] }

# [1,1] 就是设置的俩个数量中,第一个数量表示要跳过的数量,而第二个数量表示要返回的数量
> db.students.find({"age":19},{"course":{"$slice":[1,1]}})
{ "_id" : ObjectId("61dfa08d5d74d37549b18e56"), "name" : "张三", "age" : 19, "sex" : "男", "score" : 50 }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : [ "C#" ] }
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : [ "Java" ] }

嵌套集合运算

        在MongoDB数据中每一个集合数据都可以保存其它的集合数据。为嵌套集合数据,而这种集合的数据判断只能通过”$elemMatch“来完成。

# 添加一个包含集合的数据
> db.students.insert({"name":"秦六","age":21,"sex":"女","course":["C#","Java"],"scores":[{"corse":"C#","score":70,"level":"良"},{"corese":"Java","score":95,"level":"优"}]})))
WriteResult({ "nInserted" : 1 })
# 查询评优
> db.students.find({"age":21},{"scores":{"$elemMatch":{"corse":"Java","level":"优"}}})
{ "_id" : ObjectId("61dfd9815d74d37549b18e59") }

字段判断

        使用”$exists“判断某个字段是否存在,true为存在,false为不存在。可以利用此类查询来进行一些不需要的数据过滤。

> db.students.find({"score":{"$exists":false}})
{ "_id" : ObjectId("61dfd9815d74d37549b18e59"), "name" : "秦六", "age" : 21, "sex" : "女", "course" : [ "C#", "Java" ], "scores" : [ { "corse" : "C#", "score" : 70, "level" : "良" }, { "corese" : "Java", "score" : 95, "level" : "优" } ] }

以下不展示结果了...     太占地方了 

WHERE条件

        对于日常工作习惯来讲,在拼接关系型数据库的语句时,总会想到where子句。而在MongoDB中也提供了”$where“筛选条件。

db.students.find({"$where":"this.age>20"}).pretty();
db.students.find("this.age>20").pretty();

由以上示例可以看出”$where“是可以简化的,但是这类的操作是属于进行每一行的信息判断,实际上对于数据量较大的情况并不方便使用。实际上以上示例相当于编写了一个操作的函数。等同于如下:

db.students.find(function(){
	return this.age>20;
}).pretty();
或
db.students.find({"$where": function(){
	return this.age>20;
}}).pretty();

上述示例都是一个条件的查询判断,若要由多个条件的查询判断就需要使用逻辑运算符拼接。

db.students.find({"$and":[
	{"$where":"this.age>20"},
	{"$where":"this.score>60"}]
}).pretty();

此类方式实现的数据查询最大的缺点就是将MongoDB中保存的BSON数据变成JavaScript的语法结构,这种方式不便于使用数据库的索引机制.

也就是说这种查询方式是由限制的:它能变为JavaScript语法结构进行查询,但会将BSON数据重新变为JavaScript进行重新循环验证,MongoDB的索引是不能起作用的。

正则运算

        也就是模糊查询。MongoDB的模糊查询必须使用正则表达式,MongoDB的正则表达式使用的是Perl兼容的正则表达式的形式。

        格式:

                基本语法:{key: 正则标记}

                完整语法:{key: {"$regex": 正则标记, "$options": 选项}}

                        $options:主要是设置正则信息的查询标记

                                i: 忽略字母大小写
                                m: 多行查找
                                x: 空白字符除了被转义的或字符类中以外的完全被忽略
                                s: 匹配所有的字符,包括换行内容。

注:若要直接使用(JavaScript)那么只能够使用i和m,而x和s必须使用$regex

db.students.find({"name":/赵/}).pretty();

查询带有c的课程。i是不区分大小写

db.students.find({"course":/c/i}).pretty();
db.students.find({"course": {"$regex":/c/i}}).pretty()

MongoDB中的正则符号和Java的正则符号是由差别的,不建议在其中使用Java的一些正则符号。

数据排序

        在MongoDB中排序操作使用”sort()“函数,排序中的俩个顺序:升序(1),降序(-1)。

db.students.find().sort({"score",1}).pretty();
db.students.find().sort({"score",-1}).pretty();

但在进行排序过程中,有一种排序方式称之为自然排序。按照数据保存的先后顺序进行排序,使用"$natural"

db.students.find().sort({"$natural",1}).pretty();
db.students.find().sort({"$natural",-1}).pretty();

在MongoDB数据库中的排序操作相对于关系型数据库的设置要简单。

数据分页

        在MongoDB中数据分页的俩个函数:
                skip(n):表示跨过多少数据行(页码)
                limit(n):取出的数据行的个数限制(单页n条)

db.students.find().skip(0).limit(10).sort({"$natural",-1}).pretty();

数据更新

        在MongoDB在提供了对数据更新的两类函数:save()update()。若要对数据进行修改,最直接的函数就是update()函数,但是update()的语法要求相当麻烦。

        语法:db.集合.update(更新条件, 新的集合数据(需要有更新操作符), upsert, multi)
                upsert:表示若更新的数据不存在,则新增。true增加,false不增加
                multi:表示是否只更新满足条件的第一条记录,若设置为false,则只更新第一个。

# 将年龄为20岁的第一条数据更新成年龄为30岁
db.students.update({"age":20}, {"$set":{"age":30}},false,false)
# 将年龄为20岁的所有数据更新成年龄为30岁
db.students.update({"age":20}, {"$set":{"age":30}},false,true)

# 更新年龄为10岁的第一条数据,不存在则新增。
db.students.update({"age":10}, {"$set":{"name":"小明","age":20,"score":88}},true,false)

修改器

        对MongoDB数据库而言,数据的修改会牵扯到内容的变更、结构的变更(包含有数组)。那么在MongoDB设计时就提供了一系列的修改器的应用

        $inc:主要针对数字字段,增加数字字段的数据内容。{"$inc":{"成员":内容}}

# 将年龄为30岁的数据成绩加10分且年龄减5岁
db.students.update({"age",30},{"$inc":{"score":10,"age":-5}},false,true)

        $set:针对数据内容的重新设置

        $unset:删除某个成员的内容        语法:{"$unset":{"成员":1}}

# 删除赵一的年龄和成绩字段及字段内容
db.students.update({"name":"赵一"},{"$unset":{"age":1,"score":1}})

        $push:将内容追加到指定的成员中,$push追加就是针对数组数据进行操作的。若成员不存在,则进行新数组的创建。若存在,则进行数组的追加。
                语法:{"$push":{"成员":value}}

# 向赵一中追加课程信息(此时赵一没有课程信息)
db.students.update({"name":"赵一"},{"$push":{"score":"Java"}})

# 再向赵一中追加一门课程
db.students.update({"name":"赵一"},{"$push":{"score":"JavaScript"}})

         $pushAll:与$push类似,一次追加多个内容到数组中。
                语法:{"$pushALl":{成员:数组内容}}

db.students.update({"name":"小明"},{"$pushAll":{"score":["Java","JavaScript"]}})

         $addToSet:向数组中增加一个新的内容,只有内容不存在时才增加。
                语法:{"$addToSet":{成员:内容}} 内容也可以是个数组。

db.students.update({"name":"小明"},{"$addToSet":{"score":"C#"}})

        $pop:删除数组内的数据。
                语法:{"$pop":{成员:内容}}        内容为-1表示删除第一个,1表示删除最后一个。

db.students.update({"name":"赵一"},{"$pop":{"score":-1}})

        $pull:从数组中删除一个指定内容的数据。
                语法:{"$pull":{成员:数据}}        此数据是进行数据比对,若是此数据则删除。

db.students.update({"name":"赵一"},{"$pop":{"score": "Java"}})

        $pullALl:一次性删除多个内容。
                语法:{"$pullALl ":{成员:[数据1,数据2...]}}

db.students.update({"name":"赵一"},{"$pullALl":{"score": ["Java","C#"]}})

        $rename:为成员名称重命名。
                语法:{"$rename":{旧成员名称:新成员名称}}

db.students.update({"name":"赵一"},{"$rename":{"name": "userName"}})

数据删除

        在MongoDB中的删除操作只需要使用remove()函数即可。当前函数的俩个可选项:
                删除条件:满足条件的数据被删除。
                是否只删除一个数据:设置为true或1,表示只删除一个。

# 清空集合中的所有内容
db.集合名称.remove({})

# 删除指定条件的数据信息
db.students.remove({"name":/赵/});

# 只删除一个指定条件的数据信息
db.students.remove({"name":/赵/},true);

游标

        游标就是指数据可以一行行的进行操作,类似于ResultSet数据处理。在MongoDB中,对于游标的控制只需要使用find()函数就可以返回游标。对于返回的游标,要进行操作需要使用俩个函数:

                判断是否有下一行数据:hasNext()
                取出当前数据:next()

var cursor=db.students.find();
while(cursor.hasNext()){
	var _value = cursor.next();
	printJson(_value);//Json输出格式
}

索引

        在任何的数据库中,索引都是为提升数据库检索性能而存在的。MongoDB也是如此,在MongoDB中存在俩种的索引创建:一种是MongoDB自动创建的;另一种是手工创建的。

        通过getIndexes()函数观察集合种已经存在的索引内容。

db.students.getIndexes()

        创建索引:db.集合名称.createIndex(key: 1);        设置为1表示索引将按照升序的方式排列;反之-1为降序方式排列。

注:早期版本创建索引的函数为ensureIndex()。在 MongoDB 5.0 中被createIndex()函数取代。

> db.students.createIndex({"age":-1})
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}
> db.students.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "age" : -1
                },
                "name" : "age_-1"
        }
]

        当前创建的索引没有指定索引名称,所以索引名称是自动命名的;自动命名的索引名称基本是都为:key+下划线+排序方式 。如上述为age_-1。在MongoDB中针对索引的操作分析使用explain()函数来完成。

> db.students.find({"age":21}).explain()
{
        "explainVersion" : "1",
        "queryPlanner" : {
                "namespace" : "mydb.students",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "age" : {
                                "$eq" : 21
                        }
                },
                "queryHash" : "3838C5F3",
                "planCacheKey" : "C3088717",
                "maxIndexedOrSolutionsReached" : false,
                "maxIndexedAndSolutionsReached" : false,
                "maxScansToExplodeReached" : false,
                "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" : [ ]
        },
        "command" : {
                "find" : "students",
                "filter" : {
                        "age" : 21
                },
                "$db" : "mydb"
        },
        "serverInfo" : {
                "host" : "DESKTOP-NSVNGI9",
                "port" : 27001,
                "version" : "5.0.5",
                "gitVersion" : "d65fd89df3fc039b5c55933c0f71d647a54510ae"
        },
        "serverParameters" : {
                "internalQueryFacetBufferSizeBytes" : 104857600,
                "internalQueryFacetMaxOutputDocSizeBytes" : 104857600,
                "internalLookupStageIntermediateDocumentMaxSizeBytes" : 104857600,
                "internalDocumentSourceGroupMaxMemoryBytes" : 104857600,
                "internalQueryMaxBlockingSortMemoryUsageBytes" : 104857600,
                "internalQueryProhibitBlockingMergeOnMongoS" : 0,
                "internalQueryMaxAddToSetBytes" : 104857600,
                "internalDocumentSourceSetWindowFieldsMaxMemoryBytes" : 104857600
        },
        "ok" : 1
}

        当使用创建了索引的字段作为查询条件来做查询操作时,在索引分析中可以看到"stage":"IXSCAN"为索引扫描;但使用无索引的字段或者无索引字段和索引字段相结合做为查询条件,在索引分析中"stage":"COLLSCAN"为集合扫描,也就是全表扫描。其中索引分析中keyPattern指定的时索引字段的排序方式。

通配符索引:创建通配符索引{ "$**" : 1 }。创建通配符索引时,不能指定降序(-1)索引。对于降序索引指定-1的值,从3.6开始,就不能指定*作为索引名。

# 创建通配符索引时,使用降序的报错展示
> db.students.createIndex({"$**":-1})
{
        "ok" : 0,
        "errmsg" : "Error in specification { key: { $**: -1.0 }, name: \"$**_-1\" } :: caused by :: A numeric value in a $** index key pattern must be positive.",
        "code" : 67,
        "codeName" : "CannotCreateIndex"
}

# 通配符索引
> db.students.createIndex({"$**":1})
{
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}

若要实现多字段查询走索引扫描,则可以创建复合索引。

> db.students.createIndex({"age":1,"score":-1})
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}

以上示例都是使用createIndex()函数来创建集合的索引或复合索引。那么若要一次性创建多个索引则可以使用createIndexes()函数来完成。

# 创建一个
> db.students.createIndexes([{"name":1}])
{
        "numIndexesBefore" : 3,
        "numIndexesAfter" : 4,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}
> db.students.dropIndexes()
{
        "nIndexesWas" : 4,
        "msg" : "non-_id indexes dropped for collection",
        "ok" : 1
}
# 创建多个索引
> db.students.createIndexes([{"name":1},{"age":-1}])
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 3,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}
> db.students.dropIndexes()
{
        "nIndexesWas" : 3,
        "msg" : "non-_id indexes dropped for collection",
        "ok" : 1
}
# 创建多个索引,且索引中包含有复合索引
> db.students.createIndexes([{"name":1},{"age":-1},{"age":1,"score":1}])
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 4,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}
db.students.find({"$or":[{"age":20},{"score":90}]}).explain();

 当使用上述索引进行查询时,就会发现没有使用索引,这时可以指定该查询强制使用一次索引:hint() 函数。

db.students.find({"$or":[{"age":20},{"score":90}]}).hint({"age":-1,"score":-1}).explain();

删除索引

# 删除集合中的所有索引
> db.students.dropIndexes()
{
        "nIndexesWas" : 3,
        "msg" : "non-_id indexes dropped for collection",
        "ok" : 1
}

> db.students.createIndex({"age":-1})
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}

# 删除指定的索引
> db.students.dropIndex({"age":-1})
{ "nIndexesWas" : 2, "ok" : 1 }

唯一索引(unique)

        主要目的是作用在某一个字段中,创建唯一索引,以便集合不接受索引键值与索引中现有值相匹配的文档的插入或更新。指定true创建唯一索引。默认为false。

db.students.createIndex({"name":1},{"unique",true})

过期索引(expireAfterSeconds)

        指定一个以秒为单位的值,作为TTL来控制MongoDB在这个集合中保留文档的时间。存储的时间有效期的数据;但MongoDB设置的这个时间往往不怎么准确。

db.token.createIndex({"time":1},{"expireAfterSeconds":10})
# 要实现过期索引,需要一个保存时间信息。
db.token.insert({"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQi","time":new Date()})

全文索引(text)

        在一些信息管理平台上,经常需要进行信息的模糊查询,最早的时候是利用了在某些字段上来实现的模糊查询。这时返回的信息并不会很准确。因为只能匹配某个单个字段的内容。而MongoDB中实现了非常简单的全文检索。

> db.news.insert({"title":"万年大秦","context":"大秦万年"});
WriteResult({ "nInserted" : 1 })
> db.news.insert({"title":"大秦万年","context":"万年大秦"});
WriteResult({ "nInserted" : 1 })
> db.news.insert({"title":"盛世大唐","context":"大唐盛世"});
WriteResult({ "nInserted" : 1 })
> db.news.insert({"title":"万年大秦盛世大唐","context":"大秦万年大唐盛世"});
WriteResult({ "nInserted" : 1 })

# 设置全文检索
> db.news.createIndex({"title":"text","context":"text"});
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}

        若要表示出全文检索,则使用"$text"判断符;而要数据查询,则使用"$search"运算符。

# 查询指定的关键字:{"$search":"查询关键字"}
> db.news.find({"$text":{"$search":"大秦万年"}})
{ "_id" : ObjectId("61e0dfe9dd032921c50c5777"), "title" : "大秦万年", "context" : "万年大秦" }
{ "_id" : ObjectId("61e0dfe1dd032921c50c5776"), "title" : "万年大秦", "context" : "大秦万年" }

# 查询多个关键字(或关系):{"$search":"查询关键字 查询关键字 查询关键字..."}
> db.news.find({"$text":{"$search":"大秦万年 万年大秦"}})
{ "_id" : ObjectId("61e0dfe9dd032921c50c5777"), "title" : "大秦万年", "context" : "万年大秦" }
{ "_id" : ObjectId("61e0dfe1dd032921c50c5776"), "title" : "万年大秦", "context" : "大秦万年" }

# 查询多个关键字(与关系):{"$search":"\"查询关键字\"\"查询关键字\"..."}
> db.news.find({"$text":{"$search":"\"大秦万年大唐盛世\""}}))))))
{ "_id" : ObjectId("61e0dff7dd032921c50c5779"), "title" : "万年大秦盛世大唐", "context" : "大秦万年大唐盛世" }

# 查询多个关键字(排除某一个):{"$search":"查询关键字 查询关键字... -排除关键字"}
> db.news.find({"$text":{"$search":"大唐盛世 -大秦万年"}})
{ "_id" : ObjectId("61e0dff0dd032921c50c5778"), "title" : "盛世大唐", "context" : "大唐盛世" }

        在进行MongoDB的全文检索时,还可以使用"$meta"相似度的打分来判断检索成果。

db.news.find({"$text":{"$search":"大秦万年"}},{"score":{"$meta":"textScore"}})
db.news.find({"$text":{"$search":"大秦万年"}},{"score":{"$meta":"textScore"}}).sort({"score":{"$meta":"textScore"}})

        按照打分的成绩排列,可以实现更加精准的信息检索。为避免字段过多而每个字段都要书写的繁琐,MongoDB提供了一种简单的为所有字段都添加全文检索的方式。但速度较慢。

# 为所有字段设置全文检索
db.news.createIndex({"$**":"text"});

地理信息索引(2dsphere

        地理信息索引分为两类:2D索引,2DSphere球面索引。在2D索引中基本上能够保存的信息都是坐标(经纬度)

> db.shops.insert({"shopName":"A","location":[110,110]})
WriteResult({ "nInserted" : 1 })
> db.shops.insert({"shopName":"B","location":[111,111]})
WriteResult({ "nInserted" : 1 })
> db.shops.insert({"shopName":"C","location":[112,112]})
WriteResult({ "nInserted" : 1 })
> db.shops.insert({"shopName":"D","location":[10,10]})
WriteResult({ "nInserted" : 1 })
# 为shops集合定义2D索引
> db.shops.createIndex({"location": "2d"});
{
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "createdCollectionAutomatically" : false,
        "ok" : 1
}

要进行坐标位置的查询有两种方式:
        $near:查询距离某个点最近的坐标。
        $geoWithin:查询某个形状内的点。

# 查询距离我位置[110,111]最近的商铺
> db.shops.find({"location":{"$near":[110,111]}})
{ "_id" : ObjectId("61e0ee23dd032921c50c577b"), "shopName" : "A", "location" : [ 110, 110 ] }
{ "_id" : ObjectId("61e0ee23dd032921c50c577c"), "shopName" : "B", "location" : [ 111, 111 ] }
{ "_id" : ObjectId("61e0ee70dd032921c50c577d"), "shopName" : "C", "location" : [ 112, 112 ] }
{ "_id" : ObjectId("61e0ee73dd032921c50c577e"), "shopName" : "D", "location" : [ 10, 10 ] }

上述语句,查询的结果是将集合中前100条数据全部返回。那么就需要设置一个距离范围。使用$maxDistance 返回的坐标点数。

> db.shops.find({"location":{"$near":[110,111],"$maxDistance": 2}})
{ "_id" : ObjectId("61e0ee23dd032921c50c577b"), "shopName" : "A", "location" : [ 110, 110 ] }
{ "_id" : ObjectId("61e0ee23dd032921c50c577c"), "shopName" : "B", "location" : [ 111, 111 ] }

注:在2D索引中支持最大距离,但不支持最小距离。

使用$geoWithin查询一个范围,范围包括:

  •  $box(矩形范围):{"$box":[[x1,y1],[x2,y2]]}
  • $center(圆形范围):{"$center":[[x,y],r]}
  • $polygon(多边形范围):{"polygon":[[x1,y1],[x2,y2],[x3,y3]....]}
# 矩形范围
> db.shops.find({"location":{"$geoWithin":{"$box":[[88,88],[120,120]]}}});
{ "_id" : ObjectId("61e0ee23dd032921c50c577b"), "shopName" : "A", "location" : [ 110, 110 ] }
{ "_id" : ObjectId("61e0ee23dd032921c50c577c"), "shopName" : "B", "location" : [ 111, 111 ] }
{ "_id" : ObjectId("61e0ee70dd032921c50c577d"), "shopName" : "C", "location" : [ 112, 112 ] }
# 圆形范围
> db.shops.find({"location":{"$geoWithin":{"$center":[[110,110], 1]}}})
{ "_id" : ObjectId("61e0ee23dd032921c50c577b"), "shopName" : "A", "location" : [ 110, 110 ] }

聚合(Aggregation)

        MongoDB的产生背景是在大数据环境下产生的,所谓的大数据实际上也就是进行的信息收集汇总;那么必须有信息的统计操作,这个统计操作就称之为聚合。

# 取得集合数据量
> db.shops.count()
4
> db.students.count({"name":/赵/})
1

# 去除重复数据
> db.runCommand({"distinct": "students", "key": "name"});
{ "values" : [ "张三", "李四", "王五", "秦六", "苟二", "赵一" ], "ok" : 1 }
> db.students.distinct("name")
[ "张三", "李四", "王五", "秦六", "苟二", "赵一" ]

        在MongoDB中,runCommand() 这个函数可以执行所有的特定的MongoDB命令。

$group

        主要进行分组的数据操作。所有的分组操作都是无序的,且都是在内存中完成的。所以不可能支持大数据量进行聚合操作。

        在整个框架中要引用每行数据的使用:"$字段名称"

# 准备一些测试数据
> db.emps.insert({"name":"苟二","age":27,"job":"程序员","salary":15000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"张三","age":26,"job":"程序员","salary":14000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"李四","age":25,"job":"程序员","salary":15000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"王五","age":28,"job":"经理","salary":20000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"赵六","age":29,"job":"程序员","salary":18000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"田七","age":27,"job":"测试","salary":15000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"王八","age":28,"job":"测试","salary":15000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"周九","age":26,"job":"前端","salary":16000})
WriteResult({ "nInserted" : 1 })
> db.emps.insert({"name":"小明","age":25,"job":"架构师","salary":20000})
WriteResult({ "nInserted" : 1 })
# 实现聚合查询
> db.emps.aggregate({"$group":{"_id": "$job", "job_count": {"$sum":1}}});
{ "_id" : "程序员", "job_count" : 4 }
{ "_id" : "测试", "job_count" : 2 }
{ "_id" : "架构师", "job_count" : 1 }
{ "_id" : "经理", "job_count" : 1 }
{ "_id" : "前端", "job_count" : 1 }

# 查询每个职位的总工资
> db.emps.aggregate({"$group":{"_id": "$job", "job_salary": {"$sum":"$salary"}}})
{ "_id" : "程序员", "job_salary" : 62000 }
{ "_id" : "测试", "job_salary" : 30000 }
{ "_id" : "架构师", "job_salary" : 20000 }
{ "_id" : "经理", "job_salary" : 20000 }
{ "_id" : "前端", "job_salary" : 16000 }

# 查询每个职位的总工资和平均工资
> db.emps.aggregate({"$group":{"_id": "$job", "job_salary": {"$sum":"$salary"}, "job_avg":{"$avg": "$salary"}}})
{ "_id" : "测试", "job_salary" : 30000, "job_avg" : 15000 }
{ "_id" : "程序员", "job_salary" : 62000, "job_avg" : 15500 }
{ "_id" : "经理", "job_salary" : 20000, "job_avg" : 20000 }
{ "_id" : "架构师", "job_salary" : 20000, "job_avg" : 20000 }
{ "_id" : "前端", "job_salary" : 16000, "job_avg" : 16000 }

# 查询每个职位的最高、最低工资
> db.emps.aggregate({"$group":{"_id": "$job", "max_salary": {"$max":"$salary"}, "min_salary":{"$min": "$salary"}}})
{ "_id" : "测试", "max_salary" : 15000, "min_salary" : 15000 }
{ "_id" : "程序员", "max_salary" : 18000, "min_salary" : 14000 }
{ "_id" : "经理", "max_salary" : 20000, "min_salary" : 20000 }
{ "_id" : "前端", "max_salary" : 16000, "min_salary" : 16000 }
{ "_id" : "架构师", "max_salary" : 20000, "min_salary" : 20000 }

# 查询出每个职位的工资(数组显示)
> db.emps.aggregate({"$group":{"_id": "$job", "salary_data": {"$push":"$salary"}}})
{ "_id" : "程序员", "salary_data" : [ 15000, 14000, 15000, 18000 ] }
{ "_id" : "测试", "salary_data" : [ 15000, 15000 ] }
{ "_id" : "架构师", "salary_data" : [ 20000 ] }
{ "_id" : "经理", "salary_data" : [ 20000 ] }
{ "_id" : "前端", "salary_data" : [ 16000 ] }

# 查询出每个职位的员工姓名、工资(数组显示)
> db.emps.aggregate({"$group":{"_id": "$job", "name_data": {"$push":"$name"}, "salary_data": {"$push":"$salary"}}})
{ "_id" : "测试", "name_data" : [ "田七", "王八" ], "salary_data" : [ 15000, 15000 ] }
{ "_id" : "程序员", "name_data" : [ "苟二", "张三", "李四", "赵六" ], "salary_data" : [ 15000, 14000, 15000, 18000 ] }
{ "_id" : "经理", "name_data" : [ "王五" ], "salary_data" : [ 20000 ] }
{ "_id" : "前端", "name_data" : [ "周九" ], "salary_data" : [ 16000 ] }
{ "_id" : "架构师", "name_data" : [ "小明" ], "salary_data" : [ 20000 ] }

        使用$push可以将数据变成数据进行保存,但若数据有重复时,同样也会重复展示。那么在MongoDB中提供的取消重复的设置则使用$addToSet

# 添加一条重复数据
> db.emps.insert({"name":"苟二","age":25,"job":"程序员","salary":14000})
WriteResult({ "nInserted" : 1 })

# 使用$addToSet
> db.emps.aggregate({"$group":{"_id": "$job", "name_data": {"$addToSet":"$name"}}})
{ "_id" : "经理", "name_data" : [ "王五" ] }
{ "_id" : "前端", "name_data" : [ "周九" ] }
{ "_id" : "架构师", "name_data" : [ "小明" ] }
{ "_id" : "程序员", "name_data" : [ "张三", "赵六", "李四", "苟二" ] }
{ "_id" : "测试", "name_data" : [ "田七", "王八" ] }

        那么以上的数组保存展示要保存第一个或者最后一个则使用 $first 或 $last

# 全部没去重
> db.emps.aggregate({"$group":{"_id": "$job", "name_data": {"$push":"$name"}}})
{ "_id" : "程序员", "name_data" : [ "苟二", "张三", "李四", "赵六", "苟二" ] }
{ "_id" : "测试", "name_data" : [ "田七", "王八" ] }
{ "_id" : "架构师", "name_data" : [ "小明" ] }
{ "_id" : "经理", "name_data" : [ "王五" ] }
{ "_id" : "前端", "name_data" : [ "周九" ] }
# 第一个
> db.emps.aggregate({"$group":{"_id": "$job", "name_data": {"$first":"$name"}}})
{ "_id" : "程序员", "name_data" : "苟二" }
{ "_id" : "测试", "name_data" : "田七" }
{ "_id" : "架构师", "name_data" : "小明" }
{ "_id" : "经理", "name_data" : "王五" }
{ "_id" : "前端", "name_data" : "周九" }
# 最后一个
> db.emps.aggregate({"$group":{"_id": "$job", "name_data": {"$last":"$name"}}})
{ "_id" : "程序员", "name_data" : "苟二" }
{ "_id" : "测试", "name_data" : "王八" }
{ "_id" : "架构师", "name_data" : "小明" }
{ "_id" : "经理", "name_data" : "王五" }
{ "_id" : "前端", "name_data" : "周九" }

$project(控制列的展示)

  • 普通列{字段:1/true}:表示要显示的内容。
  • _id列{"_id": 0/false}:表示_id列的显示控制
  • 条件过滤列{字段:表达式}:满足表达式之后的数据才可以展示
> db.emps.aggregate({"$project":{"_id":0, "name":1, "job":1}})
{ "name" : "苟二", "job" : "程序员" }
{ "name" : "张三", "job" : "程序员" }
{ "name" : "李四", "job" : "程序员" }
{ "name" : "王五", "job" : "经理" }
{ "name" : "赵六", "job" : "程序员" }
{ "name" : "田七", "job" : "测试" }
{ "name" : "王八", "job" : "测试" }
{ "name" : "周九", "job" : "前端" }
{ "name" : "小明", "job" : "架构师" }
{ "name" : "苟二", "job" : "程序员" }

        根据以上语句就会发现,只有设置进去的列才会展示,其它的列不进行展示。实际上这就属于数据库的投影机制。

        在进行数据投影的过程中也支持四则运算:加法($add)减法($substract)乘法($multiply)除法(divide)求模($mod)

> db.emps.aggregate({"$project":{"_id":0, "name":1, "job":1, "salary": {"年薪": {"$multiply": ["$salary", 12]}}}})
{ "name" : "苟二", "job" : "程序员", "salary" : { "年薪" : 180000 } }
{ "name" : "张三", "job" : "程序员", "salary" : { "年薪" : 168000 } }
{ "name" : "李四", "job" : "程序员", "salary" : { "年薪" : 180000 } }
{ "name" : "王五", "job" : "经理", "salary" : { "年薪" : 240000 } }
{ "name" : "赵六", "job" : "程序员", "salary" : { "年薪" : 216000 } }
{ "name" : "田七", "job" : "测试", "salary" : { "年薪" : 180000 } }
{ "name" : "王八", "job" : "测试", "salary" : { "年薪" : 180000 } }
{ "name" : "周九", "job" : "前端", "salary" : { "年薪" : 192000 } }
{ "name" : "小明", "job" : "架构师", "salary" : { "年薪" : 240000 } }
{ "name" : "苟二", "job" : "程序员", "salary" : { "年薪" : 168000 } }

除四则运算之外,同样也支持一下运算符。进行运算的字段或值区分大小写:

  • 关系运算:大于($gt)大于等于($gte)小于($lt)小于等于($lte)不等于($ne)等于($eq)大小比较($cmp)判空($isNull)返回的都是布尔值
  • 逻辑运算:与($and)($or)($not)
  • 字符串运算:连接($concat)截取($substr)转小写($toLower)转大写($toUpper)不区分大小写比较($strcasecmp)
> db.emps.aggregate({"$project":{"_id":0, "name":1, "job":1, "薪资":"$salary", "salary": {"$gte": ["$salary", 15000]}}})
{ "name" : "苟二", "job" : "程序员", "薪资" : 15000, "salary" : true }
{ "name" : "张三", "job" : "程序员", "薪资" : 14000, "salary" : false }
{ "name" : "李四", "job" : "程序员", "薪资" : 15000, "salary" : true }
{ "name" : "王五", "job" : "经理", "薪资" : 20000, "salary" : true }
{ "name" : "赵六", "job" : "程序员", "薪资" : 18000, "salary" : true }
{ "name" : "田七", "job" : "测试", "薪资" : 15000, "salary" : true }
{ "name" : "王八", "job" : "测试", "薪资" : 15000, "salary" : true }
{ "name" : "周九", "job" : "前端", "薪资" : 16000, "salary" : true }
{ "name" : "小明", "job" : "架构师", "薪资" : 20000, "salary" : true }
{ "name" : "苟二", "job" : "程序员", "薪资" : 14000, "salary" : false }

$sort(排序)

> db.emps.aggregate([{"$sort": {"age": -1, "salary": 1}}]);
{ "_id" : ObjectId("61e11724dd032921c50c5783"), "name" : "赵六", "age" : 29, "job" : "程序员", "salary" : 18000 }
{ "_id" : ObjectId("61e11724dd032921c50c5785"), "name" : "王八", "age" : 28, "job" : "测试", "salary" : 15000 }
{ "_id" : ObjectId("61e11724dd032921c50c5782"), "name" : "王五", "age" : 28, "job" : "经理", "salary" : 20000 }
{ "_id" : ObjectId("61e1170fdd032921c50c577f"), "name" : "苟二", "age" : 27, "job" : "程序员", "salary" : 15000 }
{ "_id" : ObjectId("61e11724dd032921c50c5784"), "name" : "田七", "age" : 27, "job" : "测试", "salary" : 15000 }
{ "_id" : ObjectId("61e11716dd032921c50c5780"), "name" : "张三", "age" : 26, "job" : "程序员", "salary" : 14000 }
{ "_id" : ObjectId("61e11724dd032921c50c5786"), "name" : "周九", "age" : 26, "job" : "前端", "salary" : 16000 }
{ "_id" : ObjectId("61e119cbdd032921c50c5788"), "name" : "苟二", "age" : 25, "job" : "程序员", "salary" : 14000 }
{ "_id" : ObjectId("61e1171ddd032921c50c5781"), "name" : "李四", "age" : 25, "job" : "程序员", "salary" : 15000 }
{ "_id" : ObjectId("61e11726dd032921c50c5787"), "name" : "小明", "age" : 25, "job" : "架构师", "salary" : 20000 }

# 整合
> db.emps.aggregate([{"$match": {"salary":{"$gt": 15000, "$lt": 19000}}},{"$project": {"_id":0, "name":1, "job":1,"salary":1}},{"$group": {"_id": "$job", "name_data": {"$push":"$name"}}},{"$sort": {"age": -1, "salary": 1}}])
{ "_id" : "程序员", "name_data" : [ "赵六" ] }
{ "_id" : "前端", "name_data" : [ "周九" ] }

$unwind

        在查询数据时经常返回数组信息,但数组信息并不方便信息的浏览;所以使用"$unwind"可以将数组信息转化成为独立的字符串内容。

> db.students.aggregate([{"$unwind": "$course"}])
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : "C++" }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : "C#" }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : "Java" }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : "JavaScript" }
{ "_id" : ObjectId("61dfbd6b5d74d37549b18e57"), "name" : "李四", "age" : 19, "sex" : "男", "score" : 50, "course" : "Vue" }
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : "C#" }
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : "Java" }
{ "_id" : ObjectId("61dfd3615d74d37549b18e58"), "name" : "王五", "age" : 19, "sex" : "男", "score" : 80, "course" : "Vue" }

$geoNear(取附近坐标点)

做个标记

        这个一直没试成功,总是报错。过几天再研究吧。把官网MongoDB 5.0 的示例粘贴过来...

db.places.insertMany( [
   {
      name: "Central Park",
      location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
      category: "Parks"
   },
   {
      name: "Sara D. Roosevelt Park",
      location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },
      category: "Parks"
   },
   {
      name: "Polo Grounds",
      location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
      category: "Stadiums"
   }
] )
db.places.aggregate([
   {
     $geoNear: {
        near: { type: "Point", coordinates: [ -73.99279 , 40.719296 ] },
        distanceField: "dist.calculated",
        maxDistance: 2,
        query: { category: "Parks" },
        includeLocs: "dist.location",
        spherical: true
     }
   }
])

$out

        输出,利用此函数可以将查询结果输出到集合中。

> db.emps.aggregate([{"$project":{"_id":0, "name":1, "job":1}},{"$out": "newEmps"}])
> db.newEmps.find()
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3bd"), "name" : "苟二", "job" : "程序员" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3be"), "name" : "张三", "job" : "程序员" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3bf"), "name" : "李四", "job" : "程序员" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c0"), "name" : "王五", "job" : "经理" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c1"), "name" : "赵六", "job" : "程序员" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c2"), "name" : "田七", "job" : "测试" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c3"), "name" : "王八", "job" : "测试" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c4"), "name" : "周九", "job" : "前端" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c5"), "name" : "小明", "job" : "架构师" }
{ "_id" : ObjectId("61e12611a5c6ba679d2ac3c6"), "name" : "苟二", "job" : "程序员" }

固定集合

        所谓固定集合指的是规定的集合大小。若保存的内容超过集合的长度,会采用LRU的算法(最近最少使用的原则)将最早的数据进行移除,从而保存新的数据。

        默认情况下创建集合使用createCollection()函数或增加数据之后自动创建。要使用固定的集合,就必须明确的创建一个空集合。

> db.createCollection("cappedCol",{"capped": true,"size": 1024,"max": 5})
{ "ok" : 1 }
> show collections
cappedCol
emps
myclt
newEmps
news
shops
students
> db.cappedCol.insert({"name":"苟二","age":25,"job":"程序员","salary":14000})
WriteResult({ "nInserted" : 1 })
> db.cappedCol.insert({"name":"张三","age":26,"job":"程序员","salary":14000})
WriteResult({ "nInserted" : 1 })
> db.cappedCol.insert({"name":"李四","age":25,"job":"程序员","salary":15000})
WriteResult({ "nInserted" : 1 })
> db.cappedCol.insert({"name":"王五","age":28,"job":"经理","salary":20000})
WriteResult({ "nInserted" : 1 })
> db.cappedCol.insert({"name":"赵六","age":29,"job":"程序员","salary":18000})
WriteResult({ "nInserted" : 1 })

# 执行第六条添加操作后,会将最早添加的数据删除掉
> db.cappedCol.insert({"name":"田七","age":27,"job":"测试","salary":15000})
WriteResult({ "nInserted" : 1 })
> db.cappedCol.find()
{ "_id" : ObjectId("61e12723dd032921c50c578a"), "name" : "张三", "age" : 26, "job" : "程序员", "salary" : 14000 }
{ "_id" : ObjectId("61e12723dd032921c50c578b"), "name" : "李四", "age" : 25, "job" : "程序员", "salary" : 15000 }
{ "_id" : ObjectId("61e12723dd032921c50c578c"), "name" : "王五", "age" : 28, "job" : "经理", "salary" : 20000 }
{ "_id" : ObjectId("61e12723dd032921c50c578d"), "name" : "赵六", "age" : 29, "job" : "程序员", "salary" : 18000 }
{ "_id" : ObjectId("61e1272fdd032921c50c578e"), "name" : "田七", "age" : 27, "job" : "测试", "salary" : 15000 }

GridFS

        在MongoDB中支持大数据的存储(例如:图片、音乐、各种二进制数据)但这种做法需要用户自己进行数据处理,使用"mogofiles"命令完成。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值