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