版本一:7 N t. g. `: _8 p9 }% k
* N, q. v( M* ?. P F$ F" o1 ) . 大于,小于,大于或等于,小于或等于8 I& F$ m9 k! v3 r' x, Q
( a- K1 \) d& D2 x$gt:大于+ A2 Q, Q: q K
$lt:小于
% g' O, S9 z5 ?; _$gte:大于或等于
$ p, ]& V/ \' n/ o$lte:小于或等于
0 F9 u( b5 b* ^5 C- T! }9 d% Z9 ~8 g- Q0 `
例子: - db.collection.find({ "field" : { $gt: value } } ); // greater than : field > value9 U" D( \4 R; I/ s2 |: X, X8 ?
- db.collection.find({ "field" : { $lt: value } } ); // less than : field < value% O0 r3 c% e8 ?5 X+ g! g- p
- db.collection.find({ "field" : { $gte: value } } ); // greater than or equal to : field >= value R' Y6 N/ ]: ?# w
- db.collection.find({ "field" : { $lte: value } } ); // less than or equal to : field <= value
复制代码 8 v3 Y" C& H3 v j
如查询j大于3,小于4: - db.things.find({j : {$lt: 3}});
1 p! `5 g3 M$ Z/ \2 l T - db.things.find({j : {$gte: 4}});
复制代码
; c$ Q' d$ G- j( V& S( O2 ?5 ?. y& O也可以合并在一条语句内: - db.collection.find({ "field" : { $gt: value1, $lt: value2 } } ); // value1 < field < value
复制代码
3 d8 [2 k& f3 ^3 C: _
( B& Z$ ~3 O1 t1 @
" z `/ y' @2 r2) 不等于 $ne 例子: - db.things.find( { x : { $ne : 3 } } );
复制代码
7 C1 w4 w S( s* i3) in 和 not in ($in $nin)* ^, d+ j+ x5 N3 D" ~. x
: b$ L3 S/ V! Q' P8 m- @) @) P7 S语法: - db.collection.find( { "field" : { $in : array } } );
复制代码
' p$ w1 K8 z! ?5 R0 I% R4 r例子: - db.things.find({j:{$in: [2,4,6]}});6 i5 c% |. y: V- G, S% A7 {
- db.things.find({j:{$nin: [2,4,6]}});
复制代码 - X& V% y# y/ B8 u% @
0 D1 m- x( r( n8 I! H5 M
4) 取模运算$mod
( \ q+ n1 m9 l8 h' X& W* `/ b( B& `
如下面的运算: - db.things.find( "this.a % 10 == 1")
复制代码
* `& Z4 s$ \, b6 q/ K D可用$mod代替: - db.things.find( { a : { $mod : [ 10 , 1 ] } } )
复制代码
. r8 i0 S. u# F. Y% h4 E1 {, v5 a. Z
( i) N5 e5 z, H+ R' S+ Q5) $all
, l" {. F) i# V( \6 u _5 D% t) Q# b3 X* [* ?: l
$all和$in类似,但是他需要匹配条件内所有的值:4 H9 N7 Q% p$ B- X: v! k0 n
; t0 J' G( f1 X, _: F, {如有一个对象:
# i! L% i! N+ E8 Q9 X' \, N 3 w+ e, Z J3 G+ b c' L
下面这个条件是可以匹配的: - db.things.find( { a: { $all: [ 2, 3 ] } } );
复制代码 2 }# u% j3 G: d. k
但是下面这个条件就不行了: - db.things.find( { a: { $all: [ 2, 3, 4 ] } } );
复制代码
: A2 v4 X2 ~( f' M: }( C# B" B f0 N& y$ M; K- L7 q3 s9 F
6) $size
' h! h9 u5 r, T: L" w' `2 U* ?5 b! N3 W# n% Q) e
$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:
/ X9 m4 |- e( u+ C; O ~
- B6 s9 w- J0 Z( H/ Z, Z0 k% J下面的语句就可以匹配: - db.things.find( { a : { $size: 1 } } );
复制代码 % u; D4 Z9 @8 K; y( e: b
官网上说不能用来匹配一个范围内的元素,如果想找$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. $ x; T- }/ }7 w* G" y2 F
7)$exists $exists用来判断一个元素是否存在: 如: - db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回
* d# n( L0 Y" d5 Z7 M. u$ x - db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回
复制代码 % K" W# } y& _' i& f; ~4 {4 k
8) $type $type 基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。 - db.things.find( { a : { $type : 2 } } ); // matches if a is a string
/ z3 T2 M2 }% s# n - db.things.find( { a : { $type : 16 } } ); // matches if a is an int
复制代码
4 ^* Q3 ]- m/ N5 }" m" Z9 t! c9)正则表达式
" I. k4 _+ ]& w8 @" S1 n! C
1 O% @1 k; L dmongo支持正则表达式,如: - db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写
复制代码 ( L# u, E9 i8 c1 q5 f5 n- L) W) I
10) 查询数据内的值0 }/ y% U+ F+ u# v7 J" j. |$ d% {) T
& a. ?5 }/ J+ W/ G) Q& F" a
下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。 - db.things.find( { colors : "red" } );
复制代码 . {( c0 p# o1 M3 k
11) $elemMatch t. W7 C8 ~( z* T
- O ~/ _3 s- `9 _! Y
如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素: - > t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } ) 5 l2 C- [* C9 ]; i2 V' X# g
- { "_id" : ObjectId("4b5783300334000000000aa9"), , q; i8 x% j9 p) Q+ @* o% }( f; {
- "x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]: O0 o3 {8 C: l$ e: t
- }
复制代码 ; j: j2 I6 J; c; i" ~0 B, G4 o
$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。注意,上面的语句和下面是不一样的。 > t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )
7 I( {& W/ `+ Y* s$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 } * X b/ y6 u4 z
) j* _& X1 n+ H12) 查询嵌入对象的值 - db.postings.find( { "author.name" : "joe" } );
复制代码 5 l0 O+ A6 x: @( `1 r; e" ?, r H
举个例子: - > db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
复制代码
: V" T) R1 g3 \! O如果我们要查询 authors name 是Jane的, 我们可以这样: - > db.blog.findOne({"author.name" : "Jane"})
复制代码 3 u2 D. D+ I) J7 N; H
如果不用点,那就需要用下面这句才能匹配: - db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
复制代码
- a, } L$ q( p5 [5 _3 Q下面这句: - db.blog.findOne({"author" : {"name" : "Jane"}})
复制代码 . F5 ~2 A: s3 h) X
是不能匹配的,因为mongodb对于子对象,他是精确匹配。
( |! y+ }2 a7 H1 d7 @13) 元操作符 $not 取反 如: - db.customers.find( { name : { $not : /acme.*corp/i } } );+ V# q- @9 E" ?+ ?! j5 F
- db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
复制代码 ; U0 \) w) {. f- ~0 L
shell 环境下的操作: 1. 超级用户相关: 1. #进入数据库admin
- E( Q* A2 ?9 ^8 A
! \' F5 }: e7 n- |+ V 2. #增加或修改用户密码
, I3 C( t/ y: _9 f' b4 H; s! ?3 F 3. #查看用户列表 $ B1 h. M9 E1 q+ D# R0 d) t% e
4. #用户认证 5. #删除用户 6. #查看所有用户
8 ?' L; O( e$ f ~! d( i- L 7. #查看所有数据库 8. #查看所有的collection
9 I/ Y3 r3 g( \( d3 J! P6 L 9. #查看各collection的状态 - db.printCollectionStats()
复制代码 + {& l' K* m6 k- b9 ]
10. #查看主从复制状态 - db.printReplicationInfo()
复制代码 0 G3 S7 r7 u+ e; U7 A' u, c6 I
11. #修复数据库 12. #设置记录profiling,0=off 1=slow 2=all 13. #查看profiling 14. #拷贝数据库 - db.copyDatabase('mail_addr','mail_addr_tmp')
复制代码
" p) v: V4 i0 k9 v 15. #删除collection 16. #删除当前的数据库 - s9 V7 q" m; A5 b& G7 e4 V) m
2. 增删改 1. #存储嵌套的对象 - db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
复制代码 . `& l8 H1 u2 S# I7 z+ f1 e
2. #存储数组对象 - db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
复制代码
+ V/ x' c- W3 g 3. #根据query条件修改,如果不存在则插入,允许修改多条记录 - db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)
复制代码 3 ?* W/ B) P: M5 u' W+ j) r
4. #删除yy=5的记录 5. #删除所有的记录 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() + N& [. I$ ~! s, o
6. 高级查询 条件操作符
8 R+ ^- V# W1 x3 b- $gt : > 4 [( u# a w& |
- $lt : < # I z. h/ J& H! a- L2 Z
- $gte: >=
5 r( q% `: B: |& A" s9 F - $lte: <= : a& ?) X }& ` z" u2 L( G( q
- $ne : !=、<> * j9 ^, p8 Y, ^ q% |5 h5 l6 r
- $in : in 5 I0 S7 }% j8 A5 R8 F* O" F# N
- $nin: not in ( H; y+ e L! K' F1 v) Y
- $all: all # M# l- N6 G: h x8 }
- $not: 反匹配(1.3.3及以上版本)
复制代码 4 |, o3 I2 K4 d! X8 v1 ]* ^
& m6 J, L+ c4 B; O& W+ _
查询 name <> "bruce" and age >= 18 的数据
7 L% K7 E( {5 D9 k- db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});
复制代码 % @- x) H& z6 l2 a7 g
+ F4 M; J5 Z: u6 \
查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据
9 S0 |* r' @: Q& }- db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});
复制代码 ' h7 J' z: @ D* ?3 x6 t
# w2 O( l( M( C
查询 age in (20,22,24,26) 的数据 * ~6 a8 [7 s/ \+ F* a
- db.users.find({age: {$in: [20,22,24,26]}});
复制代码 & O5 _% C7 N# [0 j, Q$ V9 A
" l; X4 w8 H8 d, `, X4 j
查询 age取模10等于0 的数据 ; l. S3 x% D4 {' c c' l
- db.users.find('this.age % 10 == 0');
复制代码 9 c8 E* J8 A& x) E7 |' g! M& P) ^
或者
/ k, {4 h% v" a! M/ S+ ^6 H- db.users.find({age : {$mod : [10, 0]}});
复制代码 % Z* z) A6 H# @" G
) Q# Y1 D5 K# j# \( M8 h匹配所有 0 ~. H, e: q. \3 o( X+ L
- db.users.find({favorite_number : {$all : [6, 8]}});
复制代码 % {2 |( e( q S; P6 n& M5 o$ N! h/ ~
可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] }
# I$ U9 `4 M! G$ I: \可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] } ! A% A% p$ f/ W. W' l
$ {( k: J; [5 p, X: X
查询不匹配name=B*带头的记录
! g4 v# n4 d2 n( S- db.users.find({name: {$not: /^B.*/}});
复制代码
+ ~2 F( ~+ a1 j* A D7 X& h0 w查询 age取模10不等于0 的数据
+ u$ q& ^& W' I+ {$ L* ?- T V- db.users.find({age : {$not: {$mod : [10, 0]}}});
复制代码
- v0 p' Z. x$ `# ^6 g
9 p# |9 x o. Q#返回部分字段
' p5 n$ b) j; x选择返回age和_id字段(_id字段总是会被返回) ! F v2 p) j; {1 }& t
- db.users.find({}, {age:1}); ; H% \. D, e$ A
- db.users.find({}, {age:3});
. ~# g5 {2 H+ j( F. ^ - db.users.find({}, {age:true}); . o6 v7 N: j4 | ]
- db.users.find({ name : "bruce" }, {age:1});
复制代码
! V; }3 b- @' y3 d% d/ \, Z0为false, 非0为true 4 N# C' P2 J L+ i) p w
+ P1 N% T! f, x# Q0 V9 y
选择返回age、address和_id字段 * t D! v* L* F2 R- H, O
- db.users.find({ name : "bruce" }, {age:1, address:1});
复制代码 4 D& c; w$ Q' {/ o5 i3 j4 j$ K
8 a$ Q. ^0 p6 n1 f1 W H排除返回age、address和_id字段 & o8 n, u" U- F4 P5 @+ `# b
- db.users.find({}, {age:0, address:false});
9 Y; r7 }0 L5 ?/ a+ D4 r - db.users.find({ name : "bruce" }, {age:0, address:false});
复制代码 " @9 p( F& s8 P& n, U V6 Z: I
& f- N- B8 n2 i5 Q" u
数组元素个数判断 ) H; f% {( x. l( n" |* @3 t9 s
对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录 6 O$ B* T. c* F! B
匹配db.users.find({favorite_number: {$size: 3}});
( k% c# z0 K, H0 M9 v不匹配db.users.find({favorite_number: {$size: 2}});
% k! _" U" _2 p* A; o
- O3 U! v- O) t5 j2 y. U) H( |$exists判断字段是否存在 ) f7 W/ C( H. K% {" J/ h, r
查询所有存在name字段的记录
, b5 F3 N* N3 p+ F- R6 E- db.users.find({name: {$exists: true}});
复制代码 ; J. ^0 t- q: ^" e5 {
查询所有不存在phone字段的记录
( E; M" T2 r6 L0 m1 g+ F- db.users.find({phone: {$exists: false}});
复制代码 5 i9 l2 f) v: j) ]* z6 b/ d5 P
- k6 a4 C" y7 r$ \' {
$type判断字段类型
# ?6 ]6 o: \' a# R4 |. c& O7 V& x查询所有name字段是字符类型的
! N* G3 I% g3 F# w. d8 X1 @- db.users.find({name: {$type: 2}}); 5 e5 y3 P9 }% W! O) @
复制代码
3 n: ^. K ?9 e) C" T/ p# M0 M7 y查询所有age字段是整型的 1 |' k8 x. ^* W6 I. D/ H
- db.users.find({age: {$type: 16}}); + v9 B- y( |) z, l2 ]' S2 {( C+ O2 T
复制代码 * K. r# F- W8 K! O2 Z- i
对于字符字段,可以使用正则表达式
$ y7 Q3 K; f+ d, f1 N1 }9 S; o L8 v D查询以字母b或者B带头的所有记录 ; D0 I9 @ `: l7 E; l
- db.users.find({name: /^b.*/i}); W0 ~' p( V9 `
复制代码
; p3 o2 G1 \/ s& T8 F$elemMatch(1.3.1及以上版本)
& i" J# O# Y" e" ~, K6 x0 E为数组的字段中匹配其中某个元素 # c: U0 I4 w" m
5 C5 ]; _+ S; q' P
Javascript查询和$where查询 ) `7 L" L. q+ n+ Y, R. @! e, k! U
查询 age > 18 的记录,以下查询都一样 5 b5 i' t# H& V& X6 W1 S2 A6 `
- db.users.find({age: {$gt: 18}});
2 s a7 G8 k- |% w - db.users.find({$where: "this.age > 18"}); / y) a( T6 I7 ? O3 G7 `
- db.users.find("this.age > 18");
' z% X& P6 s, }: `2 c - f = function() {return this.age > 18} db.users.find(f);
复制代码 0 \, k- X r8 C5 v( ^
" I& ?! [. b8 w3 v d# j- u
排序sort()
7 y* V) C5 j, g+ {3 Z以年龄升序asc
! ?0 k7 i7 x& {- db.users.find().sort({age: 1});
! Q) b4 ~, Q5 h( q6 u9 g
复制代码 $ z! y1 b+ `- P# U2 b( f: c; r
以年龄降序desc
; G. U0 t/ i& V( @* k. B- J- db.users.find().sort({age: -1}); $ J6 u+ X( w7 K! T
复制代码 5 {+ n6 b# K. W8 L
限制返回记录数量limit() 6 C1 B( a9 ~3 ?& |! `
返回5条记录
7 m9 Y6 @6 \1 \2 ] G% O- ?* N }( u+ B- db.users.find().limit(5);
' L! c. H5 }- }
复制代码
. u5 T' b: |/ W; i返回3条记录并打印信息 $ a3 g: N5 C( |9 m1 w( C# d# h
- db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)});
& H2 P+ l2 a6 f4 r
复制代码 ' I. u* _1 Z5 e. Q# t" k" m% P
结果
; [4 ]$ ~7 P* ]2 @8 Y/ m3 G- my age is 18 ! j* ` t' ]$ t& s; \
- my age is 19 9 ^, \& d* L( `$ ^9 w) u R) P
- my age is 20
复制代码 & I' e. M; ~' R/ j1 W' T9 A3 s
# ~) C$ I) x" B( R" V, q# |1 z
限制返回记录的开始点skip()
0 h- z# Y% S; [% M; e从第3条记录开始,返回5条记录(limit 3, 5) 0 a. O+ S* @+ [9 p9 }# p- H" h
- db.users.find().skip(3).limit(5); ( H+ G: U3 P% o3 b1 D
复制代码 1 F4 m) y0 e/ z& F3 P
查询记录条数count()
6 h" T: F4 @4 O: Tdb.users.find().count();
6 f! Z( f& Z: {9 Pdb.users.find({age:18}).count();
2 l9 A0 t2 R8 s w以下返回的不是5,而是user表中所有的记录数量
4 ?4 |' y p7 w) bdb.users.find().skip(10).limit(5).count();
1 C. b% u, J5 H3 [; Z& y如果要返回限制之后的记录数量,要使用count(true)或者count(非0)
0 B; L! a/ |7 ]5 K, C% t- db.users.find().skip(10).limit(5).count(true);
复制代码 , D' H+ {, D$ e% t
2 P9 b# y5 _0 X/ x分组group() ) A2 |/ Z; M; d: i2 o
假设test表只有以下一条数据 * Z1 U: H: ~8 @# l% h* D$ @/ |
- { domain: "www.mongodb.org"
* Y7 n- H6 o. j3 e- ~/ l - , invoked_at: {d:"2009-11-03", t:"17:14:05"} . I6 p; D* G2 [( W2 o# S- m7 ^
- , response_time: 0.05
$ a5 G" J' I9 r5 T A$ _ - , http_action: "GET /display/DOCS/Aggregation"
0 H1 G" @3 Y3 x1 i$ t% N - }
复制代码
" X1 p/ j+ K; ^使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count;
3 E, j& G. |" A/ B y- db.test.group(
9 \+ U. J' o4 K% R" V! T - { cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}} 7 T" s; h1 J, k4 v4 Q. H
- , key: {http_action: true} ' F! A8 h2 H2 ~% R$ @
- , initial: {count: 0, total_time:0} 1 P4 C& y) i5 J7 J2 D
- , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
: Q- [% N1 i" l' J0 p0 a - , finalize: function(out){ out.avg_time = out.total_time / out.count }
; }( Z/ N; p9 F$ H - } );
* e9 p! d& O Q! ?& E7 s5 q
) g# J9 h W5 T# N% E1 {) g! R9 a- [
2 s6 Z& Q, o4 P- i, w- W& N) z - { $ _' O, X, ~3 U2 H# z+ b
- "http_action" : "GET /display/DOCS/Aggregation",
1 G( q9 ?1 M# @( c" s - "count" : 1, / k& Q* K t' _9 A+ z% a
- "total_time" : 0.05, 5 }7 r- Q4 ?$ T0 s4 H
- "avg_time" : 0.05
" o% L; N1 B6 P# ]" C" d" G6 R0 b8 | - } * o' a8 u- u' M: v5 B
- ]
复制代码 9 |0 ~$ s4 r; V$ M0 V
1 ^* g" d& I+ |) h1 S! r: o
% |# u) a; m7 E) {. V0 f/ U9 ?MongoDB 高级聚合查询MongoDB版本为:2.0.8 系统为:64位Ubuntu 12.04 先给他家看一下我的表结构[Oh sorry, Mongo叫集合] 如你所见,我尽量的模拟现实生活中的场景。这是一个人的实体,他有基本的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。 不说废话了,我们直接来MongoDB吧。 - Max 和Min3 J/ S* @" Z2 S9 s1 o% c
我和同事在测试Mongo时,索引还写了不到一半,他想查询某个字段的最大值,结果找了半天文档也没找到关于max的函数。我也很纳闷这是常规函数啊怎么不提供? 后来经过翻阅资料确定Mongo确实不提供直接的max和min函数。但是可以通过间接的方式[sort 和 limit]实现这个。 要查询最大值我们只需要把结果集按照降序排列,取第一个值就是了。 如我的例子,我想取得集合中年龄最大的人。 - db.person.find({}).sort({"age" : -1}).limit(1)
复制代码
) d4 _+ N1 i+ R0 d! N8 `4 s9 f& M' N F+ _, M% z, g. j" M" J- ^( S
$ N. Q5 S# b! _6 N9 C# `; J( H2 N. H
相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。 当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。 - distinct
. n- X' W8 Z: V% n
MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits]. 如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。 如上面的表结构,我想统计所有的喜欢的水果。 - db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.
复制代码
; A" L( p) k) t, b* r
! w, L; |! K, ^ 他成功执行了。输出如: - [ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr" ]
复制代码 8 G6 z5 J3 E$ @0 V& W
; @: ?- z9 D& @! \2 x 我想统计集合中共有多少个人[按名字吧] - db.person.distinct("manName")
复制代码 J. K, ^( v' r( o9 @
7 ~8 }0 z: B& |; D6 t
我想统计指定个数的人的共同关注的朋友。 - db.person.distinct("myFriends", {"manName" : {"$in" : ["ZhenQin", "YangYan"]}})
复制代码
' g E* @( r$ t. b- u0 s
0 M J% s! s% I) H" q' N) h 输出如: -
% U6 @* X! X8 t+ q - [ "234567", "345678", "456789", "987654", "ni", "wo" ]
复制代码
' t P6 e: o& _8 e9 H& \9 H/ h ]& _2 f3 R; E t: G
3 w$ u- V6 u* M$ E/ u+ O. T
那么我使用Java呢? 我只是在演示Mongo的命令,用Spring Data Mongo是怎么操作的? Spring Schema: - <beans xmlns="http://www.springframework.org/schema/beans"
, a1 T* i4 v2 O1 _3 T8 I" A - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance": C/ ^5 r: W) I
- xmlns:context="http://www.springframework.org/schema/context"
) \8 s2 m, @% G4 D! ^5 y - xmlns:mongo="http://www.springframework.org/schema/data/mongo", K+ B" D. Y1 J' x
- xsi:schemaLocation="http://www.springframework.org/schema/beans
+ m z5 v( t/ |7 o' J4 ~ - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd9 j# [* N# Y6 f' A; b
- http://www.springframework.org/schema/context
; l& m+ f$ x; y( ^) q. M - http://www.springframework.org/schema/context/spring-context-3.1.xsd% V2 d3 N1 F( L% j
- http://www.springframework.org/schema/data/mongo3 O8 P) b0 g& b C& U/ n
- http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">8 y; T2 f1 N1 |' d( ?
-
! ?! l Y6 @ R, z, O) ~ - <context:property-placeholder location="classpath:mongo.properties" />
) m3 B( V1 y% d7 i - 0 k7 l$ f6 T; U3 `: x
- <!-- Default bean name is 'mongo' -->
6 Y$ L! c7 `8 U+ f. E3 b - <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" />
0 H% O H4 E& `$ b: c6 L - & g' `: w2 m7 `1 `9 H6 {& o H2 G
- <mongo:db-factory id="mongoDbFactory"/ M; G8 Y9 E2 a# v5 y) H" x1 m
- mongo-ref="mongo"
X8 U+ i3 s# T - dbname="mongotest" />
7 D7 B' A- |# J9 {$ Y -
: ~+ {6 O+ R' u. \" T0 B3 T! F2 W - <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
, T( \) }: M; L G$ f - <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>5 j4 o* T+ |3 ~1 D0 A' @+ O
- </bean>
3 K- c; U, s0 |" E9 R! q& r! B - </beans>
复制代码
/ {7 ^/ T3 k4 i2 p1 e $ w- z1 ?: R) l) {1 {1 K- U6 U
max和min的测试: - @Test& ~+ Q3 m% V1 {. u
- public void testMaxAndMinAge() throws Exception {
- o' z9 C, K; R) d4 y - Query q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.ASC, "age"))).limit(1);3 N2 n) |. ?$ t
- Person result = mongoTemplate.findOne(q, Person.class);7 _9 o1 x, P7 S5 ~
- log.info(result);
5 k: e0 W0 c0 L! U/ f/ ~ -
9 _* V. C* E& \ I, q: \% M- C - q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.DESC, "age"))).limit(1);+ {3 O/ C2 S# b3 J" X
- result = mongoTemplate.findOne(q, Person.class);
, b& ^+ b( M6 C% B/ i - log.info(result);
* W/ j7 G! b+ l1 M0 ?+ q - }
复制代码
( ~2 d2 K% g# O: n& [* N8 g2 Y" N
) j. Z2 z5 N% N, n distinct的测试: - @Test1 ]" m) h/ W: b) W9 g
- public void testDistinct() throws Exception {
" P$ O7 V, |. e4 |* E/ k9 W- y7 e - List result = mongoTemplate.getCollection("person").distinct("myFriends");4 {2 ^: u0 ^, o5 o/ s# S
- for (Object o : result) {
c! z9 g8 ^- W. i& ^3 p - log.info(o);- C( `0 R% |% c, _" C
- }
- k5 P L ?+ ^( a7 D' E! d8 Y - 2 B \; f% ^; s$ e% q# O
- log.info("==================================================================");
) ]) t% d( A. {/ w" q - Query query = Query.query(Criteria.where("manId").is("123456"));/ n8 }2 R' |/ _# `
- result = mongoTemplate.getCollection("person").distinct("myFriends", query.getQueryObject());# z* s& A+ s; S* v5 K8 n
- for (Object o : result) {1 @: ?2 r f+ c1 r, S& M+ |) y% [
- log.info(o);; ~+ R. d" l, B& f2 g, K! ?
- }
. a3 G ^1 \" Q- c -
# U: r0 \' ^9 C! v: d - log.info("==================================================================");
& }/ S# j$ p4 ?* @ - result = mongoTemplate.getCollection("person").distinct("fruits.fruitId");
0 t- V* Z9 N" g+ y t a; I. B - for (Object o : result) {
4 }7 x9 ]% M# @1 b4 s8 Q: [ - log.info(o);7 D, D/ b) {; y
- }
, ~) x; a5 s+ V" b8 I: _ - }
复制代码 1 r8 `( Y& ^, p4 b
& I0 I/ S- L" X 输出的结果为: - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 234567
1 O. [; C5 G9 I- o! i" o - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 345678& x: C3 X% i% _& Y% m
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 456789( k5 E5 i) D* L9 i* w( E& W
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 987654
& w) n9 j3 @+ ^8 l6 ^ - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] ni
: ` V3 S6 J+ M9 V% Z- H - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] wo
8 g% y( h$ I& ~. D, _ m1 Z) H3 q5 D- s - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 123456
9 H, e4 q6 I. P& J0 { - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(75)] ==================================================================
& X ~8 h/ P! }& i' N - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 234567
5 F9 S: R1 W( V8 b, B - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 345678
9 c# Y4 w. }5 E; o* O - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 456789+ Z9 A( V4 W, w- z* k. Y
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 987654
, i0 V) X3 Q; w, { - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(82)] ==================================================================+ C: i2 w* D' E6 g/ C$ ]( v
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] aaa& X1 `: `: R- I$ ~; a1 t( h& e
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] bbb1 [$ I+ I' U3 ] _( r6 c3 [+ F
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] ccc, M, w. V& {( C' r: G
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] www
% m5 n5 |1 a! D% _: w/ u7 s - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] xxx/ t' N, {& y$ _
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] yyy
) F$ T0 Z3 ^6 T6 k2 n - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] zzz
+ i. o: A7 a+ l+ ~4 ~ - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] rrr A. i' Y% k/ P- @6 l. S
- 12-22 14:13:45 [INFO] [support.GenericApplicationContext(1020)] Closing org.springframework.context.support.GenericApplicationContext@1e0a91ff: startup date [Sat Dec 22 14:13:44 CST 2012]; root of context hierarchy
复制代码
6 ~ S" v9 _% C) m* h7 w3 m: Z
2 P1 ~0 d( d& N8 v2 j4 R6 k& V9 K 这里我要特别说明一下, 当使用了Spring Data Mongo,如上面的findOne(query, Person.class)它就会把查询的结果集转换成Person类的对象。Spring Data Mongo的很多API中都这样,让传入了一个Bean的class对象。因为distinct的测试是输出list<String>的,我 使用的mongo-java-driver的api。他们都很简单,唯一的是Query这个Spring提供的对象,希望读者注意,他几乎封装了所有条件 查询,sort,limit等信息。
% E. \$ \ h% j. v; i! D
3 g* l0 f8 |8 ?# ^5 j3 c/ G
4 s/ ~- ]" v6 E& S6 P |