|
版本一:
' [. m0 y* i: `: V* p1 A8 m" O2 v: t' _$ N5 Y. v$ R
1 ) . 大于,小于,大于或等于,小于或等于1 l) I# N2 \* g! e0 k7 {
3 w& E! [) p5 z. c) H: I) O6 m$gt:大于$ _9 y) f* l3 y! U9 ?% D' V
$lt:小于' S) q# b5 M9 `2 V9 @- x C+ C
$gte:大于或等于* S0 x; X' H. X/ \
$lte:小于或等于$ P$ D5 u, X( q; q; f. ~
' E% D; W1 N. y. v7 o4 i1 a. k例子: - db.collection.find({ "field" : { $gt: value } } ); // greater than : field > value
: U1 a2 m: e9 R) n+ Y - db.collection.find({ "field" : { $lt: value } } ); // less than : field < value- {( j$ }6 T& ` C# f
- db.collection.find({ "field" : { $gte: value } } ); // greater than or equal to : field >= value
2 C8 q* p/ A( j0 ?, t - db.collection.find({ "field" : { $lte: value } } ); // less than or equal to : field <= value
复制代码 / E B$ M/ i) `% V( f
如查询j大于3,小于4: - db.things.find({j : {$lt: 3}});7 v( A1 w0 x- W+ `
- db.things.find({j : {$gte: 4}});
复制代码
T( g* Q, b; ?+ V& W6 P0 \也可以合并在一条语句内: - db.collection.find({ "field" : { $gt: value1, $lt: value2 } } ); // value1 < field < value
复制代码
4 k; q( y. R2 Z5 y+ r- E; ?* @# C
8 F; A( i. ~2 } q
: O# B* l7 u. l7 L% C2) 不等于 $ne 例子: - db.things.find( { x : { $ne : 3 } } );
复制代码 8 F+ } ]. _3 F
3) in 和 not in ($in $nin)
' \* m( H/ R: X7 i/ R9 N6 i% R+ }$ W# |# V* W0 \$ C# ? r; B
语法: - db.collection.find( { "field" : { $in : array } } );
复制代码 w6 L5 V: k' b. b$ Y# f! M
例子: - db.things.find({j:{$in: [2,4,6]}});
4 v/ S$ @% r/ ]) V$ r - db.things.find({j:{$nin: [2,4,6]}});
复制代码
5 z! v$ R. M- e$ p! x6 J2 ]
) t9 E6 v5 ~* l; y- a; [( |/ s4) 取模运算$mod) W4 Q; Q0 }3 l/ S
: d$ x" _+ E% R# ^( E3 x) L4 ]# S
如下面的运算:
- db.things.find( "this.a % 10 == 1")
复制代码 1 T$ a$ i& y8 |4 Q
可用$mod代替: - db.things.find( { a : { $mod : [ 10 , 1 ] } } )
复制代码 # ]1 P" w4 t8 x+ N8 O
& B' }( ]9 u4 i" \1 a5) $all& q- }8 P4 s' D; `3 e
( w9 l; L3 [1 }- ?# P$ M6 r, K# h
$all和$in类似,但是他需要匹配条件内所有的值:
: v& D' P# q& U- A- z) K& ]6 e7 w- f. a& v+ H1 a, ? `. F, @
如有一个对象:
# L6 J2 K; B: K% O. H/ K) {3 x! Z. g # `+ P) h7 v# x) q( |& o' `$ _# a0 }
下面这个条件是可以匹配的: - db.things.find( { a: { $all: [ 2, 3 ] } } );
复制代码 ' u3 \ ^ T% ?# M/ f* X- P
但是下面这个条件就不行了: - db.things.find( { a: { $all: [ 2, 3, 4 ] } } );
复制代码 , Q) A& W7 K3 z. l2 R8 K z' P
/ ^' |+ C+ ?( s4 ^6) $size
- v* D4 f1 y: Q- k% z2 \* R& x7 \0 T3 m# d$ K/ X+ i
$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:
- C* R q* T& }* q( I( S5 r' O/ r- F2 |1 {
下面的语句就可以匹配:
- db.things.find( { a : { $size: 1 } } );
复制代码
9 S& @" E( ~+ ?) s0 M! H官网上说不能用来匹配一个范围内的元素,如果想找$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. : N. c6 W6 t# z, O$ P- y
7)$exists $exists用来判断一个元素是否存在: 如: - db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回( ?: O3 z* E. v2 o
- db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回
复制代码 ' m1 s6 F3 b3 c; W, L' Y
8) $type $type 基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。 - db.things.find( { a : { $type : 2 } } ); // matches if a is a string- h, G7 w2 t5 W% ^$ T' M
- db.things.find( { a : { $type : 16 } } ); // matches if a is an int
复制代码 : C0 C( j( i1 V W6 a. T! E+ u5 B
9)正则表达式+ L# N# z' `" Z p1 @; Y- G" t
: u& P& _. U4 u: z) n+ B9 P4 H
mongo支持正则表达式,如: - db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写
复制代码 ; G3 s4 s: `! ?' A4 v
10) 查询数据内的值
0 G2 Q" ?$ G+ Q; C0 r% z: t( z% c: F/ B, z4 |1 g
下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。 - db.things.find( { colors : "red" } );
复制代码 9 e5 h+ J# G1 z- y& G* G; |
11) $elemMatch
1 W" |8 [- m: m2 `
, l6 X0 G. B1 L9 {8 X- i如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素: - > t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } )
i: B1 T4 C+ B" E9 e - { "_id" : ObjectId("4b5783300334000000000aa9"),
; s) W" |+ _& g' ^ - "x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]
% _4 h+ B" K# q+ X; L - }
复制代码 9 L3 P+ W5 e7 l& Q
$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。注意,上面的语句和下面是不一样的。 > t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )
- g, m# |2 F( t3 c/ i7 n o0 M$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 } 6 V; s+ D+ j2 C4 l! F! c3 p
9 m j% \" O" _6 E2 Y" \12) 查询嵌入对象的值 - db.postings.find( { "author.name" : "joe" } );
复制代码
/ y, D" y k& @举个例子: - > db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
复制代码
8 E- p) V( }6 K* C/ _$ f8 r如果我们要查询 authors name 是Jane的, 我们可以这样: - > db.blog.findOne({"author.name" : "Jane"})
复制代码 2 Z& ~ |. a7 s$ v
如果不用点,那就需要用下面这句才能匹配: - db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
复制代码 & c" Z+ m* I9 x" D- S/ H
下面这句: - db.blog.findOne({"author" : {"name" : "Jane"}})
复制代码
+ k* d C# p# K# L/ |6 E4 }是不能匹配的,因为mongodb对于子对象,他是精确匹配。
! x4 z+ v" v8 Y! x$ J& K5 Q13) 元操作符 $not 取反 如: - db.customers.find( { name : { $not : /acme.*corp/i } } );2 b+ _6 P; l6 ?" J
- db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
复制代码
. B0 w/ `4 H" {; eshell 环境下的操作: 1. 超级用户相关: 1. #进入数据库admin 9 g6 K; e: @8 d7 } ~# x7 y
# s0 E; C' d! U. p% L- j3 \' b 2. #增加或修改用户密码 3. #查看用户列表 4. #用户认证 5. #删除用户 6. #查看所有用户 7. #查看所有数据库 5 O2 a9 ^) [+ |+ q/ x8 W4 u
8. #查看所有的collection 9. #查看各collection的状态 - db.printCollectionStats()
复制代码 # P: A' ~5 W6 g; w9 E1 O
10. #查看主从复制状态 - db.printReplicationInfo()
复制代码
8 k: n4 X. u( t/ n: { 11. #修复数据库 12. #设置记录profiling,0=off 1=slow 2=all 13. #查看profiling 14. #拷贝数据库 - db.copyDatabase('mail_addr','mail_addr_tmp')
复制代码 " \! i y3 b, M4 G+ Y+ h. J, w4 A0 t
15. #删除collection 16. #删除当前的数据库 & D' e# z' u* C! Z3 U( A1 l; R
2. 增删改 1. #存储嵌套的对象 - db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
复制代码 2 o& l( z8 |+ g
2. #存储数组对象 - db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
复制代码 1 |, j6 ^& {: l
3. #根据query条件修改,如果不存在则插入,允许修改多条记录 - db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)
复制代码 " k& j. U; @( L7 Y. {! L" f4 T
4. #删除yy=5的记录 5. #删除所有的记录 . I V3 @+ ]$ ]9 F- B- Q9 V4 Z3 H
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()
1 I9 r* Q) i$ n4 C6. 高级查询 条件操作符
1 x0 b: ]( m9 S. B- $gt : > / q3 t5 y% [3 Q, O/ }
- $lt : < 4 c# x9 r' ~: j3 c# f
- $gte: >=
, Z( V* ^- C- l/ Q" f: t- p7 K - $lte: <=
% L7 G2 O1 C! }- o - $ne : !=、<>
( H1 I. t/ k/ U: G+ I( P - $in : in
9 H! G0 |2 h: q% e - $nin: not in ! m @) J4 @7 P( m7 u( b: k0 F
- $all: all
; e# Y7 V! U8 j2 I Y+ S - $not: 反匹配(1.3.3及以上版本)
复制代码
- o7 D0 i0 a5 j4 N/ F0 O( q
/ P S! B* x+ L C y& i% J查询 name <> "bruce" and age >= 18 的数据
! Y: x2 k+ o" `: i% U! q; r. N- db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});
复制代码
r, S* c' z \% s9 W# G6 E/ U/ z7 u! u, i ]+ N5 }
查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据 . s& g5 ? J. t3 {9 y
- db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});
复制代码
8 @4 K( V( a/ t6 b% l5 M
* G# ^& V4 `2 m2 V% j查询 age in (20,22,24,26) 的数据
8 Y1 ~# R: u8 ^% q- Q0 f. C% G, A- db.users.find({age: {$in: [20,22,24,26]}});
复制代码 5 E+ `3 |$ L/ G4 u3 i* r1 \+ e
0 a5 u% a8 C2 E8 s* a+ ]5 ]4 S2 E
查询 age取模10等于0 的数据 D7 [% [9 x& |3 C
- db.users.find('this.age % 10 == 0');
复制代码 * M. n# M+ |& {+ v( X- x
或者
- u3 ]* b! ]& y. s7 X- db.users.find({age : {$mod : [10, 0]}});
复制代码 ; _) D$ @8 d) j/ `5 E
6 v7 \* k. m6 W& R3 @; Z
匹配所有 / C+ j* r8 _2 `$ y3 y% b6 X
- db.users.find({favorite_number : {$all : [6, 8]}});
复制代码 # Y2 \1 F8 m& P, Y$ x2 d9 z" B
可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] }
7 h3 r, i# a# f2 c可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }
8 c0 ~; V- b0 Z1 c+ t7 E3 p) F* t% u
0 R j6 Z f' ^5 V/ V查询不匹配name=B*带头的记录
0 d' _4 p; a& Z8 S- db.users.find({name: {$not: /^B.*/}});
复制代码
1 y3 f5 P8 ]2 a3 u& I% k4 A2 t# c2 a* t查询 age取模10不等于0 的数据 * E( \6 O3 M+ M) U" s
- db.users.find({age : {$not: {$mod : [10, 0]}}});
复制代码
, A0 t7 l# }( b3 D6 I8 a* O- ^( o4 j4 u6 _( p
#返回部分字段
) e: X+ \, j9 d5 \. l选择返回age和_id字段(_id字段总是会被返回)
( w, W3 {" G% A9 `0 V: y- db.users.find({}, {age:1});
0 r- y! D% O3 D - db.users.find({}, {age:3}); # [" I: `- t. O/ Y q
- db.users.find({}, {age:true});
8 X. |- S+ ~5 E2 U/ t - db.users.find({ name : "bruce" }, {age:1});
复制代码
3 b2 a$ X3 P2 R: z1 B0为false, 非0为true
! o& N5 s8 U- n5 `6 ^( @, p, r8 @6 `* ~% @/ O! _$ z- x
选择返回age、address和_id字段
% O. ]& p3 {2 k* z( i- db.users.find({ name : "bruce" }, {age:1, address:1});
复制代码 ( z9 D# p9 l4 u$ T5 |) e
# O' B1 x/ T+ W @( z% p& S排除返回age、address和_id字段 1 T6 J! _# l! \# j5 S; s) y
- db.users.find({}, {age:0, address:false});
1 i w2 V" l9 ^3 @# _& J' _ - db.users.find({ name : "bruce" }, {age:0, address:false});
复制代码
6 G& Q8 h; t$ ~ A% c
m9 C1 m, _% Z7 C6 b: @: O数组元素个数判断
9 @8 i3 O& E5 |% d) |/ g对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录
; L0 S$ r$ V( H2 |9 d! B匹配db.users.find({favorite_number: {$size: 3}});
. g( b& v( p; {. H+ ?, @不匹配db.users.find({favorite_number: {$size: 2}});
5 \# Z5 i- a, r; m- P7 _& a
" _# T7 Y+ W& {$exists判断字段是否存在
8 J" X. ^' P2 `查询所有存在name字段的记录
) j& Q3 N2 S( A* C- db.users.find({name: {$exists: true}});
复制代码 # q4 ^, Q- Y, J
查询所有不存在phone字段的记录 , V6 R$ C/ Y0 v+ j. ^6 ^. M
- db.users.find({phone: {$exists: false}});
复制代码 / I3 ^" _9 d& t' R1 X) l P: R% y5 \
4 P! J1 a( ^3 t$type判断字段类型 , g. d( q( l$ u7 l5 T+ c
查询所有name字段是字符类型的
. Y: U9 M; }% B3 P9 ?- ^* x- db.users.find({name: {$type: 2}});
) i+ c: M& [: n
复制代码
. H6 ~0 [4 i6 ]- v) r查询所有age字段是整型的 j$ u1 F; `+ s6 Z+ T V
- db.users.find({age: {$type: 16}});
; M' v' r& d2 P: b
复制代码
3 ^- R0 W* j1 E/ R2 ]对于字符字段,可以使用正则表达式
5 L' U! f) A% d4 B0 b查询以字母b或者B带头的所有记录
# m" n3 p8 i7 x0 W% y: z7 G- db.users.find({name: /^b.*/i}); - X2 M! t7 o. h, D4 ^6 H* A
复制代码 - Z/ s/ ] F: K2 k
$elemMatch(1.3.1及以上版本) 5 ]' f( t$ N, E. V# ~. B; c
为数组的字段中匹配其中某个元素
t+ p8 k9 }4 N6 h' S7 g( c
8 {, m7 | r0 f8 p6 xJavascript查询和$where查询 # H/ P5 z, h k" d
查询 age > 18 的记录,以下查询都一样
' }& _ g' n- V# j( @5 {- db.users.find({age: {$gt: 18}});
& w9 M! _" R/ b2 f - db.users.find({$where: "this.age > 18"}); 9 w4 ` }/ N1 }" D
- db.users.find("this.age > 18");
$ `" E- j& m# F4 u - f = function() {return this.age > 18} db.users.find(f);
复制代码 7 |- w& t( K& n
$ q2 B. } D h: q- `排序sort()
/ {, e0 e8 z" m以年龄升序asc 5 G/ {0 _" E1 {) g- U
- db.users.find().sort({age: 1});
; n* }; E, r( w
复制代码 ! b! ~. q. z. A* \! p6 c
以年龄降序desc
9 O v0 H5 L8 i9 L/ K- db.users.find().sort({age: -1});
0 d! ]+ y! t- ^/ r2 f' j
复制代码
; |7 K7 A4 h# f8 v限制返回记录数量limit()
, a8 l% T5 n( H5 w0 L* Z返回5条记录
1 l7 r' @) ^# \8 J! a) Y* z4 V- db.users.find().limit(5);
$ {% H5 z6 Z# J- N; T
复制代码 ! C4 e7 K, z$ x3 ^; @/ G
返回3条记录并打印信息
' K$ C9 w! S' ?+ r+ s) j% k- db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)});
1 t( G) X6 f6 a- b
复制代码
; f4 y" ^+ U r- `( V结果
$ l3 B' `6 Y$ A l. i. U; r- my age is 18 & h6 T$ s, D, j; L4 N) @- [7 S
- my age is 19 ; i, c+ V- A2 w2 I% ]
- my age is 20
复制代码
" q) V4 S- z" A) a
6 ?( J! c% O# A限制返回记录的开始点skip() ~1 B6 O M. O8 c
从第3条记录开始,返回5条记录(limit 3, 5)
& x5 J. D0 B( `; n1 w, u2 y- db.users.find().skip(3).limit(5); * D. W7 b6 C1 {
复制代码
; z, E) \# {. j, v0 `6 Y4 f4 W查询记录条数count() 9 e( f t+ U; C8 |3 I$ S
db.users.find().count();
; |/ ]2 U/ k" ?8 ~5 }$ P: {db.users.find({age:18}).count(); $ H" c8 \- d. w* _
以下返回的不是5,而是user表中所有的记录数量 2 X: H7 n8 k; k. g& z2 b$ y
db.users.find().skip(10).limit(5).count(); 1 I I/ b4 _* @8 I, [0 G
如果要返回限制之后的记录数量,要使用count(true)或者count(非0)
( T6 k) \1 e& R, u* b" V7 H; p& R- db.users.find().skip(10).limit(5).count(true);
复制代码 / x6 t% F4 G5 V. K2 r
$ a3 |% ]5 j& e' d/ \" u: R
分组group() % a5 U8 ?2 e. V/ U, X! t3 s5 \
假设test表只有以下一条数据 6 E$ P+ m7 P7 k
- { domain: "www.mongodb.org"
1 }( K" Y" G, t. T1 u4 L - , invoked_at: {d:"2009-11-03", t:"17:14:05"} $ E( N7 [& a* T8 D& h
- , response_time: 0.05
4 S# A( _0 k; U' f" e7 f: C - , http_action: "GET /display/DOCS/Aggregation"
% W7 P+ k: q9 G# k* J- ?9 c - }
复制代码
3 c/ K- W. |' W. u; k使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count; . L1 b7 V& Y9 u: L0 f
- db.test.group(
- M* G n; x+ L% y2 F1 t- o - { cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
6 @/ h5 A* Y* G K - , key: {http_action: true} 8 _$ G( s4 q& P2 j# e, I, d
- , initial: {count: 0, total_time:0}
% t! O7 p0 i9 l4 j - , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
. @; y( ]! v4 J$ [( v - , finalize: function(out){ out.avg_time = out.total_time / out.count } # k% Z$ o& ]( S' ]( r
- } );
" T! q. y% |4 |. i$ P6 e+ g& P1 k
; o$ \( P1 L$ I& @3 d- [ $ i4 U* c4 t( z) r( t. D
- { # r. |' \$ ]7 R$ p3 R( W; r
- "http_action" : "GET /display/DOCS/Aggregation", ; L* E; H7 m1 X* X9 c0 o9 o- D
- "count" : 1, " t Y- m" f1 p0 z3 S E$ z0 L' ?" D
- "total_time" : 0.05, , y7 T T1 R3 C
- "avg_time" : 0.05
6 @2 J R% e+ y4 {; C: W( ?! t - } 9 E& T8 v. X$ Q& A3 O) W) R1 q7 F
- ]
复制代码 & d" m1 b0 V* h
( P5 }3 w) k, Y5 Y- _
% \* W9 W7 f1 A) gMongoDB 高级聚合查询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 和Min% Z3 o& a8 D* u6 l. {% v
我和同事在测试Mongo时,索引还写了不到一半,他想查询某个字段的最大值,结果找了半天文档也没找到关于max的函数。我也很纳闷这是常规函数啊怎么不提供? 后来经过翻阅资料确定Mongo确实不提供直接的max和min函数。但是可以通过间接的方式[sort 和 limit]实现这个。 要查询最大值我们只需要把结果集按照降序排列,取第一个值就是了。 如我的例子,我想取得集合中年龄最大的人。 - db.person.find({}).sort({"age" : -1}).limit(1)
复制代码 7 s& _% n2 C( i1 _
3 x* L5 n N( b4 ^9 |5 @
; N/ C1 l* q5 @; f, R' S) O相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。 当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。 MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits]. 如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。 如上面的表结构,我想统计所有的喜欢的水果。 - db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.
复制代码
% A7 E+ M3 ~7 H; q6 r) j6 K3 X* L$ s Y! I
他成功执行了。输出如: - [ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr" ]
复制代码
: v2 B' L1 p3 x8 k5 I0 d3 l3 S9 P) \& B. Q6 _) b
我想统计集合中共有多少个人[按名字吧] - db.person.distinct("manName")
复制代码
$ Q- Z8 j9 r5 E( I
% `: E6 A5 I( o4 j4 M# F 我想统计指定个数的人的共同关注的朋友。 - db.person.distinct("myFriends", {"manName" : {"$in" : ["ZhenQin", "YangYan"]}})
复制代码
. R3 b C5 N! U0 I
: j ]' z2 _. t) M! D- F Q4 m: i5 [ 输出如: -
: R. w, d, N; y/ g, Z - [ "234567", "345678", "456789", "987654", "ni", "wo" ]
复制代码 6 |. G7 }& j( H1 T! K, h1 l5 z6 L
& Z: J Y9 B1 ?2 g) [: X. S5 ?
4 w$ R7 ]% z0 i% V, ]! M那么我使用Java呢? 我只是在演示Mongo的命令,用Spring Data Mongo是怎么操作的? Spring Schema: - <beans xmlns="http://www.springframework.org/schema/beans"
/ w) ?9 S6 R$ q! y - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
/ \* D& B0 @+ h: ]& P5 b - xmlns:context="http://www.springframework.org/schema/context"' N0 w$ U( C" d _
- xmlns:mongo="http://www.springframework.org/schema/data/mongo"
5 y( {9 T; U9 A$ v - xsi:schemaLocation="http://www.springframework.org/schema/beans
: k9 _4 v, F: l# W - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
9 `/ h7 W6 ]) Z7 ?$ V/ V3 ^1 e* Y - http://www.springframework.org/schema/context; T$ i% h, b! R/ G
- http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ u: s5 ~1 C/ m& v - http://www.springframework.org/schema/data/mongo
$ W9 V* W5 h/ z; j( Z2 S8 F' c - http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">/ J3 |" S, {1 ~, Z, e! x/ g9 X
- , b8 r" m+ W7 c1 R9 X
- <context:property-placeholder location="classpath:mongo.properties" />1 d: ] t: z$ ?
-
' N4 \4 f: n# ^7 O: ?8 C$ K - <!-- Default bean name is 'mongo' -->' U$ D/ W3 s1 l* _& ]" J
- <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" />- x$ _. L' ]" t& H6 F2 d
-
4 K6 ^( ]$ l% J# e - <mongo:db-factory id="mongoDbFactory", E& J2 V- F: e/ w1 C: x7 k
- mongo-ref="mongo"
5 o- A+ A. `+ p - dbname="mongotest" />4 T+ s0 e9 m; `0 G) y
-
8 \: J9 w( o# s: ` - <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
$ k3 G7 y0 B3 ?* M4 r3 W4 T - <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>! G/ I8 i$ h) z% e& A1 L: u
- </bean> b+ J6 P, v2 \* A. V) f
- </beans>
复制代码 3 ^" D* r5 S+ | _
; w* O- ~3 K' h! e: r( k
max和min的测试: - @Test
: k5 w& k1 ]4 N; `; T% \& g8 L d - public void testMaxAndMinAge() throws Exception {
. y, G1 C, v4 S) h9 C+ w* H4 Z9 M$ X - Query q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.ASC, "age"))).limit(1);
4 c/ p) M: ^$ P7 U - Person result = mongoTemplate.findOne(q, Person.class);" p) |/ |" S9 [/ c
- log.info(result);
y. I$ w8 t4 r6 ?' A - + ?' p( ^5 C, \2 e) t1 T8 }
- q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.DESC, "age"))).limit(1);2 z! C: R) J/ |6 P
- result = mongoTemplate.findOne(q, Person.class);
" l$ M+ b5 x8 L/ v# i - log.info(result);1 l8 o- @8 b K! r; x* k, n) w0 c
- }
复制代码 3 t; E6 n5 k0 X3 O' A! ^9 f; n! o
5 W3 X) i$ T4 O- ^4 E, H( o$ V
distinct的测试: - @Test
5 _* A) `1 Q; X - public void testDistinct() throws Exception {
# r7 s4 D/ j0 @2 B: w, @; E - List result = mongoTemplate.getCollection("person").distinct("myFriends");
: k; X% g8 ?$ O# B3 O" r- G - for (Object o : result) {
& A7 T& G7 Y- e# J$ h - log.info(o);' i0 Z8 W( l. Y6 t* Z" ]( N; L5 W9 A0 c
- }6 y \% u: D \- E7 Z+ H
- + M6 O& [8 S' `. y( C- ?1 Q6 F9 |
- log.info("==================================================================");: `' p# h, i' e$ r) a
- Query query = Query.query(Criteria.where("manId").is("123456"));6 L5 N8 k/ g: l" U' u: y/ ?
- result = mongoTemplate.getCollection("person").distinct("myFriends", query.getQueryObject());3 P8 i2 H% i! W x
- for (Object o : result) {
4 s7 j! H1 o8 P6 l9 N - log.info(o);
+ x7 o' h: N7 L$ Z% s$ @3 K - }
; K. @$ Q4 m% q+ s) M! K -
8 s: F) {: y% c3 O/ T; S - log.info("==================================================================");" T) A) C7 j& q8 S2 @
- result = mongoTemplate.getCollection("person").distinct("fruits.fruitId");
! T8 B& a7 s! X - for (Object o : result) {( x5 R; O* P }1 v4 U
- log.info(o);+ l- G% g" v" B) j
- }
9 C4 |+ z- x: D9 E% d - }
复制代码 $ l* i% F s/ c% r1 z, l$ z3 n
5 r: n' @( N7 t2 p
输出的结果为: - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 234567
( R. I, m! q: @' {8 C6 B/ q - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 345678
; d4 N$ T) ?7 i+ S - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 4567897 V9 z, k) k, c; K
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 987654
9 R- G, C+ Y. _4 U% i/ K4 i+ v - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] ni! g3 y6 a5 J& q, x; X
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] wo
# i8 P: g! P9 r U' ~! z - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 123456
- C+ a) A6 a9 _; H3 j6 N2 V - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(75)] ==================================================================: @8 ?/ f8 r' N" [' f4 r8 B* V; D
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 234567
/ ^$ i/ O; Z$ Y: R+ R8 `) j - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 3456784 o9 }2 y' Z) u9 J- {4 q2 t
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 456789
, h0 G1 X& b5 A - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 9876545 P, ^. r* i& q2 s
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(82)] ==================================================================. k1 k2 ?. m0 i# w
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] aaa% T, ^1 D2 r" z- {, ]: T6 ^7 _* f
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] bbb5 m3 x% T( @. C3 x1 ?, T- I4 m& V
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] ccc
( W/ P) ]6 K+ N9 x3 E0 Q& | - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] www) R$ s8 G% r) r. z- p& {$ H
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] xxx
: W4 s% N3 b' p$ P( D3 k* m$ x! _ - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] yyy
% W" L+ C% O: ~+ F' l6 f. l - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] zzz1 a4 ~8 P) s* z5 y% f4 d" d. I4 w3 R
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] rrr. B+ \3 c/ I! N3 {0 l
- 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
复制代码
! b9 E; W( z. e' B+ |/ p5 E* p$ j' q& q
这里我要特别说明一下, 当使用了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等信息。 1 v! W; _3 `0 c
o" q7 ~0 ]* Q% q
) R# e$ u7 ]5 A- u' q6 Z% @; N
|