版本一:- A% x; z! U E* U
6 c3 L2 Q1 }& e4 U/ N1 ) . 大于,小于,大于或等于,小于或等于3 `4 d0 U9 l) x9 g3 U4 O7 B
$ T) R+ X! a8 F# [
$gt:大于
! z7 Z! O5 E- d* a- \5 t, `0 m$lt:小于
) P, P/ s) D& d6 [$gte:大于或等于
3 m6 z/ N1 {9 Q- L$lte:小于或等于9 ]( \6 O6 h' M
$ A) \5 b8 _" Q& W' O; n* [' K' U例子: - db.collection.find({ "field" : { $gt: value } } ); // greater than : field > value* b3 Z N5 n7 e% E( Z ]# w
- db.collection.find({ "field" : { $lt: value } } ); // less than : field < value
* c- }1 ^' T/ {0 x - db.collection.find({ "field" : { $gte: value } } ); // greater than or equal to : field >= value
8 w' X0 [1 C4 ], ` m - db.collection.find({ "field" : { $lte: value } } ); // less than or equal to : field <= value
复制代码 2 ^; `& Q- b \" j1 p1 a" `' U
如查询j大于3,小于4: - db.things.find({j : {$lt: 3}});4 H7 Q5 ?" s3 Q% L1 |
- db.things.find({j : {$gte: 4}});
复制代码
, Q& e% W) I2 J' L也可以合并在一条语句内: - db.collection.find({ "field" : { $gt: value1, $lt: value2 } } ); // value1 < field < value
复制代码 ) k. G+ S. g @! E( L. j
# H+ C/ T8 D' `# g+ f4 u% g! v6 }& P3 `1 c. L) t& O7 ^
2) 不等于 $ne 例子: - db.things.find( { x : { $ne : 3 } } );
复制代码
/ s- G6 z% w, O3) in 和 not in ($in $nin)
% Z0 b& O e5 ]& W# E( m6 L: m" g
语法: - db.collection.find( { "field" : { $in : array } } );
复制代码
( ?- K1 X' z- j* U例子: - db.things.find({j:{$in: [2,4,6]}});
5 D) q7 @7 |+ ?# R) q. B, c - db.things.find({j:{$nin: [2,4,6]}});
复制代码
# b% l; {' E: C& E8 O- m
- M2 U. h& S; x" Q8 D& [2 H4) 取模运算$mod
1 c' } M: u" j, ^' ~6 }8 F& @6 Q, q; X b Z1 k* M0 C1 w
如下面的运算:
- db.things.find( "this.a % 10 == 1")
复制代码 $ h, s3 O( Q" [3 i: x
可用$mod代替: - db.things.find( { a : { $mod : [ 10 , 1 ] } } )
复制代码 - K6 ~) x, u, N( D, A) ?: C
: F; B/ u. M. ]% a. r0 T: X1 C
5) $all
. G$ @* K5 B @% f g0 f/ C( f& [5 f7 N) J
$all和$in类似,但是他需要匹配条件内所有的值:# i( I0 _8 @1 W3 n6 j; b
. n4 j! [6 P9 K' v如有一个对象:
* E9 J' {# C5 q) F) Q A/ g 2 W4 U# w8 p. S, T
下面这个条件是可以匹配的: - db.things.find( { a: { $all: [ 2, 3 ] } } );
复制代码 ' x, K& ]" q( f. y
但是下面这个条件就不行了: - db.things.find( { a: { $all: [ 2, 3, 4 ] } } );
复制代码 * w/ F! E9 d" {2 X8 Q
; Z w& j4 C& r9 F
6) $size8 k- k6 u- e6 A, x
, O |- Q; b! x8 Q+ J
$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:
; R3 J% z; M! M) [: k; @/ ^7 g
# P* E. H5 ^) @5 C w下面的语句就可以匹配: - db.things.find( { a : { $size: 1 } } );
复制代码 9 p) W/ W$ K- Y& Y
官网上说不能用来匹配一个范围内的元素,如果想找$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. $ V% Y% ]+ N8 M+ F3 H5 G& k
7)$exists $exists用来判断一个元素是否存在: 如: - db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回
) I/ D3 u8 g. j4 H5 i! h7 B& t - db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回
复制代码
4 o Q; U4 O2 r/ G+ N& s8) $type $type 基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。 - db.things.find( { a : { $type : 2 } } ); // matches if a is a string9 X& N+ Z+ Y9 C3 R
- db.things.find( { a : { $type : 16 } } ); // matches if a is an int
复制代码 ) Z5 \/ k f4 Y5 L: [
9)正则表达式 M6 K; K$ b; t/ ~
' y) T- ]( s: H4 ^mongo支持正则表达式,如: - db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写
复制代码
3 q- d" \" {2 O* H/ n- F% `7 c10) 查询数据内的值
! t0 x S5 O* ]8 c, i
0 l; F- d/ [+ s6 t$ V# T% k, c下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。 - db.things.find( { colors : "red" } );
复制代码
8 r# s4 G& J0 R9 r3 P11) $elemMatch6 W3 Q; q8 h# o9 T' [0 ?' r/ I% c) r
% _, v5 I* N* e$ }, E! F6 k. e如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素: - > t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } ) 2 X4 G& s, C7 P, M3 p4 D* O! E
- { "_id" : ObjectId("4b5783300334000000000aa9"), 5 w9 K, M1 K5 L. X0 b+ a9 h
- "x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]0 ]1 [% A& F, x
- }
复制代码
1 j$ n0 _$ V! _, P$ V% w$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。注意,上面的语句和下面是不一样的。 > t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )7 u1 ^) m$ ~; a0 h
$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 } ( R4 u) ]3 o) }2 q( D0 _5 D/ Q3 h
" b9 d' J' D) ]
12) 查询嵌入对象的值 - db.postings.find( { "author.name" : "joe" } );
复制代码 / e2 Y. ^1 e9 E D* q
举个例子: - > db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
复制代码 ' \6 C: V n# }1 O
如果我们要查询 authors name 是Jane的, 我们可以这样: - > db.blog.findOne({"author.name" : "Jane"})
复制代码 9 j% Q3 Z/ x7 S; E/ }
如果不用点,那就需要用下面这句才能匹配: - db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
复制代码 1 e3 i9 }& D9 u# e6 J; b' v
下面这句: - db.blog.findOne({"author" : {"name" : "Jane"}})
复制代码
* l) D) ], B5 C是不能匹配的,因为mongodb对于子对象,他是精确匹配。
5 x, @$ Z+ n4 T) o13) 元操作符 $not 取反 如: - db.customers.find( { name : { $not : /acme.*corp/i } } );
( b, ~3 t# I+ Q: F - db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
复制代码 1 V; N$ d) N: V1 T' y8 s2 ?
shell 环境下的操作: 1. 超级用户相关: 1. #进入数据库admin # f2 R- }8 h. u- d1 ~% g
( X! }) \+ m4 }8 I
2. #增加或修改用户密码 3. #查看用户列表 4. #用户认证 5. #删除用户
9 D! C9 W; ]' U3 i- \, P9 u 6. #查看所有用户 ' P) z4 f/ c9 }$ N W7 u" W
7. #查看所有数据库 8. #查看所有的collection 8 v$ }/ ~* l% u) u& W+ |" @' o
9. #查看各collection的状态 - db.printCollectionStats()
复制代码 + l6 _( N5 _' B* N
10. #查看主从复制状态 - db.printReplicationInfo()
复制代码
4 _; a9 Z& I3 v5 S 11. #修复数据库 * K! o3 ^6 X K5 z- }+ u+ i
12. #设置记录profiling,0=off 1=slow 2=all + I' e$ `' d3 o2 X# _# j+ A! R
13. #查看profiling 14. #拷贝数据库 - db.copyDatabase('mail_addr','mail_addr_tmp')
复制代码
# v: z- T0 R3 {2 }% L5 u9 x 15. #删除collection
: w, ]! W1 F) X; d8 O* M u 16. #删除当前的数据库
3 b2 E t" U. G. @ ^. q0 o$ G 2. 增删改 1. #存储嵌套的对象 - db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
复制代码
( b: ~6 ^' s7 N 2. #存储数组对象 - db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
复制代码 " N" O, [! Z0 c! |1 b
3. #根据query条件修改,如果不存在则插入,允许修改多条记录 - db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)
复制代码
7 t: \# V) c* Q" s9 g 4. #删除yy=5的记录 5. #删除所有的记录 @/ B# i3 E& _; G4 [% B! R! K- d8 n
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() ! Y$ g0 v; L+ D& P1 Z* ~* X
6. 高级查询 条件操作符 ; D h" Z6 {$ K* ?0 |. t
- $gt : > 5 Z7 v2 f7 j4 U- T+ q. T. x7 U) ~
- $lt : <
1 C" M' W( a+ W) w2 @1 U - $gte: >=
! A N- ^. |* A2 u) o V$ i3 ^* l - $lte: <=
H, P, Z" ? O' [ - $ne : !=、<> 3 { Q' `" @! e1 X# C
- $in : in
: U ^9 a p. Y3 Y$ { - $nin: not in 4 @8 E; E( y$ |- w3 E$ f( y/ ^
- $all: all 5 _/ h% [; F% c7 i6 H
- $not: 反匹配(1.3.3及以上版本)
复制代码
& C* e( l" }) D( J1 B! p) B/ a
' L9 y( I; f$ Z* f: C3 f查询 name <> "bruce" and age >= 18 的数据
* Y6 \+ ~6 C0 G% u- db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});
复制代码
5 z9 J& ?6 F+ b! ^& N0 W
1 \, `0 M4 `# o2 C查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据 # F" o$ k1 F8 q! V, u; F
- db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});
复制代码 % C$ y( w0 D: w6 X# V
# t9 S g, m, O% Z: D
查询 age in (20,22,24,26) 的数据 ( p7 v1 M, b5 l/ m2 Z) v- E' R
- db.users.find({age: {$in: [20,22,24,26]}});
复制代码
* \/ ?9 b: j" A9 R
9 z7 O, F) h0 b查询 age取模10等于0 的数据
( Y, h% f! L4 N& N. `- s0 f- db.users.find('this.age % 10 == 0');
复制代码 9 V8 m: l W/ l( k& k
或者
( x- U# u- Z' X- db.users.find({age : {$mod : [10, 0]}});
复制代码 ; B1 y A! R) q: Z9 F
( D3 u `- z1 r' O
匹配所有
/ b7 M' x0 b! B0 k- db.users.find({favorite_number : {$all : [6, 8]}});
复制代码 ) x% F, E, M! j! t1 V; U, H) G
可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] } ( E* B1 O$ i# c8 J
可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] } 4 e" v, U! N/ F. r6 C0 t& k
/ h# d* V3 S6 Y+ V# Y6 y# D Z
查询不匹配name=B*带头的记录 $ m+ s" j" v' A3 {: l
- db.users.find({name: {$not: /^B.*/}});
复制代码
{; k) t- s+ [9 X5 v Q+ o查询 age取模10不等于0 的数据 ; y. _- H4 d# b' e
- db.users.find({age : {$not: {$mod : [10, 0]}}});
复制代码
; s* X& K5 b% ]) S: b+ w, N
/ |# F9 a6 s: t: v" H6 o5 B#返回部分字段
) V) X. h* x5 V8 v) R% D) ]. n1 p% Q& I选择返回age和_id字段(_id字段总是会被返回) : h" [, a m) e) q+ u
- db.users.find({}, {age:1});
7 A2 @+ ]( x4 T- A0 Q2 | - db.users.find({}, {age:3});
- {; G* g6 g+ O - db.users.find({}, {age:true}); " c, Y* ?$ s$ R
- db.users.find({ name : "bruce" }, {age:1});
复制代码 , Q( b5 W2 c W& F% I
0为false, 非0为true
, f- L; @" e" B2 n: W M9 k- P9 k: z& m6 [* l7 a
选择返回age、address和_id字段
9 M% ~/ U( H0 ^7 E7 G- db.users.find({ name : "bruce" }, {age:1, address:1});
复制代码
p5 c3 F+ O2 h2 C% Q. k9 R" J# E+ Q$ v& k! k5 ]1 W# [
排除返回age、address和_id字段
2 t+ n& f i! u- c6 W- db.users.find({}, {age:0, address:false});
5 v8 q. b4 o5 x B2 U, \. g - db.users.find({ name : "bruce" }, {age:0, address:false});
复制代码 * Y( Z5 e V) @
# t; A- \4 f3 n; w
数组元素个数判断
: l3 p! N" ~+ \" b( I( N对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录
2 [$ I% R, Q* }6 e, t匹配db.users.find({favorite_number: {$size: 3}}); : D, A9 W; M9 Z v, D
不匹配db.users.find({favorite_number: {$size: 2}}); 3 P/ i* k- X. b, m
' b( u( S$ E, R6 N" f
$exists判断字段是否存在 M. |4 v) r3 C1 ?( D$ [! L' D
查询所有存在name字段的记录 - }" E- ]- L/ `" x4 T6 S
- db.users.find({name: {$exists: true}});
复制代码 9 i* x$ N% U, d8 U4 b6 D4 \
查询所有不存在phone字段的记录 * s4 _2 b/ n0 p @! W/ E8 ~
- db.users.find({phone: {$exists: false}});
复制代码
4 i3 h, b3 W2 }5 }! K6 p% R, f5 }; h% t a) b
$type判断字段类型
# F- R0 B, [ Q9 R* g4 V查询所有name字段是字符类型的
- }, i4 l% P; g5 N- db.users.find({name: {$type: 2}}); : P9 L8 G: A8 I% Q, S
复制代码
' J. ]7 i% i, { ^: W' ^4 S# v, ^查询所有age字段是整型的
2 k/ q/ Z3 v3 |0 a2 |- db.users.find({age: {$type: 16}});
( m0 O# G% \- A% ?9 d8 k% Q
复制代码 8 o: F- B0 m, C) f1 c1 f7 x0 {8 Y
对于字符字段,可以使用正则表达式 1 I$ P0 k; Y P3 N- c! K: M, b' R
查询以字母b或者B带头的所有记录
; _9 p, a3 t$ O( R4 U2 D- db.users.find({name: /^b.*/i}); & f3 r8 M. Y; @: l5 K- h( H
复制代码
4 [& A ], H d8 R$elemMatch(1.3.1及以上版本)
4 b" q+ c% s3 j9 H+ ~ j为数组的字段中匹配其中某个元素
3 ^" p/ a* S' l( b9 s8 L V6 D# K! a1 t& Q1 {( i# p
Javascript查询和$where查询 ! M, n9 X, x* g; \ X
查询 age > 18 的记录,以下查询都一样
- _0 P4 F8 E; o( P' b- db.users.find({age: {$gt: 18}});
6 V/ M- S7 J6 ~ - db.users.find({$where: "this.age > 18"}); ) m8 e* h9 r$ @! A
- db.users.find("this.age > 18");
# X" d% o, b: ^ - f = function() {return this.age > 18} db.users.find(f);
复制代码
_2 Q* c# W' l A1 f/ I
4 b) C6 E, b i k$ |. i排序sort()
; \8 T% H& {& r \& I" ?以年龄升序asc 1 U. ]; T* j( l) \9 s5 q" q) n# P
- db.users.find().sort({age: 1});
/ R- f4 p) M3 N: X$ n
复制代码 * x- X; L. t: i% c- W
以年龄降序desc
7 K0 r+ L& B& F7 q/ m y- db.users.find().sort({age: -1}); 5 J7 H& u: {& L- e1 z+ [0 o4 f3 _
复制代码
5 y! c" ]0 [. k& v( G' j, p限制返回记录数量limit()
6 k# j. ?9 c1 [! K" k2 b- {返回5条记录
: Y: w. `+ x1 n7 |" m" S Y- db.users.find().limit(5);
; b& l6 ]0 j2 ^
复制代码 " n; ]0 f" C0 | Y; i
返回3条记录并打印信息 # m, j8 t3 t# L9 g
- db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)}); 5 a4 F& U# l2 V3 u% R
复制代码 # b5 ]3 L. Z$ r. M4 T
结果
2 T" k: Q! k# a( S: c9 J# @- my age is 18 5 D7 ~' Z0 A! X' t# \
- my age is 19 0 Q9 }( G, q. d: ^' l$ Z) }
- my age is 20
复制代码
+ {) f) Q' L6 X( z8 K# P& G7 ~$ T( L8 H* T. i0 H
限制返回记录的开始点skip() ( r. }- {, `1 z' U
从第3条记录开始,返回5条记录(limit 3, 5) - j7 i: B" o- ^# I @4 s
- db.users.find().skip(3).limit(5); & `+ j% f) F# u$ X' G$ f
复制代码 ' `9 [4 R& D9 b% d5 ^) f* z
查询记录条数count()
/ ?3 H9 r/ Q& \! _6 o* Tdb.users.find().count(); " r/ L B3 w8 M/ O7 v
db.users.find({age:18}).count();
1 v; o& W& m3 [2 ~+ p5 n/ j* A以下返回的不是5,而是user表中所有的记录数量 1 g+ R! j7 z# j, [ T9 y
db.users.find().skip(10).limit(5).count(); # G$ Y+ K% X% f
如果要返回限制之后的记录数量,要使用count(true)或者count(非0) 5 ^' ?/ X0 D+ T1 z5 Y7 p2 o5 `2 u
- db.users.find().skip(10).limit(5).count(true);
复制代码
6 L$ Y' z) G0 J4 O
2 p8 D9 [4 q& W分组group()
# }8 X& N0 D1 }假设test表只有以下一条数据 ( \: X& b, ^/ h
- { domain: "www.mongodb.org"
! e# s( p8 K4 e0 Z - , invoked_at: {d:"2009-11-03", t:"17:14:05"}
+ m- a1 L) q8 N% m; p - , response_time: 0.05 - f/ |/ c S, [ ~' p( b3 M. n
- , http_action: "GET /display/DOCS/Aggregation" ) [6 Y; O7 J$ W2 }
- }
复制代码
, H' {: s6 J- w! H9 V使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count; # V3 M4 |% [3 F) r1 ?; Z5 `
- db.test.group(
8 a1 ]3 u0 v0 R7 Q7 z. e: D! ] - { cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
! ]* k4 K" m3 Z9 I# e& ]. S( g8 ]) v% r - , key: {http_action: true}
# _3 o" O2 O$ _1 d* ~ - , initial: {count: 0, total_time:0}
/ Z7 Y% ]3 \) g" S$ u# ^1 D0 _ - , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
7 N; K; N: o1 s! I( j4 [) u - , finalize: function(out){ out.avg_time = out.total_time / out.count } * @% W6 G2 ^7 |) `- M" D
- } ); ! F( q+ Z# p. ?3 N8 y1 P( s
- ! L& |& W. S0 [ G) }8 A
- [ ) i0 L3 ~7 h+ L' P- Q
- { 2 X6 L; w Y2 W; c5 C
- "http_action" : "GET /display/DOCS/Aggregation",
; l6 j! N1 e; t& @- G* V% ?9 ^; H - "count" : 1,
+ |0 t7 F) |( m& v0 a: ]' v - "total_time" : 0.05,
2 O ]% O3 d" D- r" k - "avg_time" : 0.05
5 H. \! _: ]! T* _4 b& H, m$ }5 M - }
$ W; J$ _3 y f! d$ j- r - ]
复制代码
5 s# d9 b) J9 Y3 m4 j6 y2 j
+ i `4 A. \- K; i& F9 ^
7 i! f. |% a) N# v3 H' RMongoDB 高级聚合查询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吧。 我和同事在测试Mongo时,索引还写了不到一半,他想查询某个字段的最大值,结果找了半天文档也没找到关于max的函数。我也很纳闷这是常规函数啊怎么不提供? 后来经过翻阅资料确定Mongo确实不提供直接的max和min函数。但是可以通过间接的方式[sort 和 limit]实现这个。 要查询最大值我们只需要把结果集按照降序排列,取第一个值就是了。 如我的例子,我想取得集合中年龄最大的人。 - db.person.find({}).sort({"age" : -1}).limit(1)
复制代码 - E( t$ f3 F R* J
2 E4 |" Z& K) s* o" F2 r0 C5 p" `% V# ~" \
相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。 当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。 - distinct4 D' H) R% A( ]1 F
MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits]. 如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。 如上面的表结构,我想统计所有的喜欢的水果。 - db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.
复制代码
: i( i; l+ A" \0 P4 u' g9 }6 d5 s& L7 x" g/ V
他成功执行了。输出如: - [ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr" ]
复制代码
6 N6 r9 {% c0 v4 _4 R, ?- [8 F% n# [$ n o
8 l0 [( M5 _! d( k7 W) i 我想统计集合中共有多少个人[按名字吧] - db.person.distinct("manName")
复制代码 A/ O2 B+ I; D4 r! ~+ `- X3 L
8 a9 b( v* }% c 我想统计指定个数的人的共同关注的朋友。 - db.person.distinct("myFriends", {"manName" : {"$in" : ["ZhenQin", "YangYan"]}})
复制代码
+ Q5 F$ X2 U5 O4 K0 | G
: t" S% f/ N. r: |4 f; k7 W- l 输出如: - " Z; U" u" l) l- J1 L
- [ "234567", "345678", "456789", "987654", "ni", "wo" ]
复制代码
8 d2 l1 j. j4 H
* ]+ A, G7 Q" V5 Q( @5 s$ G5 q! A: D
那么我使用Java呢? 我只是在演示Mongo的命令,用Spring Data Mongo是怎么操作的? Spring Schema: - <beans xmlns="http://www.springframework.org/schema/beans"# @' F3 l5 h& X) U% q
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance". l3 p. C. y7 }9 h4 `9 |8 ?
- xmlns:context="http://www.springframework.org/schema/context"9 F" J$ X3 A' Y/ k6 F
- xmlns:mongo="http://www.springframework.org/schema/data/mongo"
; p, n: O# {& U( ` - xsi:schemaLocation="http://www.springframework.org/schema/beans9 y* {: k2 @) C& n+ h2 P
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
* I/ }% A: [% B+ r' [ - http://www.springframework.org/schema/context0 I M2 h/ s5 o! E+ \% B/ r& K
- http://www.springframework.org/schema/context/spring-context-3.1.xsd
; |. @; U1 f/ x- k+ H - http://www.springframework.org/schema/data/mongo6 }, E: s+ [) G W/ K7 E4 h
- http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">" c1 G) C9 |$ _ d$ S
- 3 j( l$ N, L4 [" `# R
- <context:property-placeholder location="classpath:mongo.properties" />
+ G# Z% V0 ?; c& S7 j. n) Z9 X - , q' U- @: y+ g; F+ y. E5 y3 Y5 E) m
- <!-- Default bean name is 'mongo' -->
& y+ q, H! P. s; m5 R - <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" />! s, ^. y4 Q: v; G5 f: c% S. |( x
-
% j, e. m q2 { - <mongo:db-factory id="mongoDbFactory"
9 z' R: }. T6 s5 t$ ]# C$ k# O - mongo-ref="mongo") }! X# h0 y% _3 X- }6 p: P
- dbname="mongotest" />% A* P5 _% B3 V$ ~
-
4 u: x7 }5 Q& b% C% H8 P - <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
3 |, ^) P+ ^: d# B3 L- j U6 X - <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
7 h* X, @' x [5 [ - </bean>$ b9 I: X+ \" o: [7 [
- </beans>
复制代码
; m9 C; K. U) `+ J, X- x& N$ ` - m: i0 P E: U4 L, O0 z, K' [: x8 F9 u
max和min的测试: - @Test/ E* j& ]: {* X6 F' L
- public void testMaxAndMinAge() throws Exception {9 H8 n% u" _" q) O6 L5 |; v0 `
- Query q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.ASC, "age"))).limit(1);4 A8 I( t! Y9 g- s! @
- Person result = mongoTemplate.findOne(q, Person.class);" U& R, U* z- G1 M9 X' P
- log.info(result);
9 ^/ z1 N+ A3 d! }$ z+ X; A -
' H) r6 Z* |- j4 {5 _ - q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.DESC, "age"))).limit(1);1 t8 q' Z1 @8 F, G; `& E
- result = mongoTemplate.findOne(q, Person.class);
. T- [6 P6 k( t Y! }$ a - log.info(result);
6 X* E- J8 g1 n" s( T+ F6 E! T - }
复制代码 1 e# c) `. i# ]' y5 {
* M5 ]9 ?) H' `% ^* O distinct的测试: - @Test
- a$ S- T7 ?- H1 C - public void testDistinct() throws Exception {
. S: Z& d, [# {$ B9 k* k( i y - List result = mongoTemplate.getCollection("person").distinct("myFriends");
: m4 r( o* ? C3 _" f% L, r - for (Object o : result) {
( z3 I! R4 k, E1 w. P# q - log.info(o);
; O; u% s; q( H4 x# m7 K8 f1 d - }, A* O. ]# F6 C3 L1 ?1 I e D/ G
-
! b8 }7 ~3 ^. G5 Z5 n5 g, R - log.info("==================================================================");# A. _/ d! P5 ?; j" K | p! G
- Query query = Query.query(Criteria.where("manId").is("123456"));' I& b+ E" E; y
- result = mongoTemplate.getCollection("person").distinct("myFriends", query.getQueryObject());! j2 x7 B9 \( l. C" T7 @( F
- for (Object o : result) {! s$ y8 p3 N3 V: w# c
- log.info(o);
2 L1 _% L7 U g. T1 @ - }; L5 J5 y, h: A8 e( T0 {, p
- 5 h6 S/ ?7 z$ z; v& C/ }
- log.info("==================================================================");
' A( y! p' R& ]2 k7 N1 C! E2 R' C! I - result = mongoTemplate.getCollection("person").distinct("fruits.fruitId");: ?! }8 Q2 p& ]7 O2 } A
- for (Object o : result) {
2 D/ t" H: O+ _3 Q$ J+ u - log.info(o);
2 F) H2 i5 z5 y: _8 D( ~ L9 {' Y - }6 F+ z. d7 ]* Y* y( D9 R0 G" D
- }
复制代码
1 b- F! p1 x' y% L& o$ u5 m$ }( Z8 {0 T7 B9 u$ s& y* r
输出的结果为: - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 234567
6 l( b! F# L. J. j( q - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 345678& Q" }9 I# f) w( T$ s4 T
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 456789
3 I7 O! _4 @0 s" h) ~6 o - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 987654" ?; H# w$ S0 n* r
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] ni
& Q) z% n, ^* h3 N% r' h7 b: e - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] wo( @( R5 v- L9 o) { V
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 123456+ n. V. K+ B) p) X, n
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(75)] ==================================================================; h. y, U# |" k9 i
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 234567
, @# n& f3 I1 E# b$ Q- Y) K - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 345678/ q4 z% @$ a: W
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 456789& i% M! v& C! \/ b: ]2 u/ C
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 987654
& {! H3 r& j5 I. R8 \ - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(82)] ==================================================================
2 p: [, _7 P( \1 V3 f) }+ s - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] aaa& _4 W( [/ N" W% D: F
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] bbb
, u: E8 P! s6 i! Y! ]7 R) G2 ]0 U& L - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] ccc) M* I- `+ {% R
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] www7 U& t* X# ?$ c5 X; {) {
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] xxx |: Z6 D4 ~( d
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] yyy% v" |2 w2 K* K+ V& w
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] zzz2 L7 S0 _7 X5 h, [1 d
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] rrr/ x, m0 b. \ }! p( o9 T
- 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
复制代码 : Y4 C' W; F e9 d! ^
4 M7 }: W+ _1 z V( \% m2 i* D- h( F
这里我要特别说明一下, 当使用了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等信息。 2 A5 Z8 o. C+ H5 W' t6 ^
+ p$ H' y9 l$ A5 @
! b5 `8 f( x% z/ K9 r, j! I5 K8 O |