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