•Find 详讲
1.指定返回的键
db.[documentName].find ({条件},{键指定})
数据准备db.persion
pretty() 方法以格式化的方式来显示所有文档。
db.books.find().pretty()
1.1 查询出所有数据的指定键(name ,age ,country)
db.persons.find({},{name:1,age:1,country:1,_id:0})
db.persion.find({age:20},{name:""})
第一个参数{age:20} 相当于sql 语句的 where 条件
第二个参数{name:""} 是显示的列;如果不写,相当于select * where id = 11111;
SELECT id,`title` from t_task where id = 23227009;
2.查询条件
比较操作符 |
||
$lt |
< |
{age:{$gte:22,$lte:27}} |
$lte |
<= |
|
$gt |
> |
|
$gte |
>= |
|
$ne |
!= |
{age:{$ne:26}} |
db.persion.find({age : {$gt:20}},{name:"",age:""})
3.查询条件
2.1查询出年龄在25到27岁之间的学生
db.persons.find({age:{$gte:25,$lte:27},{_id:0,age:1})
2.2查询出所有不是韩国籍的学生的数学成绩
db.persons.find({country:{$ne:”Korea”}},{_id:0,m:1})
4包含或不包含
$in或$nin
2.3查询国籍是中国或美国的学生信息
db.persons.find({country:{$in:[“USA”,“China”]}})
db.persion.find({address:{$in:["北京昌平"]}},{_di:0})
2.4查询国籍不是中国或美国的学生信息
db.persons.find({country:{$nin:[“USA”,“China”]}})
5.OR查询
$or
2.4查询语文成绩大于85或者英语大于90的学生信息
db.persons.find({$or:[{c:{$gte:85}},{e:{$gte:90}}]},{_id:0,c:1,e:1})
很容易写错,都是javaScript 格式,注意一下结构,细心一点,不要写错啊
db.persion.find({$or:[{age:{$gte:30}}]})
看一个错误,很容易写错
Error: error: {
"ok" : 0,
"errmsg" : "$or must be an array", 必须是一个数组
"code" : 2,
"codeName" : "BadValue"
}
6.Null
把中国国籍的学生上增加新的键sex
db.person.update({country:”China”},{$set:{sex:”m”}})
2.5查询出sex 等于 null的学生
db.persons.find({sex:{$in:[null]}},{country:1})
db.persion.find({sex:{$nin:[null]}}) 不等于null
db.persion.find({sex:{$in:[null]}}) 等于null
7.正则查询
2.6查询出名字中存在”li”的学生的信息
db.persons.find({name:/li/i},{_id:0,name:1})
8.$not的使用
$not可以用到任何地方进行取反操作
2.7查询出名字中不存在”li”的学生的信息
db.persons.find({name:{$not:/li/i}},{_id:0,name:1})
$not和$nin的区别是$not可以用在任何地方儿$nin是用到集合上的
9.数组查询$all和index应用
2.8查询喜欢看MONGOD和JS的学生
db.persons.find({books:{$all:[“MONGOBD”,”JS”]}},{books:1,_id:0})
db.persion.find({book:{$all:["java","php"]}})
2.9查询第二本书是JAVA的学习信息
db.persons.find({“books.1”:”JAVA”})
db.persion.find({"book.0":"java"})
请注意book.0 需要加引号哦,否则会报错
10.查询指定长度数组$size它不能与比较查询符一起使用(这是弊端)
2.8查询出喜欢的书籍数量是4本的学生
db.persons.find({books:{$size:4}},{_id:0,books:1})
2.9查询出喜欢的书籍数量大于3本的学生
1.增加字段size
db.persons.update({},{$set:{size:4}},false, true)
2.改变书籍的更新方式,每次增加书籍的时候size增加1
db.persons.update({查询器},{$push:{books:”ORACLE”},$inc:{size:1}})
3.利用$gt查询
db.persons.find({size:{$gt:3}})
2.10利用shell查询出Jim喜欢看的书的数量
varpersons = db.persons.find({name:"jim"})
while(persons.hasNext()){
obj= persons.next();
print(obj.books.length)
}
小结
1.mongodb 是NOSQL数据库但是他在文档查询上还是很强大的
2.查询符基本是用到花括号里面的更新符基本是在外面
3.shell是个彻彻底底的JS引擎,但是一些特殊的操作要靠他的
各个驱动包来完成(JAVA,NODE.JS)
11.$slice操作符返回文档中指定数组的内部值
2.11查询出Jim书架中第2~4本书
db.persons.find({name:"jim"},{books:{"$slice":[1,3]}})
db.persion.find({name:"乔峰"},{book:{"$slice":[1,2]}})
查询结果
{ "_id" : ObjectId("5b6158db08e092bfa2d6abbd"), "name" : "乔峰", "book" : [ "javaScript", "php" ] }
{ "_id" : ObjectId("5b615df41e7efa65d6a24a94"), "name" : "乔峰" }
从结果可以看出来,没有book属性也会查询出来;
2.12查询出最后一本书
db.persons.find({name:"jim"},{books:{"$slice":-1},_id:0,name:1})
db.persion.find({name:"乔峰"},{book:{"$slice":-1}})
{ "_id" : ObjectId("5b6158db08e092bfa2d6abbd"), "name" : "乔峰", "book" : [ "php" ] }
{ "_id" : ObjectId("5b615df41e7efa65d6a24a94"), "name" : "乔峰" }
12.文档查询
为jim添加学习简历文档 jim.json
2.13查询出在K上过学的学生
1. 这个我们用绝对匹配可以完成,但是有些问题(找找问题?顺序?总要带着score?)
db.persons.find({school:{school:"K",score:"A"}},{_id:0,school:1})
2.为了解决顺序的问题我可以用对象”.”的方式定位
db.persons.find({"school.score":"A","school.school":"K"},{_id:0,school:1})
3.这样也问题看例子:
db.persons.find({"school.score":"A","school.school":”J”},{_id:0,school:1})
同样能查出刚才那条数据,原因是score和school会去其他对象对比
4.正确做法单条条件组查询$elemMatch
$elemMatch 是对文本文档的查询,如果文档中包含查询的内容,则返回;
1.数组中元素是内嵌文档。
2. 如果多个元素匹配$elemMatch条件,操作符返回数组中第一个匹配条件的元素。
3. 对文档的多条件的查询,满足school:"k", score:"A",相当于 school = "K" and score = “A”
[{
school :"K",
score:"A"
},{
school :"L",
score:"B"
},{
school :"J",
score:"A+"
}]
准备数据
db.hhw.insert({
results: [
{ item: "a", qty: 26, tags: ["blank", "red"], dim_cm: [ 1, 10 ] },
{ item: "a", qty: 27, tags: ["blank", "red"], dim_cm: [ 15, 30 ] },
{ item: "a", qty: 28, tags: ["blank", "red"], dim_cm: [ 50, 70 ] },
{ item: "b", qty: 27, tags: ["blank", "red"], dim_cm: [ 80, 90 ] }
]
});
查询出文档results 中 item 包含 a 的文档
db.hhw.find({results:{ $elemMatch:{item: "a"}}});
db.persons.find({school:{$elemMatch:{school:"K",score:"A"}}})
mongodb中的aggregate(聚合查询)
语法以及参数,该本分转载;
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
>
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$geoNear:输出接近某一地理位置的有序文档。
{"$unwind":"$results"} 将results 拆分,注意,results需要加“”,
{"$match":{"results.item":"a"}} 只返回符合条件的文档。 results是数组,所以需要results.item
db.hhw.aggregate({"$unwind":"$results"},{"$match":{"results.item":"a"}});
//结果,将results拆分成单个集合
{ "_id" : ObjectId("5b62d40b08e092bfa2d6abc6"),
"results" : { "item" : "a", "qty" : 26, "tags" : [ "blank", "red" ], "dim_cm" : [ 1, 10 ] } }
{ "_id" : ObjectId("5b62d40b08e092bfa2d6abc6"),
"results" : { "item" : "a", "qty" : 27, "tags" : [ "blank", "red" ], "dim_cm" : [ 15, 30 ] } }
{ "_id" : ObjectId("5b62d40b08e092bfa2d6abc6"),
"results" : { "item" : "a", "qty" : 28, "tags" : [ "blank", "red" ], "dim_cm" : [ 50, 70 ] } }
将查询的结果集分组 {"$group":{"_id":"$_id","myResult":{"$push":"$results"}}}
db.hhw.aggregate({"$unwind":"$results"},{"$match":{"results.item":"a"}},{"$group":{"_id":"$_id","myResult":{"$push":"$results"}}});
将结果集分组
{ "_id" : ObjectId("5b62d40b08e092bfa2d6abc6"),
"myResult" : [
{ "item" : "a", "qty" : 26, "tags" : [ "blank", "red" ], "dim_cm" : [ 1, 10 ] },
{ "item" : "a", "qty" : 27, "tags" : [ "blank", "red" ], "dim_cm" : [ 15, 30 ] },
{ "item" : "a", "qty" : 28, "tags" : [ "blank", "red" ], "dim_cm" : [ 50, 70 ] }
]}
13.$where
12.查询年龄大于22岁,喜欢看C++书,在K学校上过学的学生信息
复杂的查询我们就可以用$where因为他是万能
但是我们要尽量避免少使用它因为他会有性能的代价
db.persion.find({"$where":function(){
//得到查询结果的每一条文档
var books = this.books;
//得到文档中的school对象
var school = this.school;
//如果年纪>=22
if(this.age > 22){
var php = null;
//遍历书籍
for ( var i = 0; i < books.length; i++) {
if(books[i] == "C++"){
php = books[i];
//如果学校是真
if(school){
for (var j = 0; j < school.length; j++) {
//判断是不是在K上学
if(school[j].school == "K"){
//返回是真
return true;
}
}
break;
}
}
}
}
}})
后续更新
•分页与排序
1.Limit返回指定的数据条数
这个很容易,没什么说的
1.1查询出persons文档中前5条数据
db.persons.find({},{_id:0,name:1}).limit(5)
2.Skip返回指定数据的跨度
2.1查询出persons文档中5~10条的数据
db.persons.find({},{_id:0,name:1}).limit(5).skip(5)
> db.persion.find().limit(3).skip(0)
{ "_id" : ObjectId("5b6158db08e092bfa2d6abbd"), "name" : "乔峰", "book" : [ "java", "javaScript", "php" ], "school" : [ "北京大学", "清华大学", "科技大学" ] }
{ "_id" : ObjectId("5b615bd808e092bfa2d6abbf"), "name" : "小明", "age" : 60, "address" : [ [ "北京昌平", "张家口桥东区" ], "北京昌平", "北京海淀", "三里屯" ] }
{ "_id" : ObjectId("5b615bf108e092bfa2d6abc0"), "age" : 25 }
> db.persion.find().limit(3).skip(1)
{ "_id" : ObjectId("5b615bd808e092bfa2d6abbf"), "name" : "小明", "age" : 60, "address" : [ [ "北京昌平", "张家口桥东区" ], "北京昌平", "北京海淀", "三里屯" ] }
{ "_id" : ObjectId("5b615bf108e092bfa2d6abc0"), "age" : 25 }
{ "_id" : ObjectId("5b615df41e7efa65d6a24a94"), "name" : "乔峰" }
3.Sort返回按照年龄排序的数据[1,-1] (正序,倒序)
db.persons.find({},{_id:0,name:1,age:1}).sort({age:1})
> db.persons.find().sort({age:1})
{ "_id" : ObjectId("5b64022d08e092bfa2d6abc7"), "name" : "张三", "age" : 20 }
{ "_id" : ObjectId("5b64023e08e092bfa2d6abc8"), "name" : "李四", "age" : 30 }
{ "_id" : ObjectId("5b64024608e092bfa2d6abc9"), "name" : "王五", "age" : 40 }
{ "_id" : ObjectId("5b64024a08e092bfa2d6abca"), "name" : "王五", "age" : 40 }
> db.persons.find().sort({age:-1})
{ "_id" : ObjectId("5b64024608e092bfa2d6abc9"), "name" : "王五", "age" : 40 }
{ "_id" : ObjectId("5b64024a08e092bfa2d6abca"), "name" : "王五", "age" : 40 }
{ "_id" : ObjectId("5b64023e08e092bfa2d6abc8"), "name" : "李四", "age" : 30 }
{ "_id" : ObjectId("5b64022d08e092bfa2d6abc7"), "name" : "张三", "age" : 20 }
注意:mongodb的key可以存不同类型的数据排序就也有优先级
最小值
null
数字
字符串
对象/文档
数组
二进制
对象ID
布尔
日期
时间戳à正则 à最大值
4.Limit和Skip完成分页
4.1三条数据位一页进行分页
第一页àdb.persons.find({},{_id:0,name:1}).limit(3).skip(0)
第二页àdb.persons.find({},{_id:0,name:1}).limit(3).skip(3)
4.2skip有性能问题,没有特殊情况下我们也可以换个思路
对文档进行重新解构设计
_id |
name |
Age |
Date |
001 |
Jim |
25 |
2012-07-31:12:24:24 |
002 |
tom |
34 |
2012-07-31:12:24:54 |
003 |
Lilli |
21 |
2012-07-31:12:24:57 |
004 |
zhangsan |
23 |
2012-07-31:12:25:24 |
005 |
wangwu |
26 |
2012-07-31:12:27:26 |
006 |
zhaoliu |
29 |
2012-07-31:12:30:24 |
每次查询操作的时候前后台传值全要把上次的最后一个文档的日期保存下来
db.persons.find({date:{$gt:日期数值}}).limit(3)
个人建议à应该把软件的中点放到便捷和精确查询上而不是分页的性能上
因为用户最多不会翻查过2页的
•游标和其他知识(待完善学习)
1.游标
利用游标遍历查询数据
var persons = db.persons.find();
while(persons.hasNext()){
obj = persons.next();
print(obj.name)
}
> var persons = db.persons.find();
> while(persons.hasNext()){obj = persons.next(); print("name:"+obj.name+" age:"+obj.age)};
name:张三 age:20
name:李四 age:30
name:王五 age:40
name:王五 age:40
游标到了底部就会释放资源不能再读取了.
_id |
name |
Age |
001 |
Jim |
25 |
002 |
tom |
34 |
003 |
Lilli |
21 |
004 |
zhangsan |
23 |
005 |
wangwu |
26 |
006 |
zhaoliu |
29 |
2.游标几个销毁条件
1.客户端发来信息叫他销毁
2.游标迭代完毕
3.默认游标超过10分钟没用也会被清除
3.查询快照
快照后就会针对不变的集合进行游标运动了,看看使用方法.
$snapshot:true ,打开快照
db.persons.find({$query:{name:”Jim”},$snapshot:true})
使用快照,一定使用高级查询项;
db.persion.find({name:"张三"})
这条语句是简便写法,实际底层执行的是
db.persion.find({$query:{name:"张三"}}) //我这样写不能查询出结果,可能有问题吧;
高级查询选项
$query
$orderby
$maxsan:integer最多扫描的文档数
$min:doc 查询开始
$max:doc 查询结束
$hint:doc 使用哪个索引
$explain:boolean 统计
$snapshot:boolean一致快照
为什么要使用快照,什么时候用;
使用游标时,对数据做了修改,如果预留的内存不够,就会为他分配新的内存空间,这样就会造成新分配的空间会排在后面,
这样使用有标识,会引起数据误读,造成数据混乱; 所以快照一般和游标一起使用,相当于拍了一张照片,游标按照这张照片的顺序执行,个人理解;
db.books.help();查看帮助,非常有用,
先这样吧,慢慢完善,边学习,边整理;