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