好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

MongoDB实现查询、分页和排序操作以及游标的使用

一、Find查询

事前准备:插入如下数据

?

1

2

3

4

5

6

7

8

9

10

db.Students. insert ([

{ _id:1,  name : "Zhao" , age:25, country: "USA" , books:[ "JS" , "C++" , "EXTJS" , "MONGODB" ]},

{ _id:2, name : "Qian" ,age:22, country: "USA" , books:[ "PHP" , "JAVA" , "EXTJS" , "C++" ]},

{ _id:3, name : "Sun" ,age:26, country: "USA" , books:[ "JS" , "JAVA" , "C#" , "MONGODB" ]},

{ _id:4, name : "Li" ,age:27,country: "China" ,books:[ "JS" , "JAVA" , "EXTJS" , "MONGODB" ]},

{ _id:5, name : "Zhou" , age:30,country: "China" ,books:[ "JS" , "C#" , "PHP" , "MONGODB" ]},

{ _id:6, name : "Wu" , age:27, country: "Japan" , books:[ "JS" , "JAVA" , "C++" , "MONGODB" ]},

{ _id:7, name : "Zheng" , age:27, country: "UK" , books:[ "JS" , "JAVA" , "EXTJS" , "PHP" ]},

{ _id:8, name : "Wang" , age:26,  country: "Korea" ,books:[ "JS" , "C#" , "EXTJS" , "MONGODB" ]}

])

1.指定返回的键

db.[文档名].find ({条件},{键指定})

查询出所有数据的指定键(name ,age ,country)

?

1

db.Students.find({},{ name :1,age:1,country:1,_id:0})

※条件不写就是查询全部 ※需要查询的就在键后指定为1,不用就指定为0(感觉只要想查的键后面有值不见得非得是1) ※如果不指定显示=式_id:0,那查询过程都是带有_id的

2.查询条件

比较操作符

意义

举例

$lt

<

查询出id小于5的学生

> db.Students.find({_id:{$lt:5}},{})

$lte

<=

查询出年龄小于等于25岁之间的学生

> db.Students.find({age:{$lte:25}},{})

$ne

!=

查询出国家不是中国的学生

> db.Students.find({country:{$ne:"China"}},{})

$gt

>

查询所有年纪大于27岁的,中国学生名字

> db.Students.find({age:{$gt:27}},{name:1,country:1,age:1})

{ "_id" : 5, "name" : "Zhou", "age" : 30, "country" : "China" }

$gte

>=

同上

3.包含或不包含

较操作符

意义

举例

$in

包含

查询国家是中国和美国的学生

> db.Students.find({country:{$in:["China","USA"]}},{})

$nin

不包含

查询年龄不是27岁的学生

> db.Students.find({age:{$nin:[27]}},{})

4.OR查询

较操作符

意义

举例

$or

包含

查询年龄小于27岁,或者国家是美国的学生

>db.Students.find({$or:[{age:{$lt:27}},{country:"USA"}]},{})

查询年龄大于等于30岁,或者国家是不是美国的学生

>db.Students.find({$or:[{age:{$gte:30}},{country:{$nin:["China"]}}]},{})

5.Null

为所有美国学生添加性别属性为男性(M)

?

1

> db.Students. update ({country: "USA" },{$ set :{sex: "M" }}, false , true )

查询所有sex属性为null的学生

?

1

> db.Students.find({sex:{$ in :[ null ]}},{ name :1,country:1})

6.正则查询

查询出名字中存在]Zh]的学生的信息

?

1

2

3

4

> db.Students.find({ name :/Zh/},{})

{ "_id" : 1, "name" : "Zhao" , "age" : 25, "country" : "USA" , "books" : [ "JS" , "C++" , "EXTJS" , "MONGODB" ], "sex" : "M" }

{ "_id" : 5, "name" : "Zhou" , "age" : 30, "country" : "China" , "books" : [ "JS" , "C#" , "PHP" , "MONGODB" ] }

{ "_id" : 7, "name" : "Zheng" , "age" : 27, "country" : "UK" , "books" : [ "JS" , "JAVA" , "EXTJS" , "PHP" ] }

7.$not的使用

※$not和$nin的区别是$not可以用在任何地方儿$nin是用到集合上的

查找出名字中不存在[Zh]的学生信息

?

1

2

3

4

5

6

> db.Students.find({ name :{$ not :/Zh/}},{})

{ "_id" : 2, "name" : "Qian" , "age" : 22, "country" : "USA" , "books" : [ "PHP" , "JAVA" , "EXTJS" , "C++" ], "sex" : "M" }

{ "_id" : 3, "name" : "Sun" , "age" : 26, "country" : "USA" , "books" : [ "JS" , "JAVA" , "C#" , "MONGODB" ], "sex" : "M" }

{ "_id" : 4, "name" : "Li" , "age" : 27, "country" : "China" , "books" : [ "JS" , "JAVA" , "EXTJS" , "MONGODB" ] }

{ "_id" : 6, "name" : "Wu" , "age" : 27, "country" : "Japan" , "books" : [ "JS" , "JAVA" , "C++" , "MONGODB" ] }

{ "_id" : 8, "name" : "Wang" , "age" : 26, "country" : "Korea" , "books" : [ "JS" , "C#" , "EXTJS" , "MONGODB" ] }

8.数组查询$all和index应用

查询所有拥有JS和PHP书籍的同学

?

1

2

3

> db.Students.find({books:{$ all :[ "JS" , "PHP" ]}},{})

{ "_id" : 5, "name" : "Zhou" , "age" : 30, "country" : "China" , "books" : [ "JS" , "C#" , "PHP" , "MONGODB" ] }

{ "_id" : 7, "name" : "Zheng" , "age" : 27, "country" : "UK" , "books" : [ "JS" , "JAVA" , "EXTJS" , "PHP" ] }

查询第三本书是C#的同学

?

1

2

> db.Students.find({ "books.2" : "C#" },{})

{ "_id" : 3, "name" : "Sun" , "age" : 26, "country" : "USA" , "books" : [ "JS" , "JAVA" , "C#" , "MONGODB" ], "sex" : "M" } 

上面那个使用index来查询的例子中,"books.2"一定要用""包含起来

9.查询指定长度数组$size

它不能与比较查询符一起使用(这是弊端)

插入一条book数组有两本数的同学

?

1

2

> db.Students. insert ({_id:9, name : "Xu" ,age:26,country: "Japan" ,books:[ "C#" , "PHP" ]})

WriteResult({ "nInserted" : 1 })

查询只有两本书的同学

?

1

2

> db.Students.find({books:{$ size :2}},{})

{ "_id" : 9, "name" : "Xu" , "age" : 26, "country" : "Japan" , "books" : [ "C#" , "PHP" ] }

查询名字是[Li]的喜欢的书的数量

?

1

2

> var person = db.Students.find({ name : "Li" })

> while(person.hasNext()){ obj = person. next (); print(obj.books.length) }

10.$slice操作符返回文档中指定数组的内部值

查询名字为[Wang]书架中第1~3本书

?

1

2

> db.Students.find({ name : "Wang" },{books:{$slice:[0,3]}})

{ "_id" : 8, "name" : "Wang" , "age" : 26, "country" : "Korea" , "books" : [ "JS" , "C#" , "EXTJS" ] }

查询出最后一本书

?

1

2

> db.Students.find({ name : "Wang" },{books:{$slice:-1}})

{ "_id" : 8, "name" : "Wang" , "age" : 26, "country" : "Korea" , "books" : [ "MONGODB" ] } 

11.文档查询

添加一个对象数组到[Li]同学,记录[Li]同学的成绩

?

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

> var li = [{

 

... subject : "Math" ,

 

... score: 90

 

... },{

 

... subject : "English" ,

 

... score:85

 

... },{

 

... subject : "History" ,

 

... score:95

 

... }]

 

> db.Students. update ({ name : "Li" },{$ set :{school:li}})

 

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

 

> db.Students.find({ name : "Li" },{})

 

{ "_id" : 4, "name" : "Li" , "age" : 27, "country" : "China" , "books" : [ "JS" , "JAVA" , "EXTJS" , "MONGODB" ],

 

  "school" : [{ "subject" : "Math" , "score" : 90 },{ "subject" : "English" , "score" : 85 }, { "subject" : "History" , "score" : 95 }]

}

 

>

查询参加了数学考试,并且分数为90的同学

①.绝对匹配可以

?

1

2

> db.Students.find({school:{subject: "Math" ,score:90}},{_id:0, name :1})

{ "name" : "Li" }  

但是问题存在如下:

条件顺序变化时候,

?

1

2

> db.Students.find({school:{score:90,subject: "Math" }},{_id:0, name :1})

> --查不到东西--

条件数目不一致的时候,也同样查不到

②.为了解决顺序的问题我可以用对象[.]

?

1

2

> db.Students.find({ "school.subject" : "Math" , "school.score" :90},{ name :1})

{ "_id" : 4, "name" : "Li" }

这种方式支持顺序的变化,但是也同样存在问题,那就是匹配的问题,条件不是作为一对条件来进行匹配的

例如:

?

1

2

> db.Students.find({ "school.subject" : "Math" , "school.score" :85},{ name :1})

{ "_id" : 4, "name" : "Li" } 

这里的85分是英语成绩

③.正确做法单条条件组查询$elemMatch

?

1

2

3

4

5

6

7

> db.Students.find({school:{$elemMatch:{subject: "Math" ,score:90}}},{ name :1})

{ "_id" : 4, "name" : "Li" }

> db.Students.find({school:{$elemMatch:{score:90,subject: "Math" }}},{ name :1})

{ "_id" : 4, "name" : "Li" }

> db.Students.find({school:{$elemMatch:{subject: "Math" }}},{ name :1})

{ "_id" : 4, "name" : "Li" }

>

二、分页与排序

1.Limit返回指定的数据条数

查询出Student文档中前5条数据

?

1

> db.Students.find().limit(5)

 

2.Skip返回指定数据的跨度

查询出persons文档中3~8条的数据

?

1

> db.Students.find().limit(5).skip(2)

3.Sort返回按照年龄排序的数据[1,-1]

查询所有数据,按照年龄排序

正序

?

1

2

3

4

5

6

7

8

9

10

> db.Students.find({},{_id:0,age:1, name :1}).sort({age:1})

{ "name" : "Qian" , "age" : 22 }

{ "name" : "Zhao" , "age" : 25 }

{ "name" : "Sun" , "age" : 26 }

{ "name" : "Wang" , "age" : 26 }

{ "name" : "Xu" , "age" : 26 }

{ "name" : "Wu" , "age" : 27 }

{ "name" : "Zheng" , "age" : 27 }

{ "name" : "Li" , "age" : 27 }

{ "name" : "Zhou" , "age" : 30 }

倒序

?

1

2

3

4

5

6

7

8

9

10

11

> db.Students.find({},{_id:0,age:1, name :1}).sort({age:-1})

{ "name" : "Zhou" , "age" : 30 }

{ "name" : "Wu" , "age" : 27 }

{ "name" : "Zheng" , "age" : 27 }

{ "name" : "Li" , "age" : 27 }

{ "name" : "Sun" , "age" : 26 }

{ "name" : "Wang" , "age" : 26 }

{ "name" : "Xu" , "age" : 26 }

{ "name" : "Zhao" , "age" : 25 }

{ "name" : "Qian" , "age" : 22 }

>

skip性能不好,可以采用插入时间的做法来弥补,具体方法如下:

1.在每一个记录后面都加入一个插入时间的键值对 2.每次取数据的时候都把取出的最后一个数据的时间保存下来,再传给下一次查询 3.使用db.persons.find({date:{$gt:日期数值}}).limit(取出的数据数目)比较查询取出要分页的数据

三、游标和其他知识

1.利用游标来查询数据

?

1

2

3

4

5

var  persons = db.persons.find();

while(persons.hasNext()){

obj = persons. next ();

       print(obj. name )

  }

2.游标几个销毁条件  

客户端发来信息叫他销毁

游标迭代完毕

默认游标超过10分钟没用也会别清除

3.查询快照

快照后就会针对不变的集合进行游标运动了,看看使用方法.

?

1

db.persons.find({$query:{ name :]Jim]},$snapshot: true })

为什么用快照,以为MongoDB在进行更新的时候,例如添加一些键值对,那么MongoDB的处理不会在原来的索引位置上进行更新操作,而是会把

更新之后的数据,放在末尾,那么就导致了前后两次进行查询时候相同索引对应不同数据的情况

补充:

高级查询选项

$where $query $orderby $maxsan:integer 最多扫描的文档数 $min:doc 查询开始 $max:doc 查询结束 $hint:doc 使用哪个索引 $explain:boolean 统计 $snapshot:boolean 一致快照

到此这篇关于MongoDB实现查询操作的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://HdhCmsTestcnblogs测试数据/dcz2015/p/5251309.html

查看更多关于MongoDB实现查询、分页和排序操作以及游标的使用的详细内容...

  阅读:12次