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