MongoDB 查询篇

来源:互联网 发布:ubuntu wifi 编辑:程序博客网 时间:2024/06/05 06:38

上一篇文章说了MongoDB一些常用的更新操作,这篇就来写写常用的查询操作。



1、最基本的查询

最基本的查询就莫过于,我们之前的findOne()和find()了。基本上已经非常熟悉了,但是我们在后面会慢慢探讨findOne和find的多种多样的查询方式。先来简单的回忆一下

db.product.findOne();db.product.find();


其实我们可以像更新一样,添加查询条件:

db.product.find({product_name:"iPhoneX"});


2、查询条件

在我们的查询中好像只有=的匹配,就没有别的了。下面我们看看其他的查询条件

"$lt" 小于  "$lte"小于等于   "$gt" 大于   "$gte" 大于等于 $ne 不等于

下面的例子,我们查询商品价格大于5000元的商品:

db.product.find({price:{$gte:5000}});

查询上架日期为2017年10月的

db.product.find({create_date:{$gte:new Date("2017-10-01")},create_date:{$lt:new Date("2017-11-01")}});


查询不是官方自营店的iPhone X商品

db.product.find({store:{$ne:"官方自营店"}});

目前我们的所有查询都是AND形式去组合条件查询,后面会通过一些操作符实现其他形式的组合查询。


3、指定返回数据的键

在SQL当中,我们可以在select 关键字后面指定要返回数据字段。MongoDB也可以实现类似的功能。

我们可以通过find方法的第二个参数指定我们需要返回什么字段,或者指定不返回什么字段

db.product.find({product_name:"iPhoneX"},{product_name:1,price:1,brand:1,store:1});
我们通过第二个参数,指定了我们需要显示那几个字段。你会看到在find第二个参数当中,字段属性的值都是1,代表显示,如果是0代表不显示。需要注意的是,默认_id就算没有指定显示也会自动显示,当然你可以显性指定为不显示

结果:

{     "_id" : ObjectId("59e47fdb203e071a1b02e544"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "brand" : "Apple",     "store" : "官方自营店"}{     "_id" : ObjectId("59e5a20f7dfc75087c893b50"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "brand" : "Apple",     "store" : "第三方渠道"}
我们也可以指定不现实那几个字段属性:

db.product.find({product_name:"iPhoneX"},{_id:0,size:0,newest_commment:0,sku:0,popular_comment:0,keyword:0,create_date:0});
显示结果如下:

{     "product_name" : "iPhoneX",     "price" : 8699.0,     "description" : "一台贵到666的手机",     "product_number" : "9088816371",     "brand" : "Apple",     "store" : "官方自营店"}{     "product_name" : "iPhoneX",     "price" : 8699.0,     "description" : "一台贵到666的手机",     "product_number" : "9088816371",     "brand" : "Apple",     "store" : "第三方渠道"}


4、OR查询

上面我们所有的组合查询都是AND方式去查询,我们可以通过$in、$nin 或者 $or  操作符去进行OR方式的组合查询

为了测试,我们创建一个用户collection,然后通过手机号码通过$in获得用户数据:

var userA = {username:"TONY",user_pic:"default.jpg",phone_number:"13333333338"};var userB = {username:"YAN", user_pic:"default.jpg",phone_number:"13888888883"};db.user.insert(userA);db.user.insert(userB);db.user.find({"phone_number":{$in:["13333333338","13888888883"]}});
返回的结果:

{     "_id" : ObjectId("59e800722d68f77114ec4fac"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338"}{     "_id" : ObjectId("59e800822d68f77114ec4fad"),     "username" : "YAN",     "user_pic" : "default.jpg",     "phone_number" : "13888888883"}
当然我们还可以使用 $nin 不包含在数值的匹配条件都查询出来

var userA = {username:"TONY",user_pic:"default.jpg",phone_number:"13333333338"};var userB = {username:"YAN", user_pic:"default.jpg",phone_number:"13888888883"};var userC = {username:"CHAO",user_pic:"default.jpg",phone_number:"18333333338"};var userD = {username:"HONO",user_pic:"default.jpg",phone_number:"18888888883"};db.user.insert(userA);db.user.insert(userB);db.user.insert(userC);db.user.insert(userD);db.user.find({"phone_number":{$nin:["13333333338","13888888883"]}});
返回的结果:

{     "_id" : ObjectId("59e802432d68f77114ec4fae"),     "username" : "CHAO",     "user_pic" : "default.jpg",     "phone_number" : "18333333338"}{     "_id" : ObjectId("59e802442d68f77114ec4faf"),     "username" : "HONO",     "user_pic" : "default.jpg",     "phone_number" : "18888888883"}

还有就是$or操作符,这个就是跟SQL 的OR语句差不多。一下就是使用$or查询username 是 TONY 或者 phone_number 是 18888888883 而且user_pic 一定要是 default.jpg 就等以下这种情况:

(username = "TONY" OR phone_number = "18888888883") AND user_pic = "default.jpg"

db.user.find({$or:[{"username":"TONY"},{"phone_number":"18888888883"}],"user_pic":"default.jpg"});


查询结果如下
{     "_id" : ObjectId("59e800722d68f77114ec4fac"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338"}{     "_id" : ObjectId("59e802442d68f77114ec4faf"),     "username" : "HONO",     "user_pic" : "default.jpg",     "phone_number" : "18888888883"}


除了一个$or 还有一个$nor。就是取反:

db.user.find({$nor:[{"phone_number":"18888888883"},{"username":"YAN"}]});

返回结果:

{     "_id" : ObjectId("59e800722d68f77114ec4fac"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338"}{     "_id" : ObjectId("59e802432d68f77114ec4fae"),     "username" : "CHAO",     "user_pic" : "default.jpg",     "phone_number" : "18333333338"}


5、$not操作符

这个比较难解释,这个跟上面OR小节有比较大的关系。可以在其他任意条件之前去做取反操作,打个比方:

db.user.find({"phone_number":{$not:{$in:["18888888883","13333333338"]}}});


搜索结果如下:

{     "_id" : ObjectId("59e800822d68f77114ec4fad"),     "username" : "YAN",     "user_pic" : "default.jpg",     "phone_number" : "13888888883"}{     "_id" : ObjectId("59e802432d68f77114ec4fae"),     "username" : "CHAO",     "user_pic" : "default.jpg",     "phone_number" : "18333333338"}


6、null的特别处理

对于null这种空值处理还是比较麻烦的,因为再MongoDB不像SQL每一行记录的数据格式都是固定的。笔者在SpringCloud的微服务项目当中,通过MongoDB repository 去添加文档,如果为null 的字段,根本就不会把改字段属性添加到MongoDB当中。所以除了去判断空值,还需要去判断字段属性(KEY)是否存在。

为了测试,我为已经存在的user collection当中添加gender字段属性。我不会全部添加,部分我们添加gender的key但是写上null,还有一些我不会去添加gender的key。【其实,在MongoDB当中,字段属性是不太正确的做法,但是作为一个SQL的资深用户,为了好理解一直这样说,后面我会改成KEY 或者 键】

var tony = db.user.findOne({"username":"TONY"});tony.gender = "male";db.user.save(tony);var yan = db.user.findOne({"username":"YAN"});yan.gender = "male";db.user.save(yan);var chao = db.user.findOne({"username":"CHAO"});chao.gender = null;db.user.save(chao);db.user.find();

修改结果:

{     "_id" : ObjectId("59e83a2d2d68f77114ec4fb4"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338",     "gender" : "male"}{     "_id" : ObjectId("59e83a2d2d68f77114ec4fb5"),     "username" : "YAN",     "user_pic" : "default.jpg",     "phone_number" : "13888888883",     "gender" : "male"}{     "_id" : ObjectId("59e83a2e2d68f77114ec4fb6"),     "username" : "CHAO",     "user_pic" : "default.jpg",     "phone_number" : "18333333338",     "gender" : null}{     "_id" : ObjectId("59e83a2f2d68f77114ec4fb7"),     "username" : "HONO",     "user_pic" : "default.jpg",     "phone_number" : "18888888883"}

目前可以发现HONO 是没有gender ,CHAO这个用户gender 则是NULL,其他用户是有gender而且都不为空。 现在我们查询gender为NULL的用户

db.user.find({gender:null});
我们通过上面的查询可以同时获得HONO 和 CHAO 两个用户,可能是版本的原因。在以前的旧版本当中是无法使用上面的查询的。

我们可以使用$exists 获得不存在gender 的用户

db.user.find({gender:{$exists:false}});

7、使用正则表达式进行查询

MongoDB最为方便的查询就莫过于正则表达式查询了。我们可以通过MongoDB的正则表达式查询实现如SQL的LIKE模糊查询

db.user.find({username:/O/i});

查询结果:

{     "_id" : ObjectId("59e83a2d2d68f77114ec4fb4"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338",     "gender" : "male"}{     "_id" : ObjectId("59e83a2e2d68f77114ec4fb6"),     "username" : "CHAO",     "user_pic" : "default.jpg",     "phone_number" : "18333333338",     "gender" : null}{     "_id" : ObjectId("59e83a2f2d68f77114ec4fb7"),     "username" : "HONO",     "user_pic" : "default.jpg",     "phone_number" : "18888888883"}


8、查询数组

首先我们通过一个普通的查询,看看MongoDB数组的查询是怎么样的:

db.product.find({"keyword":"iphone"},{"product_name":1,"keyword":1,"price":1,"store":1});

结果可以发现,只要keyword数组当中,有iphone 就匹配上。

{     "_id" : ObjectId("59e47fdb203e071a1b02e544"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "keyword" : [        "苹果",         "iphone",         "apple"    ],     "store" : "官方自营店"}{     "_id" : ObjectId("59e5a20f7dfc75087c893b50"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "keyword" : [        "苹果",         "iphone",         "apple"    ],     "store" : "第三方渠道"}

但是事实上却没有我们想象中这么方便,如我们希望在一个数组属性当中同时匹配其中两个关键字的话,上面的方法就不是这么奏效了。

看看下面的列子:

var userA = {username:"TONY",user_pic:"default.jpg",phone_number:"13333333338",favorite:["swimming","computer game","reading","running"]};var userB = {username:"YAN", user_pic:"default.jpg",phone_number:"13888888883",favorite:["football","drawing","video game","shopping"]};var userC = {username:"CHAO", user_pic:"default.jpg",phone_number:"13888888889",favorite:["talking show","swimming","computer game","kidding"]};var userD = {username:"LTT", user_pic:"default.jpg",phone_number:"13888888833",favorite:["shopping","watching tv","running","travel"]};db.user.insert(userA);db.user.insert(userB);db.user.insert(userC);db.user.insert(userD);db.user.find({favorite:["swimming","reading"]});

结果将会返回空,因为上面这条语句会精确匹配只有两个元素而且是swimming 和 reading的文档结果。最重要的是,精确匹配会连顺序都要完全匹配。

如果希望在一个数组当中同时匹配到指定的元素,我们可以使用$all 操作符。(匹配跟顺序无关)

db.user.find({favorite:{$all : ["swimming","reading"]}});
返回结果:

{     "_id" : ObjectId("59eb577e89c5ddc1ad8058b6"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338",     "favorite" : [        "swimming",         "computer game",         "reading",         "running"    ]}


指定元素位置匹配,我们可以获得指定第二个元素为drawing 的文档。

db.user.find({"favorite.1":"drawing"});

返回结果:

{     "_id" : ObjectId("59eb577f89c5ddc1ad8058b7"),     "username" : "YAN",     "user_pic" : "default.jpg",     "phone_number" : "13888888883",     "favorite" : [        "football",         "drawing",         "video game",         "shopping"    ]}

我们可以通过使用$size操作符,匹配指定长度的数组:

db.user.find({"favorite":{$size:4}});


9、通过$slice获得指定数组属性的子数组

我们希望返回用户的前两个favorite

db.user.find({"username":"TONY"},{username:1,phone_number:1,favorite:{$slice:2}});

返回的结果:

{     "_id" : ObjectId("59eb577e89c5ddc1ad8058b6"),     "username" : "TONY",     "phone_number" : "13333333338",     "favorite" : [        "reading",         "running"    ]}

如果希望返回最后两个favorite元素,将2改成-1即可。

最牛逼的还是可以截取中间指定范围的子数组:

db.user.find({"username":"TONY"},{username:1,phone_number:1,favorite:{$slice:[1,2]}});
返回结果:

{     "_id" : ObjectId("59eb577e89c5ddc1ad8058b6"),     "username" : "TONY",     "phone_number" : "13333333338",     "favorite" : [        "computer game",         "reading"    ]}

需要提醒的是,如果我们只在find第二个参数当中指定了$slice会默认返回全部的键

db.user.find({"username":"TONY"},{favorite:{$slice:[1,2]}});
返回结果:

{     "_id" : ObjectId("59eb577e89c5ddc1ad8058b6"),     "username" : "TONY",     "user_pic" : "default.jpg",     "phone_number" : "13333333338",     "favorite" : [        "computer game",         "reading"    ]}

有时候我们不知道我们想要的数组元素具体的下标,我们可以通过查询的方位去定位到某一个数组元素:

db.product.findOne({"popular_comment.user_id":119},{"popular_comment.$":1});

返回结果

{     "_id" : ObjectId("59e47fdb203e071a1b02e544"),     "popular_comment" : [        {            "content" : "Comment C content !",             "user_id" : 119.0,             "popularity_degree" : 108.0        }    ]}


10、坑爹数组组合查询

来看看下面的查询例子:

db.product.update({"store":"官方自营店"},{$set:{"sku.0.price":8388,"sku.1.price":8388,"sku.2.price":9688,"sku.3.price":9688}});db.product.findOne({"store":"官方自营店"});db.product.update({"store":"第三方渠道"},{$set:{"sku.0.price":9600,"sku.1.price":9800,"sku.2.price":12388,"sku.3.price":12699}});db.product.findOne({"store":"第三方渠道"});db.product.update({"store":"金牌苹果店"},{$set:{"sku.0.price":9500,"sku.1.price":9600,"sku.2.price":12388,"sku.3.price":12588}});db.product.findOne({"store":"金牌苹果店"});db.product.find({"sku.price":{$gt:9850,$lt:10000}});
按照道理来说,应该查询不出任何数据的,因为9850-10000这个区间之内,根本没有任何一个数组的元素可以匹配上。但是事实上mo'nMongoDB返回了以下的数据:

{     "_id" : ObjectId("59e5a20f7dfc75087c893b50"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "description" : "一台贵到666的手机",     "product_number" : "9088816371",     "brand" : "Apple",     "size" : "143.6 X 70.9",     "newest_commment" : {        "comment_content" : "this is newtest comment at that place!",         "user_id" : 109382.0,         "create_date" : ISODate("2017-10-17T01:15:20.466+0000")    },     "sku" : [        {            "capacity" : "64G",             "style" : "silver",             "price" : 9600.0        },         {            "capacity" : "64G",             "style" : "gray",             "price" : 9800.0        },         {            "capacity" : "256G",             "style" : "silver",             "price" : 12388.0        },         {            "capacity" : "256G",             "style" : "gray",             "price" : 12699.0        }    ],     "popular_comment" : [        {            "content" : "Comment A content !",             "user_id" : 399.0,             "popularity_degree" : 89.0        },         {            "content" : "Comment C content !",             "user_id" : 119.0,             "popularity_degree" : 108.0        },         {            "content" : "Comment E content !",             "user_id" : 893.0,             "popularity_degree" : 103.0        }    ],     "keyword" : [        "苹果",         "iphone",         "apple"    ],     "store" : "第三方渠道",     "create_date" : ISODate("2017-11-10T00:00:00.000+0000")}{     "_id" : ObjectId("59e9c5872d68f77114ec4fb8"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "description" : "一台贵到666的手机",     "product_number" : "9088816371",     "brand" : "Apple",     "size" : "143.6 X 70.9",     "newest_commment" : {        "comment_content" : "this is newtest comment at that place!",         "user_id" : 109382.0,         "create_date" : ISODate("2017-10-17T01:15:20.466+0000")    },     "sku" : [        {            "capacity" : "64G",             "style" : "silver",             "price" : 9500.0        },         {            "capacity" : "64G",             "style" : "gray",             "price" : 9600.0        },         {            "capacity" : "256G",             "style" : "silver",             "price" : 12388.0        },         {            "capacity" : "256G",             "style" : "gray",             "price" : 12588.0        }    ],     "popular_comment" : [        {            "content" : "Comment A content !",             "user_id" : 399.0,             "popularity_degree" : 89.0        },         {            "content" : "Comment C content !",             "user_id" : 119.0,             "popularity_degree" : 108.0        },         {            "content" : "Comment E content !",             "user_id" : 893.0,             "popularity_degree" : 103.0        }    ],     "keyword" : [        "iphone"    ],     "store" : "金牌苹果店",     "create_date" : ISODate("2017-11-10T00:00:00.000+0000")}
可以看到的是,有两条数据。因为MongoDB会查询文档中sku数组中的其中有元素大于9850,并且其中有元素小于10000即可。但是必须有一个元素满足大于9850和必须有一个元素小于10000,那这里就会匹配以上的两条数据。但是官方自营店的数据却匹配不上去了。因为官方自营店无法满足有元素大约9850这个匹配条件。

所以我们可以使用$elemMatch这个操作符进行组合条件匹配操作,但是需要注意的是,$elemMatch无法匹配非数组的key

db.product.find({"sku.price":{$elemMatch:{$gt:9850,$lt:10000}}});
此时查询就会返回空


11、$where查询

$where 查询是一种非常消耗资源的查询方法,当所有操作符无法达成你的查询要求时,就可以使用$where。但是$where 不走索引,查询速度会怎么样大家应该也很清楚了。所以如无必要就不用使用它。以下我们通过以下查询演示一下$where的查询方法。

db.product.find({$where:function(){if(this.store == "官方自营店"){return true;}return false;}});
查询与db.product.find({store:"官方自营店"})等价,我们可以看见$where查询非常灵活,因为查询是通过JavaScript进行的,所以方便直接。但是查询速度是个大问题,所以一般情况下,我们会先用普通的操作符进行初步筛选,然后再通过$where进行二次筛选,这样的话查询速度会比较可控。关于这种查询会在之后的文章中介绍。


12、分页与排序

在SQL当中排序和分页查询应该算是使用率比较高的一个操作了,在MongoDB当中,分页查询也是相当的重要。下面通过skip limit sort方法去实现分页排序查询。

db.product.find().skip(1).limit(2).sort({"sku.0.price":-1});
查询一开始先通过skip跳开第一行数据,然后限制返回2条数据,查询通过商品的第一个sku的价格进行倒列排序(如果我们需要正序排序将-1改成1即可),返回的结果如下:

{     "_id" : ObjectId("59e9c5872d68f77114ec4fb8"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "description" : "一台贵到666的手机",     "product_number" : "9088816371",     "brand" : "Apple",     "size" : "143.6 X 70.9",     "newest_commment" : {        "comment_content" : "this is newtest comment at that place!",         "user_id" : 109382.0,         "create_date" : ISODate("2017-10-17T01:15:20.466+0000")    },     "sku" : [        {            "capacity" : "64G",             "style" : "silver",             "price" : 9500.0        },         {            "capacity" : "64G",             "style" : "gray",             "price" : 9600.0        },         {            "capacity" : "256G",             "style" : "silver",             "price" : 12388.0        },         {            "capacity" : "256G",             "style" : "gray",             "price" : 12588.0        }    ],     "popular_comment" : [        {            "content" : "Comment A content !",             "user_id" : 399.0,             "popularity_degree" : 89.0        },         {            "content" : "Comment C content !",             "user_id" : 119.0,             "popularity_degree" : 108.0        },         {            "content" : "Comment E content !",             "user_id" : 893.0,             "popularity_degree" : 103.0        }    ],     "keyword" : [        "iphone"    ],     "store" : "金牌苹果店",     "create_date" : ISODate("2017-11-10T00:00:00.000+0000")}{     "_id" : ObjectId("59e47fdb203e071a1b02e544"),     "product_name" : "iPhoneX",     "price" : 8699.0,     "description" : "一台贵到666的手机",     "product_number" : "9088816371",     "brand" : "Apple",     "size" : "143.6 X 70.9",     "newest_commment" : {        "comment_content" : "this is newtest comment at that place!",         "user_id" : 109382.0,         "create_date" : ISODate("2017-10-17T01:15:20.466+0000")    },     "sku" : [        {            "capacity" : "64G",             "style" : "silver",             "price" : 8388.0        },         {            "capacity" : "64G",             "style" : "gray",             "price" : 8388.0        },         {            "capacity" : "256G",             "style" : "silver",             "price" : 9688.0        },         {            "capacity" : "256G",             "style" : "gray",             "price" : 9688.0        }    ],     "popular_comment" : [        {            "content" : "Comment A content !",             "user_id" : 399.0,             "popularity_degree" : 89.0        },         {            "content" : "Comment C content !",             "user_id" : 119.0,             "popularity_degree" : 108.0        },         {            "content" : "Comment E content !",             "user_id" : 893.0,             "popularity_degree" : 103.0        }    ],     "keyword" : [        "苹果",         "iphone",         "apple"    ],     "store" : "官方自营店",     "create_date" : ISODate("2017-10-27T00:00:00.000+0000")}

13、不使用skip进行分页查询

其实使用skip进行分页查询是最为方便的一个做法,但是事实上skip的查询效率上并不高。skip需要先找到需要跳过的数据文档,然后进行丢弃,这个已经足够低效了。如果数据量大的话通过skip进行查询将不会是一个好的策略。我们可以利用一些关键的key,然后通过$gt或者$lt的方式进行跳过的操作。

举个例子

var pageOne = db.product.find().limit(1).sort({"sku.0.price":1});var firstItem = pageOne.next();db.product.find({"sku.0.price":{$gt:firstItem.sku[0].price}}).limit(1).sort({"sku.0.price":1});
可以看见我们是通过游标pageOne,获得第一页最后一个对象,然后通过改对象的价格属性进行$gt条件查询,再通过limit进行限制。重点是两条查询语句必须要使用价格属性进行排序。如果是有两个同样的价格这样就不太奏效了,所以也不是万能的一个方式。


14、游标

其实第13点已经使用了游标了,就是那个pageOne。游标跟我们以前SQL的游标其实差不多,MongoDB的游标在find方法执行完之后会返回,但是不会产生查询,当第一个游标的第一个next方法被出发后默认先会查询100条或者4M大小的数据(选择两者这间的最小者)。当游标已经存在的数据已经耗尽,游标会再去忽的100条数据或者4M大小的数据。所以不必担心游标每次next都会去查询。

var cursor = db.product.find();cursor.forEach(function(item){print(item.product_name);});

15、随机查询

在之前我写过关于SQL反模式的文章,其中说过不要用MySQL的random查询,可以通过random得出一个值然后,通过这个值查询主键大于这个值的数据,limit为一条数据,这样我们就可以获得一条随机的数据了。同样的MongoDB也可以这样去做,不过MongoDB当中主键不是一个自动增长的数,所以之前MySQL中的随机查询我们就用不上了。

我们可以通过为文档添加相应的random属性:

var cursor = db.product.find();cursor.forEach(function(item){item.random = Math.random();db.product.save(item);});db.product.find();
添加完之后,我们可以通过以下这种方式去获得随机的文档:

db.product.find({"random":{$lt:Math.random()}}).limit(1);
当然如果以上的查询查不到数据就可以通过$gt来进行查询,如果两个都查询不到任何数据就可以直接返回空了。

16、快照查询

快照查询是一种安全的查询操作,MongoDB在文档修改后导致原位置无法扩展,会将文档移动到末尾然后进行修改扩展。所以以下这种情况就可能会出现问题

var cursor = db.product.find();cursor.forEach(function(item){item.keyword.push("New");});
如果在添加新的关键字时,发现当前位置没有足够的空间存储新的关键字,MongoDB会将这个文档移动到末尾,然后添加新的关键字。但是这样会导致cursor会在末尾获得到同样的文档。基于解决这种问题,我们可以使用快照查询:

var cursor = db.product.find().snapshot();cursor.forEach(function(item){item.keyword.push("New");});
使用snapshot之后会,按照_id索引去遍历执行。但是虽然这样会安全一点,但是事实上查询效率会有所降低。如非必要也不会使用快照查询。


17、数据库命令

其实在更新的文档当中我已经写过一些书库命令了,以下是一些补充:

通常我们会使用db.collection_name.drop()这种方式去删除一个collection

其中我们可以直接使用数据库命令:

db.runCommand({"drop":"product_pv"});

返回的结果如下:

{     "ns" : "product_service.product_pv",     "nIndexesWas" : 1.0,     "ok" : 1.0}


获得最后一次执行的结果:

db.runCommand({"getLastError":1});
返回结果如下:

{     "connectionId" : 10.0,     "n" : 0.0,     "syncMillis" : 0.0,     "writtenTo" : null,     "err" : null,     "ok" : 1.0}


有些操作只能够是管理员执行,所以不能使用runCommand了,而是adminCommand。例如关闭MongoDB的服务:

db.adminCommand({"shutdown":1});






原创粉丝点击