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