MongoDB高级查询用法

db的帮助文档

输入:db.help();

db.AddUser(username,password[, readOnly=false])  添加用户  

db.auth(usrename,password)     设置数据库连接验证  

db.cloneDataBase(fromhost)     从目标服务器克隆一个数据库  

db.commandHelp(name)           returns the help for the command  

db.copyDatabase(fromdb,todb,fromhost)  复制数据库fromdb---源数据库名称,todb---目标数据库名称,fromhost---源数据库服务器地址  

db.createCollection(name,{size:3333,capped:333,max:88888})  创建一个数据集,相当于一个表  

db.currentOp()                 取消当前库的当前操作  

db.dropDataBase()              删除当前数据库  

db.eval(func,args)             run code server-side  

db.getCollection(cname)        取得一个数据集合,同用法:db['cname'] or  

db.getCollenctionNames()       取得所有数据集合的名称列表  

db.getLastError()              返回最后一个错误的提示消息  

db.getLastErrorObj()           返回最后一个错误的对象  

db.getMongo()                  取得当前服务器的连接对象get the server  

db.getMondo().setSlaveOk()     allow this connection to read from then nonmaster membr of a replica pair  

db.getName()                   返回当操作数据库的名称  

db.getPrevError()              返回上一个错误对象  

db.getProfilingLevel()         获取profile level  

db.getReplicationInfo()        获得重复的数据  

db.getSisterDB(name)           get the db at the same server as this onew  

db.killOp()                    停止(杀死)在当前库的当前操作  

db.printCollectionStats()      返回当前库的数据集状态  

db.printReplicationInfo()        打印主数据库的复制状态信息  

db.printSlaveReplicationInfo()        打印从数据库的复制状态信息  

db.printShardingStatus()       返回当前数据库是否为共享数据库  

db.removeUser(username)        删除用户  

db.repairDatabase()            修复当前数据库  

db.resetError()  

db.runCommand(cmdObj)          run a database command. if cmdObj is a string, turns it into {cmdObj:1}  

db.setProfilingLevel(level)    设置profile level 0=off,1=slow,2=all  

db.shutdownServer()            关闭当前服务程序  

db.stats()                       返回当前数据库的状态信息

db.version()                   返回当前程序的版本信息

表的帮助,格式:db.表名.help()

db.test.find({id:10})          返回test数据集ID=10的数据集  

db.test.find({id:10}).count()  返回test数据集ID=10的数据总数  

db.test.find({id:10}).limit(2) 返回test数据集ID=10的数据集从第二条开始的数据集  

db.test.find({id:10}).skip(8)  返回test数据集ID=10的数据集从0到第八条的数据集  

db.test.find({id:10}).limit(2).skip(8)  返回test数据集ID=1=的数据集从第二条到第八条的数据  

db.test.find({id:10}).sort()   返回test数据集ID=10的排序数据集  

db.test.findOne([query])       返回符合条件的一条数据  

db.test.getDB()                返回此数据集所属的数据库名称  

db.test.getIndexes()           返回些数据集的索引信息  

db.test.group({key:...,initial:...,reduce:...[,cond:...]})    返回分组信息  

db.test.mapReduce(mayFunction,reduceFunction,)  这个有点像存储过程  

db.test.remove(query)                      在数据集中删除一条数据  

db.test.renameCollection(newName)          重命名些数据集名称  

db.test.save(obj)                          往数据集中插入一条数据  

db.test.stats()                            返回此数据集的状态  

db.test.storageSize()                      返回此数据集的存储大小  

db.test.totalIndexSize()                   返回此数据集的索引文件大小  

db.test.totalSize()                        返回些数据集的总大小  

db.test.update(query,object[,upsert_bool]) 在此数据集中更新一条数据  

db.test.validate()                         验证此数据集  

db.test.getShardVersion()                  返回数据集共享版本号  

版本一:

1 ) . 大于,小于,大于或等于,小于或等于

$gt:大于

$lt:小于

$gte:大于或等于

$lte:小于或等于

例子:

db.collection.find({ "field" : { $gt: value } } );  // greater than  : field > valuedb.collection.find({ "field" : { $lt: value } } );  // less than  :  field= valuedb.collection.find({ "field" : { $lte: value } } );  // less than or equal to : field<=value

如查询j大于3,小于4:

db.things.find({j : {$lt: 3}});

db.things.find({j : {$gte: 4}});

也可以合并在一条语句内:

db.collection.find({ "field" : { $gt: value1, $lt: value2 } } );    // value1 < field < value

2) 不等于 $ne

例子:

db.things.find( { x : { $ne : 3 } } );

3) in 和 not in ($in $nin)

语法:

db.collection.find( { "field" : { $in : array } } );

例子:

db.things.find({j:{$in: [2,4,6]}});

db.things.find({j:{$nin: [2,4,6]}});

4) 取模运算$mod

如下面的运算:

db.things.find( "this.a % 10 == 1")

可用$mod代替:

db.things.find( { a : { $mod : [ 10 , 1 ] } } )

5)  $all

$all和$in类似,但是他需要匹配条件内所有的值:

如有一个对象:

{ a: [ 1, 2, 3 ] }

下面这个条件是可以匹配的:

db.things.find( { a: { $all: [ 2, 3 ] } } );

但是下面这个条件就不行了:

db.things.find( { a: { $all: [ 2, 3, 4 ] } } );

6)  $size

$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:

下面的语句就可以匹配:

db.things.find( { a : { $size: 1 } } );

官网上说不能用来匹配一个范围内的元素,如果想找$size<5之类的,他们建议创建一个字段来保存元素的数量。

You cannot use $size to find a range of sizes (for example: arrays with more than 1 element). If you need to query for a range, create an extra size field that you increment when you add elements.

7)$exists

$exists用来判断一个元素是否存在:

如:

db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回

db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回

8)  $type

$type 基于bsontype来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。

db.things.find( { a : { $type : 2 } } ); // matches if a is a string

db.things.find( { a : { $type : 16 } } ); // matches if a is an int

9)正则表达式

mongo支持正则表达式,如:

db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写

10)  查询数据内的值

下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。

db.things.find( { colors : "red" } );

11) $elemMatch

如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素:

> t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } ) 

{ "_id" : ObjectId("4b5783300334000000000aa9"), 

"x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]

}

$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。

注意,上面的语句和下面是不一样的。

> t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )

$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 }

12)  查询嵌入对象的值

db.postings.find( { "author.name" : "joe" } );

注意用法是author.name,用一个点就行了。更详细的可以看这个链接:dot notation

举个例子:

> db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})

如果我们要查询 authors name 是Jane的, 我们可以这样:

> db.blog.findOne({"author.name" : "Jane"})

如果不用点,那就需要用下面这句才能匹配:

db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})

下面这句:

db.blog.findOne({"author" : {"name" : "Jane"}})

是不能匹配的,因为mongodb对于子对象,他是精确匹配。

13) 元操作符 $not 取反

如:

db.customers.find( { name : { $not : /acme.*corp/i } } );

db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );

mongodb还有很多函数可以用,如排序,统计等,请参考原文。

mongodb目前没有或(or)操作符,只能用变通的办法代替,可以参考下面的链接:

http://www.mongodb.org/display/DOCS/OR+operations+in+query+expressions

版本二:

shell 环境下的操作:

   1.  超级用户相关:

         1. #进入数据库admin

             use admin

         2. #增加或修改用户密码

          db.addUser('name','pwd')

         3. #查看用户列表

          db.system.users.find()

         4. #用户认证

          db.auth('name','pwd')

         5. #删除用户

          db.removeUser('name')

         6. #查看所有用户

          show users

         7. #查看所有数据库

          show dbs

         8. #查看所有的collection

          show collections

         9. #查看各collection的状态

          db.printCollectionStats()

        10. #查看主从复制状态

          db.printReplicationInfo()

        11. #修复数据库

          db.repairDatabase()

        12. #设置记录profiling,0=off 1=slow 2=all

          db.setProfilingLevel(1)

        13. #查看profiling

          show profile

        14. #拷贝数据库

          db.copyDatabase('mail_addr','mail_addr_tmp')

        15. #删除collection

          db.mail_addr.drop()

        16. #删除当前的数据库

          db.dropDatabase()

   2. 增删改

         1. #存储嵌套的对象

             db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})

         2. #存储数组对象

             db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})

         3. #根据query条件修改,如果不存在则插入,允许修改多条记录

            db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)

         4. #删除yy=5的记录

            db.foo.remove({'yy':5})

         5. #删除所有的记录

            db.foo.remove()

   3. 索引

         1. #增加索引:1(ascending),-1(descending)

         2. db.foo.ensureIndex({firstname: 1, lastname: 1}, {unique: true});

         3. #索引子对象

         4. db.user_addr.ensureIndex({'Al.Em': 1})

         5. #查看索引信息

         6. db.foo.getIndexes()

         7. db.foo.getIndexKeys()

         8. #根据索引名删除索引

         9. db.user_addr.dropIndex('Al.Em_1')

   4. 查询

         1. #查找所有

        2. db.foo.find()

        3. #查找一条记录

        4. db.foo.findOne()

        5. #根据条件检索10条记录

        6. db.foo.find({'msg':'Hello 1'}).limit(10)

        7. #sort排序

        8. db.deliver_status.find({'From':'ixigua@sina.com'}).sort({'Dt',-1})

         9. db.deliver_status.find().sort({'Ct':-1}).limit(1)

        10. #count操作

        11. db.user_addr.count()

        12. #distinct操作,查询指定列,去重复

        13. db.foo.distinct('msg')

        14. #”>=”操作

        15. db.foo.find({"timestamp": {"$gte" : 2}})

        16. #子对象的查找

        17. db.foo.find({'address.city':'beijing'})

   5. 管理

         1. #查看collection数据的大小

         2. db.deliver_status.dataSize()

         3. #查看colleciont状态

         4. db.deliver_status.stats()

         5. #查询所有索引的大小

         6. db.deliver_status.totalIndexSize()

6.  高级查询

条件操作符

$gt : >

$lt : <

$gte: >=

$lte: <=

$ne : !=、<>

$in : in

$nin: not in

$all: all

$not: 反匹配(1.3.3及以上版本)

查询 name <> "bruce" and age >= 18 的数据

db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});

查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据

db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});

查询 age in (20,22,24,26) 的数据

db.users.find({age: {$in: [20,22,24,26]}});

查询 age取模10等于0 的数据

db.users.find('this.age % 10 == 0');

或者

db.users.find({age : {$mod : [10, 0]}});

匹配所有

db.users.find({favorite_number : {$all : [6, 8]}});

可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] }

可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }

查询不匹配name=B*带头的记录

db.users.find({name: {$not: /^B.*/}});

查询 age取模10不等于0 的数据

db.users.find({age : {$not: {$mod : [10, 0]}}});

#返回部分字段

选择返回age和_id字段(_id字段总是会被返回)

db.users.find({}, {age:1});

db.users.find({}, {age:3});

db.users.find({}, {age:true});

db.users.find({ name : "bruce" }, {age:1});

0为false, 非0为true

选择返回age、address和_id字段

db.users.find({ name : "bruce" }, {age:1, address:1});

排除返回age、address和_id字段

db.users.find({}, {age:0, address:false});

db.users.find({ name : "bruce" }, {age:0, address:false});

数组元素个数判断

对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录

匹配db.users.find({favorite_number: {$size: 3}});

不匹配db.users.find({favorite_number: {$size: 2}});

$exists判断字段是否存在

查询所有存在name字段的记录

db.users.find({name: {$exists: true}});

查询所有不存在phone字段的记录

db.users.find({phone: {$exists: false}});

$type判断字段类型

查询所有name字段是字符类型的

db.users.find({name: {$type: 2}});

查询所有age字段是整型的

db.users.find({age: {$type: 16}});

对于字符字段,可以使用正则表达式

查询以字母b或者B带头的所有记录

db.users.find({name: /^b.*/i});

$elemMatch(1.3.1及以上版本)

为数组的字段中匹配其中某个元素

Javascript查询和$where查询

查询 age > 18 的记录,以下查询都一样

db.users.find({age: {$gt: 18}});

db.users.find({$where: "this.age > 18"});

db.users.find("this.age > 18");

f = function() {return this.age > 18} db.users.find(f);

排序sort()

以年龄升序asc

db.users.find().sort({age: 1});

以年龄降序desc

db.users.find().sort({age: -1});

限制返回记录数量limit()

返回5条记录

db.users.find().limit(5);

返回3条记录并打印信息

db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)});

结果

my age is 18

my age is 19

my age is 20

限制返回记录的开始点skip()

从第3条记录开始,返回5条记录(limit 3, 5)

db.users.find().skip(3).limit(5);

查询记录条数count()

db.users.find().count();

db.users.find({age:18}).count();

以下返回的不是5,而是user表中所有的记录数量

db.users.find().skip(10).limit(5).count();

如果要返回限制之后的记录数量,要使用count(true)或者count(非0)

db.users.find().skip(10).limit(5).count(true);

分组group()

假设test表只有以下一条数据

{ domain: "www.mongodb.org"

, invoked_at: {d:"2009-11-03", t:"17:14:05"}

, response_time: 0.05

, http_action: "GET /display/DOCS/Aggregation"

}

使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count;

db.test.group(

{ cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}

, key: {http_action: true}

, initial: {count: 0, total_time:0}

, reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }

, finalize: function(out){ out.avg_time = out.total_time / out.count }

} );

[

{

"http_action" : "GET /display/DOCS/Aggregation",

"count" : 1,

"total_time" : 0.05,

"avg_time" : 0.05

}

]

MongoDB 高级聚合查询

MongoDB版本为:2.0.8 

系统为:64位Ubuntu 12.04

如你所见,我尽量的模拟现实生活中的场景。这是一个人的实体,他有基本的manId, manName, 有朋友[myFriends],有喜欢的水果[fruits],而且每种水果都有喜欢的权重。

很不好的是你还看见了有个“_class”字段? 因为我是Java开发者, 我还喜欢用Spring,因此我选用了Spring Data Mongo的类库[也算是框架吧,但是我不这么觉得]。

现在有很多人Spring见的腻了也开始烦了。是的,Spring野心很大,他几乎想要垄断Java方面的任何事情。没办法我从使用Spring后就离不开他,以至于其他框架基本上都不用学。我学了Spring的很多,诸如:Spring Security/Spring Integration/Spring Batch等。。。不发明轮子的他已经提供了编程里的很多场景,我利用那些场景解决了工作中的很多问题,也使我的工作变得很高效。从而我又时间学到它更多。Spring Data Mongo封装了mongodb java driver,提供了和SpringJDBC/Template一致编程风格的MongoTemplate。

见:http://static.springsource.org/spring-data/data-mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html

不说废话了,我们直接来MongoDB吧。

Max 和Min

我和同事在测试Mongo时,索引还写了不到一半,他想查询某个字段的最大值,结果找了半天文档也没找到关于max的函数。我也很纳闷这是常规函数啊怎么不提供? 后来经过翻阅资料确定Mongo确实不提供直接的max和min函数。但是可以通过间接的方式[sort 和 limit]实现这个。

要查询最大值我们只需要把结果集按照降序排列,取第一个值就是了。

如我的例子,我想取得集合中年龄最大的人。

1db.person.find({}).sort({"age": -1}).limit(1)

相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。

当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。

distinct

MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits].

如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。

如上面的表结构,我想统计所有的喜欢的水果。

1db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.

 他成功执行了。输出如:

1[ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr"]

 我想统计集合中共有多少个人[按名字吧]

1db.person.distinct("manName")

 我想统计指定个数的人的共同关注的朋友。

1db.person.distinct("myFriends", {"manName": {"$in": ["ZhenQin", "YangYan"]}})

 输出如:

1[ "234567", "345678", "456789", "987654", "ni", "wo"]

参考:https://www.cnblogs.com/t2xingzhe/p/3555268.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,893评论 2 89
  • 目录 查询操作 集合查询方法 find() 查询内嵌文档 查询操作符(内含 数组查询) "$gt" 、"$gte"...
    彩虹之梦阅读 1,008评论 0 1
  • 你好,10月12日,多云,清冷,哈市还没有供暖,所以还没有雾霾。今天啊,做的唯一一件不同的事情是,今天早起吃了个早...
    寒江北阅读 188评论 0 0
  • 【第四十二章】 钟山风雨起苍黄 文/慕凉卿卿 前情回顾:上官易设计坑害段宸曜,意图歼其全军,京都城门为引段宸曜入瓮...
    慕凉卿卿阅读 347评论 2 5
  • 这篇文章分享我的 Android 开发(入门)课程 的第六个实战项目:旅游指南应用。之所以为此单独列出一篇文章来,...
    HsuJin阅读 1,330评论 0 10