|
版本一:
; d# P4 Y8 }- `* Y4 u' \7 M0 z* P6 L) D! U# }9 v6 l
1 ) . 大于,小于,大于或等于,小于或等于" x7 T9 y8 S. p. L" Y- c& ~2 ^( l
6 X* \2 f! ]* e+ H9 O5 m3 v
$gt:大于7 T/ t" w* A( G7 j
$lt:小于( i3 z, ~1 G0 Z$ n& U2 Q& v: ^9 J
$gte:大于或等于
: t& J8 N5 I5 L1 v$lte:小于或等于
7 Z& l! B9 M' c, c* w% c3 r( x) O9 O( _2 V1 s$ b% g: }
例子: - db.collection.find({ "field" : { $gt: value } } ); // greater than : field > value
8 O+ m5 w+ x6 j5 E9 l! J0 r# | - db.collection.find({ "field" : { $lt: value } } ); // less than : field < value5 W7 ]1 _8 [) f, ^0 ~
- db.collection.find({ "field" : { $gte: value } } ); // greater than or equal to : field >= value
0 ~8 g+ @) {4 _7 Q - db.collection.find({ "field" : { $lte: value } } ); // less than or equal to : field <= value
复制代码 0 |1 H: E& _3 _$ p0 }8 C
如查询j大于3,小于4: - db.things.find({j : {$lt: 3}});, V C# X# X/ C
- db.things.find({j : {$gte: 4}});
复制代码 " ?: F [' c! a) R1 }! Y
也可以合并在一条语句内: - db.collection.find({ "field" : { $gt: value1, $lt: value2 } } ); // value1 < field < value
复制代码 ! ] f+ s$ |( K* P: ? r3 t
) D5 E% Q/ q1 ^7 v3 |( s9 e8 Y- e3 m6 `2 k9 q. I( j
2) 不等于 $ne 例子: - db.things.find( { x : { $ne : 3 } } );
复制代码 2 |0 G0 D- |8 V3 x: V7 L
3) in 和 not in ($in $nin). D* y. ?6 a4 `
: x+ ^2 V! t+ R/ a+ L3 y5 S- i语法: - db.collection.find( { "field" : { $in : array } } );
复制代码 0 j, ^( {$ C0 \: _2 r: A7 `
例子: - db.things.find({j:{$in: [2,4,6]}});6 H: o1 S! U, Y! ^0 {* ]/ l
- db.things.find({j:{$nin: [2,4,6]}});
复制代码 : J: s, a9 u, ^4 M
( ^! U; H/ [ P5 \7 @4) 取模运算$mod2 q/ W, ]" h" n* W* U
; Q2 {1 N' U4 s' e; t如下面的运算:
- db.things.find( "this.a % 10 == 1")
复制代码
! }) p1 ?5 \3 J! n可用$mod代替: - db.things.find( { a : { $mod : [ 10 , 1 ] } } )
复制代码
# _# R+ g; j1 H0 [, @' k
& S* X2 w0 `; T! n% A- b5) $all- I! b- a z* V
! V( ]( M v# |; q; a9 y: ]
$all和$in类似,但是他需要匹配条件内所有的值:) V! Y+ J1 f" }) [
' w5 d. \; X; j) N! A2 {如有一个对象:
- }0 j! K5 K+ ~) k$ X3 W6 U: G 1 `5 x8 u1 a! H7 }+ V( N8 K, ?! ~
下面这个条件是可以匹配的: - db.things.find( { a: { $all: [ 2, 3 ] } } );
复制代码 2 z) [/ O6 u+ ?6 S" Z1 _% P
但是下面这个条件就不行了: - db.things.find( { a: { $all: [ 2, 3, 4 ] } } );
复制代码 & r- H1 @+ ` U# S
% e! F& f7 Y1 i" }% U6 X6) $size
/ u2 y' Y, K+ R1 l3 M) N& @ b$ J. Z
3 Q0 C3 V- }# j$ l- |1 g/ S$size是匹配数组内的元素数量的,如有一个对象:{a:["foo"]},他只有一个元素:
2 t& c7 `0 s% |% b: j% Z- D
3 W3 V. h3 w9 g. f2 F& a- g* ~7 Q, z3 P下面的语句就可以匹配:
- db.things.find( { a : { $size: 1 } } );
复制代码 " [7 V3 C3 d E8 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.
# B; f) _8 Z8 ~; z6 T7)$exists $exists用来判断一个元素是否存在: 如: - db.things.find( { a : { $exists : true } } ); // 如果存在元素a,就返回0 D1 P8 J% ~* u, `6 F
- db.things.find( { a : { $exists : false } } ); // 如果不存在元素a,就返回
复制代码
9 W* e" c. _- O( T; T8) $type $type 基于 bson type来匹配一个元素的类型,像是按照类型ID来匹配,不过我没找到bson类型和id对照表。 - db.things.find( { a : { $type : 2 } } ); // matches if a is a string- c. ?/ \/ B& j- `
- db.things.find( { a : { $type : 16 } } ); // matches if a is an int
复制代码 ( Y% L( P4 B0 a2 v9 `. H$ z/ j* z
9)正则表达式
' U" O8 w: q1 a: E3 Y4 W/ ^
9 l3 H/ r: c2 i9 T5 Smongo支持正则表达式,如: - db.customers.find( { name : /acme.*corp/i } ); // 后面的i的意思是区分大小写
复制代码
4 h: ?3 a; O& B M' ]0 c f10) 查询数据内的值
, D! k1 `8 X7 `; D
: {0 X$ b# J" o( l/ s8 `- r: U下面的查询是查询colors内red的记录,如果colors元素是一个数据,数据库将遍历这个数组的元素来查询。 - db.things.find( { colors : "red" } );
复制代码
; b: O; H, a4 T2 O6 V11) $elemMatch+ |7 c, h, W* u$ [- o
4 K& `( V. W0 w( u
如果对象有一个元素是数组,那么$elemMatch可以匹配内数组内的元素: - > t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } ) 2 \7 ]( z# a+ P6 \( x! V! ]. ?
- { "_id" : ObjectId("4b5783300334000000000aa9"), N" M. h% ^7 t7 ^; B# k5 a3 n
- "x" : [ { "a" : 1, "b" : 3 }, 7, { "b" : 99 }, { "a" : 11 } ]
/ R. o- b' r3 A* `' ^. ? y - }
复制代码 0 W) Y# J% a# F. a- B
$elemMatch : { a : 1, b : { $gt : 1 } } 所有的条件都要匹配上才行。注意,上面的语句和下面是不一样的。 > t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )
/ x" g& b6 U* n$ U% Q9 S# m$elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 }
0 y/ n& x6 ^ w* W" Y/ n, _0 |) x8 U1 D8 n
12) 查询嵌入对象的值 - db.postings.find( { "author.name" : "joe" } );
复制代码
0 a9 ~8 W( d$ y% r3 W! R0 w举个例子: - > db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
复制代码 % K: X3 ^9 d# v
如果我们要查询 authors name 是Jane的, 我们可以这样: - > db.blog.findOne({"author.name" : "Jane"})
复制代码 - c) ~6 ^0 U& s/ I
如果不用点,那就需要用下面这句才能匹配: - db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
复制代码 $ P. K" i4 A: R8 E
下面这句: - db.blog.findOne({"author" : {"name" : "Jane"}})
复制代码 9 y8 `. H" y$ U! q s; _$ g* d- V
是不能匹配的,因为mongodb对于子对象,他是精确匹配。 ' y6 p; f3 q* |5 J
13) 元操作符 $not 取反 如: - db.customers.find( { name : { $not : /acme.*corp/i } } );6 _! X' ~' `! A% {9 ]9 v
- db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );
复制代码
8 Y& t8 f' P/ N: }% ~shell 环境下的操作: 1. 超级用户相关: 1. #进入数据库admin
6 t" j( j, O% f: |' A
" D# S6 B7 a# f7 K+ _6 s. v8 I1 t 2. #增加或修改用户密码 3. #查看用户列表 4. #用户认证 5. #删除用户 : Z; T) @: z# `3 W2 {2 ?+ V
6. #查看所有用户 7. #查看所有数据库 8. #查看所有的collection
- T' o% [ K- N$ h: X. G' ^; w 9. #查看各collection的状态 - db.printCollectionStats()
复制代码 0 ^+ }! Y" V, ?
10. #查看主从复制状态 - db.printReplicationInfo()
复制代码
' @( `6 `" o0 i' G. L: T2 _ 11. #修复数据库 12. #设置记录profiling,0=off 1=slow 2=all d$ q) B4 q9 Z) Q- ]* Y2 O' Z
13. #查看profiling 14. #拷贝数据库 - db.copyDatabase('mail_addr','mail_addr_tmp')
复制代码
3 Q& |1 F6 c y2 c5 T N: w5 s0 H: Z 15. #删除collection 16. #删除当前的数据库 2. 增删改 1. #存储嵌套的对象 - db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
复制代码
. Q2 _4 W8 @/ _ F, ] 2. #存储数组对象 - db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
复制代码 8 V9 L8 u; ^& e# R
3. #根据query条件修改,如果不存在则插入,允许修改多条记录 - db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)
复制代码 " T3 S' O+ Q( q& t
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() - w! S$ l7 `& D0 E( u! w
6. 高级查询 条件操作符 " c5 E9 H; T2 Y3 R( G* }" }4 T
- $gt : > 8 m& T& ^0 R G# \
- $lt : <
: }' ~6 R5 Y$ F* f& Q6 C {9 ? - $gte: >=
( P% o, k! m. X% K - $lte: <=
4 ~- @2 V/ ^. k0 v3 U$ i! x% m" y - $ne : !=、<> ( s# ], x4 ^" K/ r+ w
- $in : in ' E5 b' ~- T. p+ ~7 [
- $nin: not in 3 }1 }5 f" A: u9 d4 p- v' W/ N
- $all: all : W4 [- y2 R" E1 U2 k
- $not: 反匹配(1.3.3及以上版本)
复制代码
5 D$ N) j9 O& |. c& ? _
' K3 {( j2 j1 k2 i" {& D查询 name <> "bruce" and age >= 18 的数据 ' E8 p8 I u& m+ f9 z
- db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}});
复制代码
$ L* Y$ t3 M% p6 k2 v M1 j. G& Z, F7 W2 P6 {
查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据
+ e/ O4 K+ V0 h- db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});
复制代码
7 W7 y- r$ u9 h- u* R1 ]8 b: j3 A, W: ]; g" S( R( b
查询 age in (20,22,24,26) 的数据
# ^* }* X% Z0 u0 Y+ } s- db.users.find({age: {$in: [20,22,24,26]}});
复制代码
: P! V& o c6 o0 X) f' J
& a6 p) P5 E( c; w$ |; O7 y查询 age取模10等于0 的数据
/ w# g2 f) _( r# ?- db.users.find('this.age % 10 == 0');
复制代码 3 O X* Q' t3 p, z
或者 - U/ E% M3 D* J4 e, u- F9 l/ L% E
- db.users.find({age : {$mod : [10, 0]}});
复制代码
+ e& y) H/ `! B$ P. A& ]3 D e& |5 i X
匹配所有
$ i* {# r! N) k7 u0 U# p. B6 e8 h- db.users.find({favorite_number : {$all : [6, 8]}});
复制代码 6 {, C% D. J* T
可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] }
/ s* a% q- t# m0 N1 f/ c1 F& v7 D/ p可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }
* ` [9 E. S- p7 `, y# {$ `, {4 c) F& Q( [8 w* N* H
查询不匹配name=B*带头的记录
0 i/ L: [& s" G+ N, u- db.users.find({name: {$not: /^B.*/}});
复制代码 9 |7 y+ ~4 B4 g) w4 l
查询 age取模10不等于0 的数据
6 T. l/ F$ f* K3 M! P2 G- db.users.find({age : {$not: {$mod : [10, 0]}}});
复制代码 $ C( x$ j9 |& ?
. _ @% R" J6 I; ?7 r7 D, e
#返回部分字段
8 Y. k2 y( ^& }6 c) i选择返回age和_id字段(_id字段总是会被返回) 8 ^: x7 M4 g; k& o" J# X) j
- db.users.find({}, {age:1});
9 l7 x: s- O. _/ v+ f* \ - db.users.find({}, {age:3});
8 u1 h* Z6 z; S+ g& A' b - db.users.find({}, {age:true});
' Q8 B8 B9 w0 w0 i8 u E0 Q+ ?; K - db.users.find({ name : "bruce" }, {age:1});
复制代码
4 h# D U5 d/ w+ C9 F Q) Q; V0为false, 非0为true
5 n. v5 O6 A& x0 U/ X; p0 D) [1 ]0 Y- V: b$ k
选择返回age、address和_id字段 ) Y+ M7 q0 k9 T
- db.users.find({ name : "bruce" }, {age:1, address:1});
复制代码 + {9 m6 g1 {) e' S8 U
% e8 V* \$ D1 y: x _! X9 E
排除返回age、address和_id字段 ! D3 b' w$ ?5 I6 {
- db.users.find({}, {age:0, address:false});
+ T8 S' v/ @+ f, c/ j( c7 m - db.users.find({ name : "bruce" }, {age:0, address:false});
复制代码 $ ^6 k4 L. [" i1 R1 [9 j5 k
' v8 n, M- ?5 p9 F
数组元素个数判断
3 d4 m0 d4 h1 p# s. d( V对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录
1 O: I/ X0 Z5 x) @匹配db.users.find({favorite_number: {$size: 3}}); 2 F) x( x3 W6 Q0 h4 B9 @, Q. `( o
不匹配db.users.find({favorite_number: {$size: 2}}); - ^2 y1 ~1 T, l: `3 T: w) ?; q
9 n9 w. B9 ^2 ~5 u, c% ]& H$exists判断字段是否存在 / y1 E/ w6 \; U+ N
查询所有存在name字段的记录
1 Z) d5 f: P; S& v# \- db.users.find({name: {$exists: true}});
复制代码 ! M* l, n. A `- y- T o4 y
查询所有不存在phone字段的记录
" y4 P B6 I7 l# G A( B1 m- db.users.find({phone: {$exists: false}});
复制代码 : i; Z" J5 [0 H- b i& U
/ N* G) l3 f2 H+ f; o/ }
$type判断字段类型 0 g+ L" B1 O& a8 }" [
查询所有name字段是字符类型的
j, o( `9 X+ D1 x0 M- db.users.find({name: {$type: 2}});
& Y! ]6 w' H' A
复制代码
( J x" i1 q! g; ?' Z查询所有age字段是整型的
+ T+ }7 ?* _: ]$ _- db.users.find({age: {$type: 16}}); 9 Z6 k% R. \- |$ P% v6 l
复制代码
* E! M% [: Z* ~, v1 W% P7 f对于字符字段,可以使用正则表达式 , ~% }* l2 s8 E- `
查询以字母b或者B带头的所有记录 # Y ~4 C/ \: l1 K6 B# r
- db.users.find({name: /^b.*/i}); # v2 L5 c9 [& N3 j
复制代码
9 \ c# [3 s( P' J5 q' v$elemMatch(1.3.1及以上版本) 6 q+ w; m5 {; Y9 z1 Z9 B8 W6 E X. M
为数组的字段中匹配其中某个元素 / G. Y& I: @- e% q; y
' Y+ d; A& }: uJavascript查询和$where查询 4 i% ~3 V8 J4 T% ^1 X
查询 age > 18 的记录,以下查询都一样 8 R+ z) R( C# ~* G1 m' R
- db.users.find({age: {$gt: 18}});
3 P; u* Q+ L! x3 C: b6 _' | - db.users.find({$where: "this.age > 18"});
i. J3 Q0 ?/ C- D, I* } - db.users.find("this.age > 18"); + C5 }+ F. L* N+ J6 y; _- Z
- f = function() {return this.age > 18} db.users.find(f);
复制代码
3 l8 E' l2 V( C1 D |8 D4 ~* O; v( C# H! Z) l- p# M
排序sort()
! L+ @5 R( _# x. f+ n, a8 C以年龄升序asc 7 i: v" O+ C. t2 o" Z: K
- db.users.find().sort({age: 1}); 3 ~! `% b, v5 R9 C4 E
复制代码 g0 s7 Y+ |3 E$ `
以年龄降序desc
4 l. N- Z; J) x1 Q1 o* Y$ K C" O" ^$ M- db.users.find().sort({age: -1}); , h3 l. L k! W: t: M/ c
复制代码
+ P$ l8 I* a1 z: d限制返回记录数量limit() - e" }# ?1 g, J& O
返回5条记录 / d! H# N2 t1 \6 ^4 r
- db.users.find().limit(5); 3 g' N( w6 ?& E6 _$ M7 _
复制代码
( c( ?" G0 ]% M7 o9 U返回3条记录并打印信息 3 u5 ^% b- L3 b3 [7 ]# ~1 D
- db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)});
9 @3 |1 G! @2 ]2 W2 l
复制代码
7 e$ l* U- z6 S" J结果 . z; j S# V: {
- my age is 18
1 }" b6 C; K' a6 I! i8 g - my age is 19 6 W6 @, n$ g0 n* ^% H4 w' x
- my age is 20
复制代码 8 t8 O% P$ j- z1 V" T+ J
. e, l8 l; H1 c- n* Z
限制返回记录的开始点skip() ! A4 \: U" R+ |4 ]+ C% {
从第3条记录开始,返回5条记录(limit 3, 5)
I; K" W# F+ t- db.users.find().skip(3).limit(5);
. T; i" C3 r" a2 l( V
复制代码 : v; S3 j& Z2 ]: f" _1 k8 T
查询记录条数count() 2 M' o& D/ L3 Y: h% e5 K' H$ s; E/ u: p
db.users.find().count(); 1 Z- u0 s( Z5 ]3 M7 W1 N
db.users.find({age:18}).count(); 6 H6 S! K7 z5 l6 h( i% ]3 _/ }5 x
以下返回的不是5,而是user表中所有的记录数量 . _' n( c# V& A a
db.users.find().skip(10).limit(5).count(); - L/ w' p. l1 u! X! v
如果要返回限制之后的记录数量,要使用count(true)或者count(非0)
; S+ M' X3 x! ?0 |5 J, l% d! Q, d- db.users.find().skip(10).limit(5).count(true);
复制代码
8 h+ d/ k% g! C+ V1 ]; L1 _
' P; w& x. H* b% Y, u. @分组group()
# H7 V3 t h" r' u假设test表只有以下一条数据
6 b& ^$ Q. i# ^" ]+ A- { domain: "www.mongodb.org"
8 t$ S! ~: ~: ^- o S6 ?4 x - , invoked_at: {d:"2009-11-03", t:"17:14:05"}
' \; E1 H9 _1 Q l - , response_time: 0.05 ! F }) l( D1 T% H9 s: j5 x
- , http_action: "GET /display/DOCS/Aggregation" / L) H* {8 W4 @' F; ?
- }
复制代码 8 U6 ^3 M! o1 \3 ?! E8 ~ @
使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count; , n8 f8 b m# b( l
- db.test.group( q5 H4 B. s0 S$ t' x
- { cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
( ]# v4 V7 W! g, c- ^8 Y2 O - , key: {http_action: true}
" a. Q b( ^% S/ P9 s - , initial: {count: 0, total_time:0} - K6 X# r+ l6 ]# Q# L
- , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
}5 a& G0 O+ N- \6 u8 y4 d - , finalize: function(out){ out.avg_time = out.total_time / out.count } # Z1 } W7 l" m# {% v
- } );
- D( R8 {- X! C: [" j! a3 s6 A - ) u$ z0 F& I5 b, W* p4 P( g F
- [ ! M: ^% H* a( u* B1 }& q; ?
- { ( I* @; |) V5 W5 d
- "http_action" : "GET /display/DOCS/Aggregation",
# m' c7 N( N6 J" W - "count" : 1,
7 B' Q& R* s$ b1 f! J& Z) Y. R0 [2 Q - "total_time" : 0.05,
/ @3 \9 e- N! x# k" f - "avg_time" : 0.05 ( U" t# ^0 B6 w, `) I8 ?
- } o9 |- I1 k, {1 C+ n
- ]
复制代码
& E+ T( h y4 Y( f
2 c h$ b$ K, h0 E9 |7 P( ^% v2 \6 Z/ t- 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
& O; J. A( c! ]; N$ f, @' l* r
我和同事在测试Mongo时,索引还写了不到一半,他想查询某个字段的最大值,结果找了半天文档也没找到关于max的函数。我也很纳闷这是常规函数啊怎么不提供? 后来经过翻阅资料确定Mongo确实不提供直接的max和min函数。但是可以通过间接的方式[sort 和 limit]实现这个。 要查询最大值我们只需要把结果集按照降序排列,取第一个值就是了。 如我的例子,我想取得集合中年龄最大的人。 - db.person.find({}).sort({"age" : -1}).limit(1)
复制代码
2 u N$ W/ K4 }/ J$ v" u5 G% g1 h0 B! _. \: M
2 R! ?9 v7 i- r
相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。 当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。 - distinct
" X6 g1 ]* T- j- e- } }
MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits]. 如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。 如上面的表结构,我想统计所有的喜欢的水果。 - db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.
复制代码 1 q: r/ J& F B$ C! q2 x/ ^1 h6 y
- \3 C2 D6 K# c5 u9 c/ s7 t) L( j4 y 他成功执行了。输出如: - [ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr" ]
复制代码 . ~; X4 @3 v) b* X1 R2 K
2 B" W. q0 D8 ?& K$ J0 B0 f0 X
我想统计集合中共有多少个人[按名字吧] - db.person.distinct("manName")
复制代码 9 r, O2 u$ Z& Z+ k$ i2 U
. t' q: z/ o" h& f4 Z 我想统计指定个数的人的共同关注的朋友。 - db.person.distinct("myFriends", {"manName" : {"$in" : ["ZhenQin", "YangYan"]}})
复制代码
- P' v/ O8 m+ X$ Z5 J6 g
. u( ~0 q% C6 l- J2 n$ c, v 输出如: - ( L+ z. n2 Y" l4 K
- [ "234567", "345678", "456789", "987654", "ni", "wo" ]
复制代码
9 p: Q/ r1 |: l1 ^9 g0 X: _9 R, @" j+ j. i% R" k7 m
& S$ {; M( @4 |( v5 C" H: t* d那么我使用Java呢? 我只是在演示Mongo的命令,用Spring Data Mongo是怎么操作的? Spring Schema: - <beans xmlns="http://www.springframework.org/schema/beans"4 t" f" p9 f/ Z0 `8 }: z. y* s
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
; [. b8 W/ k5 O% r- A/ U. a - xmlns:context="http://www.springframework.org/schema/context"3 Q; N' r S: v% Q9 M8 g* D0 h1 E# E9 t
- xmlns:mongo="http://www.springframework.org/schema/data/mongo"
0 E( P8 k7 z: R; B, n9 m - xsi:schemaLocation="http://www.springframework.org/schema/beans/ |! Y2 k# v U2 h
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd# e/ Z6 B# a6 o* A2 L& E7 Y$ M' d
- http://www.springframework.org/schema/context
8 X4 n* S4 f% `) F" R/ Z - http://www.springframework.org/schema/context/spring-context-3.1.xsd
. n+ Z ~6 e/ T - http://www.springframework.org/schema/data/mongo4 K5 f3 ^+ U" G7 O
- http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">9 G L! w8 J2 t# _( X& u% O
- * S$ d2 r! }% {& W) ]
- <context:property-placeholder location="classpath:mongo.properties" />3 y7 v1 o; R5 ~9 e0 M4 L( D
-
' I% m8 c- O( K - <!-- Default bean name is 'mongo' -->
2 {& x2 Z- n/ u% |% I - <mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" />
) y" J" \& A0 T, d5 @6 J* J -
" s( d1 m" Z( b q6 _) J/ Q& h$ l - <mongo:db-factory id="mongoDbFactory"' Z, y! c8 e( l
- mongo-ref="mongo"
# I. e3 l6 u9 Y* ]! H$ }/ | - dbname="mongotest" />) u4 O; H" p+ p- Q1 u( J. q$ M6 O
- # X+ c* E. M' F u' r7 ^
- <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
$ L) C( |( Y8 {! W. E( S - <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
' ^3 z! J! s5 P$ N' ` - </bean>& S6 G* O" o( |
- </beans>
复制代码 - G0 U9 v; ]9 w+ T$ n: g/ G/ Q/ m
1 u+ c8 E4 m5 }" E b6 V; l5 ~; S8 c6 i
max和min的测试: - @Test
* Z1 k- F* h# b8 j% F( x - public void testMaxAndMinAge() throws Exception {
, W$ D1 z* i5 f t* ^* }1 P$ D - Query q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.ASC, "age"))).limit(1);
t; k. H* c) e - Person result = mongoTemplate.findOne(q, Person.class);
6 A' h4 s0 @' U3 ~ - log.info(result);- R6 d* Q7 u) `: i H" J
-
) p$ K/ y/ B3 d/ L, Z" t# O/ K7 \8 R - q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.DESC, "age"))).limit(1);
; i/ c/ T. G/ Z& Y$ H' u - result = mongoTemplate.findOne(q, Person.class);
6 y2 _( u$ z1 e" f: Z6 X - log.info(result);' ` a0 Y5 A$ l0 O
- }
复制代码
, W! @5 _& K8 ]: J' j D% Y P/ x4 F3 g
distinct的测试: - @Test% }6 }2 k0 \1 c: M
- public void testDistinct() throws Exception {
8 t) e( x5 p1 t* A' \ - List result = mongoTemplate.getCollection("person").distinct("myFriends");
! _+ h$ g) m2 P. e - for (Object o : result) {! t9 Y w) k3 q) V8 M% b$ b8 k h" m' `
- log.info(o);3 \$ c& X6 }) N, i. F+ W
- }1 g& F6 T2 {2 `* J! A
-
* v6 ]$ i( f: l. a7 r" O% a - log.info("==================================================================");8 G7 w5 j/ \2 p7 q
- Query query = Query.query(Criteria.where("manId").is("123456"));
. t- J- U: p$ Q! f3 B - result = mongoTemplate.getCollection("person").distinct("myFriends", query.getQueryObject());0 s& V' ^3 [) a& C9 \- g
- for (Object o : result) {; S. p* E }5 C$ v
- log.info(o);! Z0 k5 Y% E$ a1 h; K! I- f: X( I
- }& t3 n1 a6 W" G9 l& ]
- + k8 {! V4 [8 q5 t& k/ y" ]$ {
- log.info("==================================================================");) |! u/ N4 m6 v- ?, L% r# V" q5 K
- result = mongoTemplate.getCollection("person").distinct("fruits.fruitId");3 W; @0 W3 k4 l- x) A
- for (Object o : result) {2 V) J) V* W" D
- log.info(o);
, f% a8 T+ T m$ T - }- l# H% |$ i( @1 M$ A9 g( @
- }
复制代码
, }8 }0 O; \7 J8 B3 W# A, E O/ W
- c7 P9 v0 X2 \# W 输出的结果为: - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 234567& ^0 O/ p! a( K& t/ L
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 345678# |- P1 x2 n7 S' i( `% b4 m
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 456789
' M- y6 \5 ]+ [+ k( x2 Q% D5 Z - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 987654
5 [/ q" q. M& z4 H7 M. O8 ^ - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] ni" b) o" S1 \, V [: y
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] wo4 t$ P, x+ L! V5 a2 x
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 123456
# {7 e W9 n. w - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(75)] ==================================================================
! `! V- w% e) l4 P. V& B - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 234567+ P5 \# j- U# N+ N
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 345678
( T; k% G+ u, G: d: A2 u - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 456789( I- T7 w2 _% K9 S& |
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 987654& R5 ?. b. R4 y' f: q. \
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(82)] ==================================================================
+ s! \! e8 \" M - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] aaa
' J x) r5 T" m& \4 H, C - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] bbb5 o1 M8 q( N( g; K: X0 a8 J7 x3 F
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] ccc, @% W" f# ~2 I- O) c1 ~# B3 I
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] www7 l- b6 J, S h: \' F' ?4 [, c
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] xxx
5 _0 {! M; L$ `4 X- m: Y - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] yyy
9 w3 l2 x( k! m" I' r3 f: q - 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] zzz, a0 F& Q3 D5 t9 x. `/ \9 }
- 12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] rrr! O4 \7 @5 G# d' r
- 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
复制代码 ( V T+ T" Y: Q# \
# r2 I' @- w$ v4 T8 M5 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等信息。 9 `% }) n$ ?( @* h; `
5 p7 E/ M: O9 i1 ?4 b) P7 w
6 r* p0 r1 e) E1 p, o) X- B |