|
版本一:9 j) O5 M8 b! E5 o5 Y# Q1 J
# m4 _3 r0 p" U6 |4 n) ?* `2 c1 ) . 大于,小于,大于或等于,小于或等于8 ?+ n" m, v* U r& V2 j
0 ]% F8 r; |9 n) N
$gt:大于( I2 W% _. b! x$ s+ s$ y: P
$lt:小于: r2 z1 W# P2 u8 |
$gte:大于或等于1 F+ C# [( F/ Y/ o/ O
$lte:小于或等于6 w7 p+ K! b- P4 L1 E
. s) v# G) l" l6 K2 k& f9 C$ V例子: - db.collection.find({ "field" : { $gt: value } } ); // greater than : field > value
2 V' w; K+ ^3 |6 h - db.collection.find({ "field" : { $lt: value } } ); // less than : field < value
, ]$ G/ m; o/ G - db.collection.find({ "field" : { $gte: value } } ); // greater than or equal to : field >= value
- {) I% w2 L) G% M) A; b5 N - db.collection.find({ "field" : { $lte: value } } ); // less than or equal to : field <= value
复制代码
0 b; a! L3 a- Q* K如查询j大于3,小于4: - db.things.find({j : {$lt: 3}});
6 T: H! R! {( m" L& } - db.things.find({j : {$gte: 4}});
复制代码 8 B- J* J* H7 _, c. @
也可以合并在一条语句内: - db.collection.find({ "field" : { $gt: value1, $lt: value2 } } ); // value1 < field < value
复制代码
4 \# i9 Z+ A8 y- `0 a/ m, R
9 X# ]$ B6 M& N3 h7 G; W" p
& d6 R* B8 F: `* b8 N2) 不等于 $ne 例子: - db.things.find( { x : { $ne : 3 } } );
复制代码
9 ]) n, {8 `& \0 I5 B1 U3) in 和 not in ($in $nin)6 J% }; \! W- ^
( z' M( J8 T4 B/ Q3 r! Q2 ~3 l语法: - db.collection.find( { "field" : { $in : array } } );
复制代码
/ d0 B/ }* n- _# ~ ~& Z例子: - db.things.find({j:{$in: [2,4,6]}});4 q' m/ g" o8 V* u9 ]
- db.things.find({j:{$nin: [2,4,6]}});
复制代码
7 {7 N0 ~/ S2 U5 \* W# U. g% S& ~
3 }& v; Q* g( Y7 E- F4) 取模运算$mod4 F7 S" j7 [" ^/ P- i% N N$ U
2 B# W$ J; P8 e; b3 N/ `6 l' `如下面的运算:
- db.things.find( "this.a % 10 == 1")
复制代码
/ I \3 Q7 `. t2 M3 v可用$mod代替: - db.things.find( { a : { $mod : [ 10 , 1 ] } } )
复制代码
& F& O1 O5 Z" X. y. z/ N1 d9 s
: k- o+ [8 G6 m5) $all) \; @: ^5 ~* R* P
b0 I5 @+ `) [" h9 p6 R; i2 O3 P1 q0 x
$all和$in类似,但是他需要匹配条件内所有的值:6 ]3 m% l+ p; X# V/ {
1 z# e5 O; Q5 X9 s. R! |, k
如有一个对象: t+ b" O3 N/ g
5 q! k1 \: S4 ] @5 X- r下面这个条件是可以匹配的: - db.things.find( { a: { $all: [ 2, 3 ] } } );
复制代码 5 b) g! I# F* M# w5 K
但是下面这个条件就不行了: - db.things.find( { a: { $all: [ 2, 3, 4 ] } } );
复制代码 * K2 d; Q! [7 w+ ?
1 v7 O- J; i, _1 F9 @
6) $size9 N$ J/ o7 o z; ^" P* c2 r& q
1 Y, w7 s) B7 s' ]$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:; z7 k2 H4 @$ \
. o7 `' C2 n3 W# ^6 }. R2 b8 c
下面的语句就可以匹配: - db.things.find( { a : { $size: 1 } } );
复制代码 7 G9 k# O; R4 f6 r9 h8 ]! U
官网上说不能用来匹配一个范围内的元素,如果想找$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.
& b6 j: Z. v3 n' Z" Q: F7)$exists $exists用来判断一个元素是否存在: 如: - db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回1 T$ x$ v: t1 I2 x% S9 u& A! k1 O
- db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回
复制代码
9 W+ G$ O- n3 x# V8) $type $type 基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。 - db.things.find( { a : { $type : 2 } } ); // matches if a is a string* w! A: S: v: K; B3 g3 ?9 d
- db.things.find( { a : { $type : 16 } } ); // matches if a is an int
复制代码
( b! w. L: I( }" S( X& q9)正则表达式9 Y+ R/ U" \$ E7 v- y
4 ?) E) ^# d9 F# D8 m& F- emongo支持正则表达式,如: - db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写
复制代码 7 Q( j" C: o! L) }" C4 f+ U h( O
10) 查询数据内的值
' a0 S; J6 q1 ~* R8 C. V0 U* t# S$ o8 u* ~3 J( t9 |2 Y, `3 o
下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。 - db.things.find( { colors : "red" } );
复制代码 / [* O4 y- O5 w
11) $elemMatch( r5 q j! _' n2 x! s* y
' V: }% s/ i4 X d0 T# g) N
如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素: - > t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } )
$ D& n. p5 Y9 f0 \# F+ ] - { "_id" : ObjectId("4b5783300334000000000aa9"),
: l* G! R, K- x) e# P2 Z+ p3 J - "x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]
9 e- `4 X# h$ E# S - }
复制代码 3 n2 [$ L! Q4 g) H& ^
$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。注意,上面的语句和下面是不一样的。 > t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )
- j9 Z) F* l5 G% M: ~' D/ W$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 } 0 g9 }: h2 K: i! i# P9 D# ~
& o( B9 [, x! i. n4 X" S2 S* J
12) 查询嵌入对象的值 - db.postings.find( { "author.name" : "joe" } );
复制代码 3 v0 ]8 z: L+ _2 K2 r$ u6 S
举个例子: - > db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
复制代码
! O* R* }3 N3 Q4 R: [" ]+ j$ P! f如果我们要查询 authors name 是Jane的, 我们可以这样: - > db.blog.findOne({"author.name" : "Jane"})
复制代码
: S4 d& u( k2 m( K; R如果不用点,那就需要用下面这句才能匹配: - db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
复制代码
6 Y, G- P) R5 l* l% O5 I下面这句: - db.blog.findOne({"author" : {"name" : "Jane"}})
复制代码 8 V) b' B% j' s) V; h
是不能匹配的,因为mongodb对于子对象,他是精确匹配。
1 R6 @1 ^. G$ A' @13) 元操作符 $not 取反 如: - db.customers.find( { name : { $not : /acme.*corp/i } } );
2 w h$ t- f1 _6 N6 W* K: s - db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
复制代码
/ w. I9 C) g( E' y% m, Q4 [shell 环境下的操作: 1. 超级用户相关: 1. #进入数据库admin : S6 g o( D" F0 ?1 g2 u
7 a" [! k% b: ~ 2. #增加或修改用户密码 3. #查看用户列表 4. #用户认证 5. #删除用户 6. #查看所有用户 7. #查看所有数据库 8. #查看所有的collection 9. #查看各collection的状态 - db.printCollectionStats()
复制代码 ) q) C, I! b' z+ C; i( D6 U. I) ^* t
10. #查看主从复制状态 - db.printReplicationInfo()
复制代码 : |+ }9 e) e2 f. L! W
11. #修复数据库 12. #设置记录profiling,0=off 1=slow 2=all 13. #查看profiling
: r; h; \" z- `$ D% U/ X- {" D/ t: O 14. #拷贝数据库 - db.copyDatabase('mail_addr','mail_addr_tmp')
复制代码 6 _2 {2 ~0 C" h9 [7 L: R* e
15. #删除collection 16. #删除当前的数据库 2. 增删改 1. #存储嵌套的对象 - db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
复制代码
8 B% @6 u/ p! y( f& O' d 2. #存储数组对象 - db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
复制代码 ; f0 l: v$ J" y0 K: k! Y/ ^
3. #根据query条件修改,如果不存在则插入,允许修改多条记录 - db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)
复制代码 ) z/ g3 s, \$ q
4. #删除yy=5的记录 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() 0 H1 O; U- r6 j% @1 R
6. 高级查询 条件操作符
( Y9 }: F7 X$ l, @! Q1 J- $gt : > 0 f: Q- u+ x& R0 B$ {$ W+ Z
- $lt : <
" T# t4 Q; L) M- l* r - $gte: >= & O* \7 ~2 j3 d: L# G
- $lte: <=
, m( C. W D q4 Z! {# L. M, h* s - $ne : !=、<> / h5 a2 t' g- |
- $in : in
& i/ c. ]3 v u& c - $nin: not in 0 l. G2 i9 o: l1 F( O4 F: p
- $all: all 4 J! E! Z7 L0 a6 K- a
- $not: 反匹配(1.3.3及以上版本)
复制代码
4 k; h, V( P. o$ I1 b& B7 j" B
" \ V; l2 m# ^" I$ L$ ]* w7 \查询 name <> "bruce" and age >= 18 的数据 1 A" H2 q* I" O
- db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});
复制代码
/ S% N3 \& h2 K' w$ Y+ W2 y2 W6 c' n8 s8 A& f
查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据
1 ] U7 ]- }! ]. u* t" B$ ~- db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});
复制代码
2 I+ s$ g# O* k' X2 X5 T! @7 T! K; n& V3 f. k4 ?
查询 age in (20,22,24,26) 的数据 ! s9 E+ A9 i6 V$ M
- db.users.find({age: {$in: [20,22,24,26]}});
复制代码 0 Z- W; g4 r' S
' z; T' f: t7 X& ~1 ~
查询 age取模10等于0 的数据
6 l) D' K- t( c/ h- db.users.find('this.age % 10 == 0');
复制代码
9 ?! x( I0 N1 O或者
5 i" A0 z0 K/ q0 a" f: w- db.users.find({age : {$mod : [10, 0]}});
复制代码
5 o+ Z( p5 h/ N) S) B' G, o
2 S$ A6 j" \' r! S匹配所有
7 |8 ~; g6 z7 Z' m. N, F m3 P3 B- db.users.find({favorite_number : {$all : [6, 8]}});
复制代码 % {2 ?: S* ]4 O: `8 ^
可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] } 4 e" j. Q w8 ~: _$ V6 M
可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }
' x$ X# W+ w0 R
2 V1 X4 @ a6 {1 ~' x$ Y查询不匹配name=B*带头的记录
$ b: h. t7 `/ d; U- db.users.find({name: {$not: /^B.*/}});
复制代码
* t$ n/ U$ s1 C5 ~查询 age取模10不等于0 的数据
6 {: e A. m1 |; ~7 I) z/ @- db.users.find({age : {$not: {$mod : [10, 0]}}});
复制代码
3 ~& s6 X- x* `, w( k9 S
* T% y/ ?7 w. Z5 N4 Q) Y3 Z* s0 V#返回部分字段 / u0 v0 x7 ]! n: W
选择返回age和_id字段(_id字段总是会被返回) * ^7 K M) _- `
- db.users.find({}, {age:1}); ; T" D- l) ?" ^. R
- db.users.find({}, {age:3});
. g6 o5 g3 J0 u% Q - db.users.find({}, {age:true});
x/ I1 b8 c! @& V2 w2 L - db.users.find({ name : "bruce" }, {age:1});
复制代码 8 q) _, A/ i' s0 R1 k- D
0为false, 非0为true
; X( X4 e3 |& E. q! T4 ~7 b7 v: L' Q( c5 q& \* W
选择返回age、address和_id字段 $ D. p p4 h' E8 C- n
- db.users.find({ name : "bruce" }, {age:1, address:1});
复制代码
7 |% X" w4 J8 A3 x! P$ w: Z1 f0 @& U
5 Z5 i$ N+ a$ c% W' H1 S排除返回age、address和_id字段
" Q! G% p9 `+ h& W- db.users.find({}, {age:0, address:false}); 3 @7 F' n+ f/ x: M* j
- db.users.find({ name : "bruce" }, {age:0, address:false});
复制代码 * ^) f) ?6 \! \8 U9 L- [% S2 n
( _0 w7 m# p/ g% J( G& @( A/ b ?数组元素个数判断
/ J6 ^/ d9 x! E4 a, j6 _3 E6 m( n对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录 * ~4 C* f' m& C: w1 O. j4 t
匹配db.users.find({favorite_number: {$size: 3}}); / v' h. _0 w+ F& S4 T- Q
不匹配db.users.find({favorite_number: {$size: 2}});
: [( F% H' o: B$ D- S# u7 R- n
6 q6 ?8 G9 G6 K L$exists判断字段是否存在 ! H' j% L/ v! `$ b
查询所有存在name字段的记录 & a, Q, }4 ]& b
- db.users.find({name: {$exists: true}});
复制代码 * }" T2 T# j7 c
查询所有不存在phone字段的记录 w3 A3 {/ e1 q Y! `3 D
- db.users.find({phone: {$exists: false}});
复制代码
/ C J) b5 E( k. h% c" l
- F# D- @7 H; d' W% [$type判断字段类型 / n$ `& f9 h; j
查询所有name字段是字符类型的
( Y) c+ i6 I& ]- db.users.find({name: {$type: 2}});
2 e; W; \! i0 e k0 b \: w
复制代码 & T0 X4 e4 s) T* m( B
查询所有age字段是整型的 % Y7 E( B6 z$ Y1 G, h: S& t
- db.users.find({age: {$type: 16}});
( @3 e" Y3 ~) S
复制代码
2 L1 T* B9 M$ @+ ?5 p! \对于字符字段,可以使用正则表达式 - ~. _6 U; a. }& G8 e; \ C
查询以字母b或者B带头的所有记录 V0 Z4 Q6 S: e# a
- db.users.find({name: /^b.*/i}); ! n6 p& Y( i; U( q
复制代码
/ _, N4 `+ E8 D: n, M* x& C$elemMatch(1.3.1及以上版本)
9 s7 W: @! f8 x为数组的字段中匹配其中某个元素 ! T, h/ Y- u0 Y3 O* s- s' G8 H
R1 r# Y3 C( I* N8 o: _6 kJavascript查询和$where查询 , E9 f }0 S2 u/ P
查询 age > 18 的记录,以下查询都一样 & W: a G$ C9 ~: @) O9 M4 l) D
- db.users.find({age: {$gt: 18}});
9 @0 W, X) Y! d - db.users.find({$where: "this.age > 18"});
4 E' t$ m1 T! Q* J' Z/ Y) b" { - db.users.find("this.age > 18");
7 O R$ C# h0 u) z6 m9 G - f = function() {return this.age > 18} db.users.find(f);
复制代码 9 Y$ _5 U/ I! F+ w- O' y' I
+ ?' ]/ ~4 N5 ^排序sort()
( p/ J6 A+ L Q0 T/ w以年龄升序asc # r8 _% j. h. R) W. o" g$ ]
- db.users.find().sort({age: 1});
) ~* E9 z4 `# P9 b( d
复制代码 6 u/ S/ ? c6 q( E6 M
以年龄降序desc
) S3 e E: Y- E$ o- Y! T' {8 e- db.users.find().sort({age: -1});
) t& U+ ~$ m$ E- B, p8 N
复制代码 7 u4 h+ \. ~1 b* F7 @1 ]8 V! P A
限制返回记录数量limit() 5 b9 R! h6 Q5 S' Z9 x2 ~" z; s
返回5条记录
$ c3 b8 S" ]8 ~: e; Z! s- db.users.find().limit(5); 2 r4 h/ V( n7 q# `
复制代码
: f+ K! [& \* `9 w1 T& Q返回3条记录并打印信息 / S5 U: f8 d$ _. y. G! q7 z) a! J
- db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)}); ) L% i' x6 y3 h: H8 M8 G G9 j
复制代码
! U7 f9 {0 G# E' y; |结果 $ J0 y4 h6 \, }' U' W. O9 P6 R
- my age is 18 9 J8 g) ^& {" E0 K
- my age is 19
& e% \3 U: l% [, f) O+ \ - my age is 20
复制代码 ( ^: S B# T6 Z! e: g
# e0 {9 j$ W0 h# x" Z- S L限制返回记录的开始点skip() # }. I4 O2 k% U3 z `/ t
从第3条记录开始,返回5条记录(limit 3, 5) / i5 }2 ^! j0 ~
- db.users.find().skip(3).limit(5);
. _* h. O; D, X! _
复制代码 & y! _; h' ~9 Q4 d1 w- j9 y4 B) H2 l! b9 L
查询记录条数count()
3 X( |. Q* a) d, odb.users.find().count(); 2 r" @! Q, L& F1 A. N! Z
db.users.find({age:18}).count();
, U0 ~2 C U( O& X% i6 h以下返回的不是5,而是user表中所有的记录数量 4 y, n1 x, v7 q6 |
db.users.find().skip(10).limit(5).count(); ( |! S4 b: x& T2 ?: f& h4 e- t
如果要返回限制之后的记录数量,要使用count(true)或者count(非0) ) c8 w2 N' m, j' ~' M
- db.users.find().skip(10).limit(5).count(true);
复制代码 ! |4 d5 r2 _$ g3 }; A! X! `
4 G9 E7 v9 j" Z9 z5 V分组group() 8 [9 l0 M' C2 a2 \9 U& f& X9 R
假设test表只有以下一条数据 3 ]( q g$ E( f. E; q
- { domain: "www.mongodb.org"
0 F" ^/ K1 l: h - , invoked_at: {d:"2009-11-03", t:"17:14:05"}
% i( Z( [, d/ H) p - , response_time: 0.05
i5 W* d b% T5 P - , http_action: "GET /display/DOCS/Aggregation"
! ]- i, M5 G8 K& o - }
复制代码
% U6 U5 d% F7 n- o使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count;
) z6 @+ Y8 G" o0 `8 v- db.test.group(
( s$ d; t2 p* b2 k( k' V) a* n/ Z - { cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}} ' ^. t( |0 H5 P# `2 ~2 q3 y
- , key: {http_action: true}
X# _( G+ z0 z2 N5 ~- j3 G, X4 W - , initial: {count: 0, total_time:0} R, d8 d( I7 ?/ A7 p
- , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
# R2 e8 B+ ^! t8 t) [% d - , finalize: function(out){ out.avg_time = out.total_time / out.count } 8 J3 X4 a! O" j5 w, L6 H- [ P
- } );
, S# N/ \0 ` m V$ W$ W - % K. ]2 l4 k9 x' N5 ]
- [
' Q1 O: F) o" z9 R6 z( b" ~/ L2 B - { 9 f/ t l) J0 C+ Y5 x
- "http_action" : "GET /display/DOCS/Aggregation", / L o9 l5 a- |# [& J9 x
- "count" : 1, ( z5 f* n! N! M9 T% u3 ?
- "total_time" : 0.05,
4 k- y. } G0 w) s - "avg_time" : 0.05 - |7 H* ~- l6 P1 J) N$ t1 o
- } + I! `( R9 O0 K! D7 k1 ^1 [7 y
- ]
复制代码 ; R7 x- s# B# F3 N+ x
8 ^ n! [" c3 w0 j; X: ?" A
( x3 Z' L$ E* c. e P& A6 D- ~3 ^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)
复制代码 ' P! X: |% N; ?% g1 A- Z* m
% g0 |/ A! U" V
, P: n% R4 _+ N% i$ K
相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。 当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。 - distinct
" ], V$ ?. i5 [" J1 z
MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits]. 如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。 如上面的表结构,我想统计所有的喜欢的水果。 - db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.
复制代码
7 P Z( |# j4 h+ k. @7 T9 V- I6 M2 N( m% Z9 D- f$ c" x! H
他成功执行了。输出如: - [ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr" ]
复制代码
9 R3 @( O* S' F4 o' k( M
/ J# w. ?, D! e5 v( M# s5 Z 我想统计集合中共有多少个人[按名字吧] - db.person.distinct("manName")
复制代码
1 j$ x6 X8 |& e: C4 f0 Y
8 V. q, Y/ Q# t/ r6 T 我想统计指定个数的人的共同关注的朋友。 - db.person.distinct("myFriends", {"manName" : {"$in" : ["ZhenQin", "YangYan"]}})
复制代码 , U- z( y* v8 J7 c& M1 k, Z. p5 Z
( C3 _! o u" m
输出如: - 4 ?+ _& _7 Y6 n* b; `
- [ "234567", "345678", "456789", "987654", "ni", "wo" ]
复制代码 1 o. Z0 N1 Z+ y/ Q( A* ]5 g
) [9 y5 C7 w' h; f" p( i6 ^
( U2 G4 | r _+ a8 ~; f那么我使用Java呢? 我只是在演示Mongo的命令,用Spring Data Mongo是怎么操作的? Spring Schema: - <beans xmlns="http://www.springframework.org/schema/beans"! q5 P8 \. Z2 |+ F3 I
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
$ k. F3 P- f* e6 n0 f& Z - xmlns:context="http://www.springframework.org/schema/context"
9 ]& u2 J$ j3 N - xmlns:mongo="http://www.springframework.org/schema/data/mongo"
% s% c4 g& M; A - xsi:schemaLocation="http://www.springframework.org/schema/beans
/ R+ R# K; V6 q" O, ] - http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
( B! v0 }8 g7 L - http://www.springframework.org/schema/context" x: n% r: d/ U' t5 y/ S4 A0 m# I( _
- http://www.springframework.org/schema/context/spring-context-3.1.xsd* T- B, h$ t/ ^! o' `% _
- http://www.springframework.org/schema/data/mongo
' o+ n7 z2 M; x - http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
: U) ^ B! y! p6 K' ^- c j1 z -
$ t* U' ?. c; ]+ Y8 J, i. {9 x - <context:property-placeholder location="classpath:mongo.properties" />
9 y/ ?' U( m) T. J) M - . e8 P# i I, K5 u/ c4 P
- <!-- Default bean name is 'mongo' -->: P4 T' n( t+ O B/ M* |3 O5 J
- <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" />1 o; ~5 s7 [! d
-
: c: N; k9 b) h) p9 `3 r - <mongo:db-factory id="mongoDbFactory"
% u6 h) o8 }& q - mongo-ref="mongo"
1 F+ n2 E1 F. u4 y7 z: z5 D) ^ - dbname="mongotest" />: U+ ]3 V# X/ t% u; ? Q: |
-
2 ^5 c- o1 {) n3 y4 J. \. B - <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
1 n! a# k- z4 Y9 s1 J - <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
! K0 [: z3 y7 n# s8 F) f! ? I - </bean>
; Y! r9 y* \4 m# ~# U4 a6 V - </beans>
复制代码
; A. x6 z5 }5 w
1 Y6 m S8 Z' t- L6 M7 T, ?9 @ max和min的测试: - @Test$ r" ]* L* Z5 b( n( k" y+ g- d
- public void testMaxAndMinAge() throws Exception {$ Z! A; ^. w( v0 Q: v. h- i
- Query q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.ASC, "age"))).limit(1);
% A9 e1 }' [( d; t3 H - Person result = mongoTemplate.findOne(q, Person.class);4 l* K8 A4 r$ K k/ e0 R
- log.info(result);, U) m- |$ U3 i
-
* L8 T- U) T, j - q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.DESC, "age"))).limit(1);6 C; ] k: y/ t) I I
- result = mongoTemplate.findOne(q, Person.class);
3 d# V7 C9 d3 s$ e' ?$ _- S7 \ - log.info(result);% V: c9 [8 s2 W0 J; j0 H9 z b
- }
复制代码 2 e8 T' N3 r, ]/ d" O0 g
# o4 a* M/ F r6 N9 T9 Z) U( T
distinct的测试: - @Test3 U! z0 N, r# Z* l* u6 o+ P
- public void testDistinct() throws Exception {( i; g2 d$ }% |, l
- List result = mongoTemplate.getCollection("person").distinct("myFriends");
+ Q+ z0 l0 G" } - for (Object o : result) {
* J8 b0 r5 L7 ^ - log.info(o);
% U1 a: B3 Z1 o* ] |6 \ - }$ z7 i. H' b* I: ?
-
5 J( L0 B- J" N& \& d9 H - log.info("==================================================================");
: g+ ?: b e% x' H% q - Query query = Query.query(Criteria.where("manId").is("123456"));* y; N' a+ q2 P4 e5 S2 g
- result = mongoTemplate.getCollection("person").distinct("myFriends", query.getQueryObject());
: z8 o6 r7 s% g2 G* T+ w - for (Object o : result) {
& o) @" [% ^' m& a - log.info(o);
" b- S& I7 F0 q5 Q) [$ n - }) b3 p8 |+ ^! \2 c/ Y, L/ L
- , j# o: ?9 r- }7 k
- log.info("==================================================================");
. q! r( i( R4 Z5 Y5 C - result = mongoTemplate.getCollection("person").distinct("fruits.fruitId");
" r' ]! ^3 v9 s Z - for (Object o : result) {
1 y9 w+ |" n9 e' I& }. ? - log.info(o);
1 s1 M8 ^) o7 d P W, e( F, [ - }0 L( E! l) n, _ ~) R
- }
复制代码 6 L9 { ?. t# G7 B& Z
" ^% J) n# A8 q: I5 K
输出的结果为: - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 234567
9 J) g' T! J" S) k/ x3 s - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 345678
) S' Z1 i0 W* D/ h5 \ - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 456789) u. ]1 m" P" l% z$ N) V, W( R
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 987654- L: v0 w8 `' P! W. n+ k
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] ni- C; a7 v5 f- }
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] wo
" Y; @9 r, \( e( W$ o - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 123456
. R! f! T: ~* e1 J - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(75)] ==================================================================7 o% s C2 q& A4 l% R- G
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 234567 b+ q7 P. |" ~; t" X- e
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 345678
, H. E* M8 g, u% a - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 456789* Y0 E% C7 d) o6 s
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 987654
* ^2 h& R" |+ d4 S- _3 ` - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(82)] ==================================================================- g7 e- D! p s# W
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] aaa) q5 a7 w9 @7 Z9 |8 s' ?
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] bbb
% f) i7 I# O7 O: U" y - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] ccc3 }2 w; a& o& q, Q5 n F+ Z
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] www' }+ F0 k- f6 g% h$ `
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] xxx
3 O x" q9 d' O+ i- A- A - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] yyy( e6 Y2 k" J0 O# |0 m6 T: ]
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] zzz# \6 Q/ p5 k. [+ W! F
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] rrr& s6 P0 s' q6 K; L4 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
复制代码
% J. u* {2 x$ F2 H! D! q. h' |9 t. K s4 s
这里我要特别说明一下, 当使用了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等信息。
; I7 I+ i* b+ y+ I5 R
- ` s9 a7 U9 E: T6 Q+ Z% Y' {/ O [' r
|