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