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