MongoDB入门学习:MongoDB的增删查改

Posted ldxsuanfa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB入门学习:MongoDB的增删查改相关的知识,希望对你有一定的参考价值。

? ? ? ? 对于我们这样的菜鸟来说,最重要的不是数据库的管理,也不是数据库的性能,更不是数据库的扩展,而是怎么用好这款数据库,也就是一个数据库提供的最核心的功能,增删查改。

? ? ? ? 由于MongoDB存储数据都是以文档的模式。所以在操作它的数据时。也是以文档为单位的。

那么我们实现增删查改也是以文档为基础。不知道文档是什么的同学能够看看上篇介绍的基本概念

1.插入文档

? ? ? ? 向MongoDB集合中插入文档的基本方法是insert:

单个插入
> document = {key : value}
> db.collectionName.insert(document)
批量插入
> documents = [{key : value}, {key : value}, {key : value}, ...]
传入数组
> db.collectionName.insert(documents)
for循环
> for(var i = 0; i < documents.length; i++){
...  db.people.insert(documents[i]);
...  }

? ? ? ? 由于集合是无模式的。集合中的文档能够是各式各样的。所以在插入方面是非常随意的。想一次插入非常多数据的话能够使用for循环,也能够使用批量插入,传入一个由文档构成的数组。由于使用for循环来实现批量插入会为每次插入建立一个TCP连接,而传入数组实现批量插入仅仅有一次TCP连接,所以在效率上来说,for的效率会比传入数组要低。

? ? ? ? 另一种插入的方式save,在shell中能够使用db.collectionName.function不加括号来看方法的实现。能够看出insert和save的差别,看个小样例:

> db.people.find()
{ "_id" : 1, "name" : "mary", "age" : 20 }
> db.people.insert({"_id" : 1, "name" : "amy", "age" : 22})
E11000 duplicate key error index: test.people.$_id_  dup key: { : 1.0 }
> db.people.save({"_id" : 1, "name" : "amy", "age" : 22})
> db.people.find()
{ "_id" : 1, "name" : "amy", "age" : 22 }

? ? ? ? 本来people集合中已经有一个文档了,假设我们要插入的文档中的主键"_id"在集合中已经存在一样的值则会报错,而save就不会。没有一样的主键时。insert和save一样都运行插入操作,有一样的主键时。insert就报错,save就运行更新操作,用新文档的内容来替换已经原来的内容,和update操作一样,所以mary被替换成了amy。

? ? ? ? 运行插入操作的时候,驱动程序先将数据转换成BSON的形式,然后再送入数据库,仅仅检验是否包括了"_id"键。文档是否超过4MB(能插入的文档最大为4MB,超过了就不能存入数据库)。而不进行别的验证和运行别的代码,所以远离了注入式攻击。使数据库更安全。

2.删除文档

? ? ? ? 删除文档的基本方法是remove:

db.collectionName.remove()
db.collectionName.remove({})
db.collectionName.remove(condition)
db.collectionName.drop()

? ? ? ? 前三种都是删除集合中的文档。第一个和第二个是一样的。都不指定删除的条件。这样会删除掉集合中全部的文档。第四个是删除该集合。连索引都删除了,假设要清除整个集合。直接删除集合的效率比删除集合中的全部文档更快。

第三个指定了一个条件。比方删除people集合中name为mary的全部文档:

db.people.remove({"name" : "mary"})

3.更新文档

? ? ? ? 更新文档的基本方法是update。尽管上面讲到了save在"_id"一样的时候也有这样的功效,当然我们通常是不会以"_id"为更新条件的:

db.collectionName.uodate(condition, modifier, upsert, multi)

? ? ? ? update有四个參数,condition是查询文档,用来查询出要改动的文档。modifier是改动器文档,描写叙述对查找到的文档做哪些改动,upsert表示假设没有该文档就插入这个心文档,默觉得false,multi表示是否更新查询到的全部文档,默觉得false,所以仅仅更新查询到的第一个文档。可是我们平时经经常使用到的还是前两个參数。假设有必要就用后两个參数。

由于更新操作是原子的,所以当有非常多更新同一时候发生时。最后一次的更新操作才是最后的结果。

以下我们将name为mary的文档age改为20:

> db.people.find()
{ "_id" : ObjectId("53a3a0b7abda49d7dfce102c"), "name" : "mary", "age" : 30, "country" : "US" }
> db.people.update({"name" : "mary"}, {"age" : 20})
> db.people.find()
{ "_id" : ObjectId("53a3a0b7abda49d7dfce102c"), "age" : 20 }

? ? ? ? 可是最后的结果却出乎我们的预料。name字段和country字段都没有了,这样的update是用后面的文档替换查询到的文档。所以结果是正确的,仅仅是我们的操作错误了。那我们每次更新不都要将原来的数据再写一次么。这样比写SQL更复杂啊,只是另一种改进方式。在shell中将查询到的文档赋值给一个变量。然后再改动,最后在将这个变量替换原来的查询结果:

方式一:
> db.people.find()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "name" : "mary", "age" : 30, "country" : "US" }
> db.people.update({"name" : "mary"}, {"name" : "mary", "age" : 20})
> db.people.find()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "name" : "mary", "age" : 20 }
方式二:
> db.people.find()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "name" : "mary", "age" : 30, "country" : "US" }
> person = db.people.findOne()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "name" : "mary", "age" : 30, "country" : "US"}
> person.age = 20
> delete person.country
true
> db.people.update({"name" : "mary"}, person)
> db.people.find()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "name" : "mary", "age" : 20 }

? ? ? ? 查询出name为mary的文档赋值给person,然后将person的age赋为20,删除country字段。再替换原来查询到的文档,假设一个文档有非常多字段,而我们仅仅要改动当中一到两个字段。这样的方式就比第一种方式要简单的非常多。

可是这样就有个问题,假设findOne匹配到第二个mary,更新的时候却更新到了第一个mary。那就会出现"_id"反复的问题。这样就有了改动器的使用,是更新变的更简单高效。

? ? ? ? 1).$set

? ? ? ? ? ?$set用来改动指定键的值(也能够是内嵌文档的键),假设这个键不存在就创建它,如:

> db.people.find()
{ "_id" : ObjectId("53a3b0e633c516902a43a790"), "name" : "mary", "age" : 30, "country" : "US", "school" : { "name" : "BeijingUniversity", "city" : "Beijing" } }
> db.people.update({"name" : "mary"}, {"$set" : {"age" : 20, "school.name" : "QinghuaUniversity"}})
> db.people.find()
{ "_id" : ObjectId("53a3b0e633c516902a43a790"), "name" : "mary", "age" : 20, "country" : "US", "school" : { "name" : "QinghuaUniversity", "city" : "Beijing" } }

? ? ? ? 2).$unset

? ? ? ? ? ?$unset用来将键全然删除,如:

> db.people.find()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "name" : "mary", "age" : 20, "country" : "US" }
> db.people.update({"name" : "mary"}, {"$unset" : {"country" : 1}})
> db.people.find()
{ "_id" : ObjectId("53a3a1c1abda49d7dfce102d"), "age" : 20, "name" : "mary" }

? ? ? ? 3).$inc

? ? ? ? ? ?$inc用来添加已有键的值,当键不存在时创建这个键,再在初始值0的基础上再添加,$inc相应的键必须是数字类型的,假设是别的数据类型就会报错。如:

> db.people.find()
{ "_id" : ObjectId("53a3b0e633c516902a43a790"), "age" : 20, "country" : "US", "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$inc" : {"age" : 1}})
> db.people.find()
{ "_id" : ObjectId("53a3b0e633c516902a43a790"), "age" : 21, "country" : "US", "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$inc" : {"age" : -2}})
> db.people.find()
{ "_id" : ObjectId("53a3b0e633c516902a43a790"), "age" : 19, "country" : "US", "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$inc" : {"country" : 2}})
Cannot apply $inc modifier to non-number

? ? ? ? 4).$push,$pushAll

? ? ? ? ? ?$push用来对内置数组的操作。给内置数组加入元素,$push是加入一个元素,$pushAll是加入一个数组,如:

> db.people.find()
{ "_id" : ObjectId("53a3b47733c516902a43a791"), "name" : "mary", "friends" : [  "amy",  "join" ] }
> db.people.update({"name" : "mary"}, {"$push" : {"friends" : "joe"}})
> db.people.find()
{ "_id" : ObjectId("53a3b47733c516902a43a791"), "friends" : [  "amy",  "join",  "joe" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$push" : {"friends" : ["jodan", "mical"]}})
> db.people.find()
{ "_id" : ObjectId("53a3b47733c516902a43a791"), "friends" : [  "amy",  "join",  "joe",  [  "jodan",  "mical" ] ], "name" : "mary" }

? ? ? ? 5).$addToSet,$each

? ? ? ? ? ?$addToSet用来给内置数组加入元素。假设数组中已经存在同样值的元素。就不加入。用来避免反复,通常和$each组合使用,$each后面跟一个数组用来加入该数组中的元素如:

> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "amy" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$addToSet" : {"friends" : "join"}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "amy",  "join" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$addToSet" : {"friends" : {"$each" : ["amy", "join", "jodan"]}}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "amy",  "join",  "jodan" ], "name" : "mary" }

? ? ? ? 6).$pull。$pullAll

? ? ? ? ? ?$pull用来删除内置数组中的某元素。$pullAll删除某几个元素。如:

 db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "name" : "mary", "friends" : [  "amy",  "join",  "jodan",  "mical" ] }
> db.people.update({"name" : "mary"}, {"$pull" : {"friends" : "amy"}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "join",  "jodan",  "mical" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$pullAll" : {"friends" : ["join", "jodan"]}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "mical" ], "name" : "mary" }

? ? ? ? 7).$pop

? ? ? ? ? ?$pop也是用来删除内置数组中的一个元素,这个元素要么是数组的第一个元素要么是数组的最后一个元素,如:

> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "mical",  "amy",  "join" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$pop" : {"friends" : 1}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "mical",  "amy" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$pop" : {"friends" : -1}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "amy" ], "name" : "mary" }

? ? ? ? 8).$

? ? ? ? ? ?$用来定位内置数组的元素,MongoDB的内置数组下标也是从0開始递增的。所以我们能够通过对数组进行定位改动。如:

> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "amy",  "join",  "jodan" ], "name" : "mary" }
> db.people.update({"name" : "mary"}, {"$set" : {"friends.0" : "mical"}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "mical",  "join",  "jodan" ], "name" : "mary" }
> db.people.update({"name" : "mary", "friends" : "join"}, {"$set" : {"friends.$" : "amy"}})
> db.people.find()
{ "_id" : ObjectId("53a3c18533c516902a43a794"), "friends" : [  "mical",  "amy",  "jodan" ], "name" : "mary" }

? ? ? ? ? ? 上面第一种更新。我们就是单纯的想把mary的第一个朋友变成mical。另外一种更新。我们不知道mary的朋友join是在数组的哪个位置。可是确实有这么个朋友,就查询到了通过$进行定位,然后再将其变成amy。

? ? ? ? 9).$rename

? ? ? ? ? ?$rename用来对字段重命名。如:

> db.people.find()
{ "_id" : ObjectId("53a3c80a33c516902a43a795"), "name" : "mary", "friends" : [  "mical",  "amy",  "jodan" ] }
> db.people.update({"name" : "mary"}, {"$rename" : {"friends" : "classmates"}})
> db.people.find()
{ "_id" : ObjectId("53a3c80a33c516902a43a795"), "classmates" : [  "mical",  "amy",  "jodan" ], "name" : "mary" }

? ? ? ? 文档的插入,删除和更新都是瞬间完毕的,由于client并不需要等待数据库的响应,这个也不是异步操作,由于client将文档给数据库了其它的操作都由数据库本身来操作,和client就全然没关系了。文档的查询就不一样了,client必需要等到数据库返回来的查询结果。

4.查询文档

? ? ? ? 查询文档的基本方法是find:

db.collectionName.find(condition, returnKey)
db.collectionName.find()
db.collectionName.find({})
db.collectionName.find({}, {"name" : 1})
db.collectionName.find({}, {"name" : 0})

? ? ? ? find有两个參数,condition为查询文档。returnKey为指定返回的字段。不指定查询条件或者查询条件是一个空文档,那就是查询集合中的全部文档,返回值指定键。假设为1就是返回该键的值,假设为0就返回除了该键以外的全部键的值。

? ? ? ? 当然我们除了精确查询,比方查询name为mary,age为20的文档并返回其friends字段的结果,还会有更复杂的模糊查询条件。比方范围查询。age在20到30之间的文档等。这时候在查询文档中就要加入这些查询条件。

? ? ? ? 1).$lt。$lte,$gt,$gte,$ne

? ? ? ? ? ?$lt。$lte,$gt,$gte分别相应<。<=。>,>=,能够组合起使用来查询一个范围。$ne表示不等于,如:

> db.people.find()
{ "_id" : ObjectId("53a3e01d33c516902a43a797"), "name" : "mary", "age" : 20 }
{ "_id" : ObjectId("53a3e02533c516902a43a798"), "name" : "amy", "age" : 23 }
{ "_id" : ObjectId("53a3e02d33c516902a43a799"), "name" : "join", "age" : 18 }
{ "_id" : ObjectId("53a3e03c33c516902a43a79a"), "name" : "jodan", "age" : 25 }
{ "_id" : ObjectId("53a3e04933c516902a43a79b"), "name" : "mical", "age" : 19 }
> db.people.find({"age" : {"$gte" : 19, "$lte" : 23}, "name" : {"$ne" : "mary"}}, {"_id" : 0})
{ "name" : "amy", "age" : 23 }
{ "name" : "mical", "age" : 19 }

? ? ? ? 2).$or,$in,$nin

? ? ? ? ? ?$or,$in表示几个条件中满足一个就能够返回,可是$in仅仅能用于在同一个字段中给几个条件,而or能够用于不同字段。还能和$in搭配使用。$nin和$in相反。表示仅仅要不符合几个给定的条件就能够返回,如:

> db.people.find()
{ "_id" : ObjectId("53a3e01d33c516902a43a797"), "name" : "mary", "age" : 20 }
{ "_id" : ObjectId("53a3e02533c516902a43a798"), "name" : "amy", "age" : 23 }
{ "_id" : ObjectId("53a3e02d33c516902a43a799"), "name" : "join", "age" : 18 }
{ "_id" : ObjectId("53a3e03c33c516902a43a79a"), "name" : "jodan", "age" : 25 }
{ "_id" : ObjectId("53a3e04933c516902a43a79b"), "name" : "mical", "age" : 19 }
> db.people.find({"age" : {"$in" : [19, 20, 21, 22, 23]}}, {"_id" : 0})
{ "name" : "mary", "age" : 20 }
{ "name" : "amy", "age" : 23 }
{ "name" : "mical", "age" : 19 }
> db.people.find({"age" : {"$nin" : [19, 20, 21, 22, 23]}}, {"_id" : 0})
{ "name" : "join", "age" : 18 }
{ "name" : "jodan", "age" : 25 }
> db.people.find({"$or" : [{"age" : {"$in" : [19, 20, 21, 22, 23]}}, {"name" : "jodan"}]}, {"_id" : 0})
{ "name" : "mary", "age" : 20 }
{ "name" : "amy", "age" : 23 }
{ "name" : "jodan", "age" : 25 }
{ "name" : "mical", "age" : 19 }

? ? ? ? 3).$not,$mod

? ? ? ? ? ?$not是元条件句,能够用在不论什么其它条件上。表示非,$mod表示取模运算,相应运算符%,如:

> db.people.find()
{ "_id" : ObjectId("53a3e01d33c516902a43a797"), "name" : "mary", "age" : 20 }
{ "_id" : ObjectId("53a3e02533c516902a43a798"), "name" : "amy", "age" : 23 }
{ "_id" : ObjectId("53a3e02d33c516902a43a799"), "name" : "join", "age" : 18 }
{ "_id" : ObjectId("53a3e03c33c516902a43a79a"), "name" : "jodan", "age" : 25 }
{ "_id" : ObjectId("53a3e04933c516902a43a79b"), "name" : "mical", "age" : 19 }
> db.people.find({"age" : {"$not" : {"$mod" : [5, 0]}}}, {"_id" : 0})
{ "name" : "amy", "age" : 23 }
{ "name" : "join", "age" : 18 }
{ "name" : "mical", "age" : 19 }

? ? ? ? ? ?这里表示对age进行取模运算,假设里面的$mod条件为对5取模。为0就符合条件,加上外面的$not,表示非,也就是模不为0就符合条件。

? ? ? ? 4).$exists,null

? ? ? ? ? ?$exists表示推断键值是否已经存在,它的值为true或者false。null表示空值或不存在的字段,如:

> db.variable.find()
{ "_id" : ObjectId("53a3e91f33c516902a43a79c"), "x" : 1, "y" : null }
{ "_id" : ObjectId("53a3e92733c516902a43a79d"), "x" : 3 }
{ "_id" : ObjectId("53a3e92e33c516902a43a79e"), "x" : 5, "y" : 10 }
> db.variable.find({"y" : null}, {"_id" : 0})
{ "x" : 1, "y" : null }
{ "x" : 3 }
> db.variable.find({"y" : {"$in" : [null], "$exists" : true}}, {"_id" : 0})
{ "x" : 1, "y" : null }

? ? ? ? ? ?当我们仅仅查询y为null时,由于第二个文档中没有y字段所以也符合条件,那么假设要查询的文档y必需要存在并且为null。就用到了$exists。


? ? ? ? 5).正則表達式

? ? ? ? ? ?没错,MongoDB也支持正則表達式来查询字符串,这就使得对字符串的查询更加的简单高效。正則表達式是查询字符串的神器。如:

> db.people.find()
{ "_id" : ObjectId("53a3e01d33c516902a43a797"), "name" : "mary", "age" : 20 }
{ "_id" : ObjectId("53a3e02533c516902a43a798"), "name" : "amy", "age" : 23 }
{ "_id" : ObjectId("53a3e02d33c516902a43a799"), "name" : "join", "age" : 18 }
{ "_id" : ObjectId("53a3e03c33c516902a43a79a"), "name" : "jodan", "age" : 25 }
{ "_id" : ObjectId("53a3e04933c516902a43a79b"), "name" : "mical", "age" : 19 }
> db.people.find({"name" : /jo.*/}, {"_id" : 0})
{ "name" : "join", "age" : 18 }
{ "name" : "jodan", "age" : 25 }

? ? ? ? 6).对内置数组的查询,$all。$size,$slice

? ? ? ? ? ?对内置数组最简单的查询就是精确的指定条件,指定的条件表示该内置数组包括该元素,而不是等于,这是非常有意思的。精确查询一般的字段都是指该字段的值等于我们给定的值。而对内置数组而言,是表示包括该元素。


? ? ? ? ? ?假设要对数组通过多元素来匹配就要用到$all,假设包括$all给定的数组中的元素。就符合条件推断,$size表示数组的大小,$slice是find中第二个參数中指定的内容。表示返回数组的一个子集合。也就是查询到的数组返回哪几个元素。正数表示前几个。负数表示后几个。如:

> db.food.find()
{ "_id" : ObjectId("53a3ebcf33c516902a43a79f"), "fruit" : [  "apple",  "banana",  "orange" ] }
{ "_id" : ObjectId("53a3ee0e33c516902a43a7a0"), "fruit" : [  "bnana" ] }
{ "_id" : ObjectId("53a3ee1933c516902a43a7a1"), "fruit" : [  "apple",  "orange" ] }
> db.food.find({"fruit" : "apple"}, {"_id" : 0})
{ "fruit" : [  "apple",  "banana",  "orange" ] }
{ "fruit" : [  "apple",  "orange" ] }
> db.food.find({"fruit" : {"$all" : ["apple", "orange"]}}, {"_id" : 0})
{ "fruit" : [  "apple",  "banana",  "orange" ] }
{ "fruit" : [  "apple",  "orange" ] }
> db.food.find({"fruit" : {"$size" : 2}}, {"_id" : 0})
{ "fruit" : [  "apple",  "orange" ] }
> db.food.find({"fruit" : {"$size" : 3}}, {"_id" : 0, "fruit" : {"$slice" : -2}})
{ "fruit" : [  "banana",  "orange" ] }
> db.food.find({"fruit" : {"$size" : 3}}, {"_id" : 0, "fruit" : {"$slice" : 2}})
{ "fruit" : [  "apple",  "banana" ] }

? ? ? ? 7).对内置数组中文档的查询,$elemMatch

? ? ? ? ? ?对内置数组中文档的查询事实上就是将内置数组中的元素替换成文档形式。$elemMatch保证我们的查询是在内置数组中同一文档中进行的。如:

> db.grade.find()
{
        "_id" : ObjectId("53a3f4d933c516902a43a7a4"),
        "name" : "jim",
        "age" : 20,
        "score" : [
                {
                        "course" : "computer",
                        "credit" : 2,
                        "teacher" : "mary"
                },
                {
                        "course" : "english",
                        "credit" : 1,
                        "teacher" : "join"
                 }
        ]
}
{
        "_id" : ObjectId("53a3fbf7901e10bdd70adf9e"),
        "name" : "amy",
        "age" : 21,
        "score" : [
                {
                        "course" : "computer",
                        "credit" : 2,
                        "teacher" : "nola"
                },
                {
                        "course" : "chinese",
                        "credit" : 3,
                        "teacher" : "mary"
                }
        ]
}
方式一、这里指定score中course为computer和teacher为mary是查不到的
> db.grade.find({"score" : {"course" : "computer", "teacher" : "mary"}})
方式二、指定score中元素的全部字段就能查到了,并且顺序不能变
> db.grade.find({"score" : {"course" : "computer", "teacher" : "mary", "credit" : 2}})
> db.grade.find({"score" : {"course" : "computer", "credit" : 2, "teacher" : "mary"}})
{
        "_id" : ObjectId("53a3f4d933c516902a43a7a4"),
        "name" : "jim",
        "age" : 20,
        "score" : [
                {
                        "course" : "computer",
                        "credit" : 2,
                        "teacher" : "mary"
                },
                {
                        "course" : "english",
                        "credit" : 1,
                        "teacher" : "join"
                }
        ]
}
方式三、指定score.course为computer和score.teacher为mary竟然把两个都查出来了
> db.grade.find({"score.course" : "computer", "score.teacher" : "mary"})
{
        "_id" : ObjectId("53a3f4d933c516902a43a7a4"),
        "name" : "jim",
        "age" : 20,
        "score" : [
                {
                        "course" : "computer",
                        "credit" : 2,
                        "teacher" : "mary"
                },
                {
                        "course" : "english",
                        "credit" : 1,
                        "teacher" : "join"
                }
        ]
}
{
        "_id" : ObjectId("53a3fbf7901e10bdd70adf9e"),
        "name" : "amy",
        "age" : 21,
        "score" : [
                {
                        "course" : "computer",
                        "credit" : 2,
                        "teacher" : "nola"
                },
                {
                        "course" : "chinese",
                        "credit" : 3,
                        "teacher" : "mary"
                }
        ]
}
方式四、通过$elemMatch来查询,得到我们想要的结果
> db.grade.find({"score" : {"$elemMatch" : {"course" : "computer", "teacher" : "mary"}}})
{
        "_id" : ObjectId("53a3f4d933c516902a43a7a4"),
        "name" : "jim",
        "age" : 20,
        "score" : [
                {
                        "course" : "computer",
                        "credit" : 2,
                        "teacher" : "mary"
                },
                {
                        "course" : "english",
                        "credit" : 1,
                        "teacher" : "join"
                }
        ]
}

? ? ? ? ? ?对于方式一和方式二可能有个难理解的地方,为什么仅仅指定当中部分字段就查询不到。而必需要指定全部的字段才干够呢。查询内置数组的时候仅仅要指定fruit为apple就能查询出包括apple的数组,这里为什么要指定全部的字段呢。事实上这是一个误区。在这里一个内置文档才相当于fruit中的一种水果,也就是数组中的一个元素,假设连这个元素都缺斤少两。在数组中怎样查询的到呢。

? ? ? ? ? ?对于方式三,指定score.course和score.teacher为啥把两个都查询出来了,明明第二个结果不是我们想要的。course为computer时teacher并不为mary,可是course为chinese时teacher为mary,所以第二个结果中的确存在score.course为computer。并且同一时候存在score.teacher为mary,那这是将两个文档的字段组合起来达到我们的要求了。显然这并非我们想要的,所以就必须使用$elemMatc,也就是方式四。它保证了我们查询是在数组中同一个文档元素中进行的。


? ? ? ? 7).$where

? ? ? ? ? ?$where能够运行不论什么的javascript作为查询的一部分,所以$where差点儿能够做全部的事。可是这样的方式必需要将每一个文档从BSON转换成javascript对象。然后再通过$where的表达式来运行,并且还不能用索引。因此用$where是下下策,在你实在走投无路的时候再用。使用方法也比較简单。就是对this的操作,假设某文档满足我们自己定义的条件就返回true。那么该文档就会被返回。如:

> db.fruit.find()
{ "_id" : ObjectId("53a412c7901e10bdd70adfa2"), "apple" : 2, "banana" : 6, "orange" : 3 }
{ "_id" : ObjectId("53a412d1901e10bdd70adfa3"), "apple" : 5, "banana" : 7, "orange" : 8 }
db.fruit.find({"$where" : function(){
        for(var x in this){
                for(var y in this){
                        if(this[x] / this[y] == 2){
                                return true;
                        }
                }
        }
}})
{ "_id" : ObjectId("53a412c7901e10bdd70adfa2"), "apple" : 2, "banana" : 6, "orange" : 3 }

? ? ? ? 数据库使用游标来返回find的运行结果。client对游标的实现通常能够对查询到的结果进行有效的控制。能够限制结果的数量,略过部分结果。依据随意方向,随意键的组合对结果进行排序,或者运行其它一些功能强大的操作。

? ? ? ? 在shell中使用游标,要先将查询到的结果赋值给一个变量,然后通过游标一次查看一条结果。

假设查询结果没有赋值给变量,那么shell会自己主动迭代。打印全部查询到的结果。

游标提供了两个方法,hasNext返回是否还有结果,next返回下一个结果用来遍历查询到的结果,还提供了limit。skip。sort几个方法来操作结果。

由于游标对象的方法都返回游标本身,所以这几个方法能够以随意的顺序进行组合。如:

> db.people.find()
{ "_id" : ObjectId("53a3e01d33c516902a43a797"), "name" : "mary", "age" : 20 }
{ "_id" : ObjectId("53a3e02533c516902a43a798"), "name" : "amy", "age" : 23 }
{ "_id" : ObjectId("53a3e02d33c516902a43a799"), "name" : "join", "age" : 18 }
{ "_id" : ObjectId("53a3e03c33c516902a43a79a"), "name" : "jodan", "age" : 25 }
{ "_id" : ObjectId("53a3e04933c516902a43a79b"), "name" : "mical", "age" : 19 }
> var cursor = db.people.find();
> while(cursor.hasNext()){ obj = cursor.next(); print(obj.name); }
mary
amy
join
jodan
mical
> var cursor = db.people.find().limit(3);
> while(cursor.hasNext()){ obj = cursor.next(); print(obj.name); }
mary
amy
join
> var cursor = db.people.find().skip(2);
> while(cursor.hasNext()){ obj = cursor.next(); print(obj.name); }
join
jodan
mical
> var cursor = db.people.find().sort({"name" : 1});
> while(cursor.hasNext()){ obj = cursor.next(); print(obj.name); }
amy
jodan
join
mary
mical
> var cursor = db.people.find().skip(2).limit(2).sort({"name" : 1});
> while(cursor.hasNext()){ obj = cursor.next(); print(obj.name); }
join
mary

? ? ? ? limit表示对查询到的结果加上数量上限,假设查询到的结果数量多于这个上限,则返回这个数量的结果。假设不够。就返回全部的结果。skip表示略过一定数量的结果,假设查询到的结果数量少于这个数量,就没有不论什么文档返回。假设多于,则略过这个数量的文档后再返回。

sort表示对查询结果进行排序,指定字段并指定顺序。1为升序,-1为降序。也能够同一时候对多个字段进行排序。

以上是关于MongoDB入门学习:MongoDB的增删查改的主要内容,如果未能解决你的问题,请参考以下文章

mongodb(四):对文档操作增删查改(python)

MongoDB增删查改

MongoDB数据库进阶 --- 增删查改...

MongoDB入门三

MongoDB快速入门教程 (4.2)

node.js+express+mongoose实现用户增删查改案例