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