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