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