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