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