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