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