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