4.数组的特殊待遇
很多人并不知道这个特性,但数组确实是经过特殊处理的。
1 | > db.c.insert({ a: [{x: 2}, {x: 3}], _id: "aaa" }) |
2 | > db.c.find({ 'a.x' : { $gt: 1 }}) |
3 | < { "_id" : "aaa" , "a" : [ { "x" : 2 }, { "x" : 3 } ] } |
4 | > db.c.find({ 'a.x' : { $gt: 2 }}) |
5 | < { "_id" : "aaa" , "a" : [ { "x" : 2 }, { "x" : 3 } ] } |
6 | > db.c.find({ 'a.x' : { $gt: 3 }}) |
因此每当有一个数组对象,选择器都会“分发”给每一个元素,这就像“如果其中一个元素匹配,那么整个文档(document)都会被匹配”。
值得注意的是,它并不适用于嵌套数组::
1 | > db.x.insert({ _id: "bbb" , b: [ [{x: 0}, {x: -1}], {x: 1} ] }) |
2 | > db.x.find({ 'b.x' : 1 }) |
3 | < { "_id" : "bbb" , "b" : [ [ { "x" : 0 }, { "x" : -1 } ], { "x" : 1 } ] } |
4 | > db.x.find({ 'b.x' : 0 }) |
6 | > db.x.find({ 'b.x' : -1 }) |
同样也适用于预测数组中字段(field)的一些特性:
1 | > db.z.insert({a:[[{b:1,c:2},{b:2,c:4}],{b:3,c:5},[{b:4, c:9}]]}) |
2 | > db.z.find({}, { 'a.b' : 1}) |
3 | < { "_id" : ObjectId( "52ca24073e47d3d91146f2b7" ), "a" : [ [ { "b" : 1 }, { "b" : 2 } ], { "b" : 3 }, [ { "b" : 4 } ] ] } |
如果我们在选择器上将以上特性与使用数字键做更多的组合,那么这个特性将变得越来越难以预测:
01 | > db.z.insert({a: [[{x: "00" }, {x: "01" }], [{x: "10" }, {x: "11" }]], _id: "zzz" }) |
02 | > db.z.find({ 'a.x' : '00' }) |
04 | > db.z.find({ 'a.x' : '01' }) |
06 | > db.z.find({ 'a.x' : '10' }) |
08 | > db.z.find({ 'a.x' : '11' }) |
10 | > db.z.find({ 'a.0.0.x' : '00' }) |
11 | < { "_id" : "zzz" , "a" : [ [ { "x" : "00" }, { "x" : "01" } ], [ { "x" : "10" }, { "x" : "11" } ] ] } |
12 | > db.z.find({ 'a.0.0.x' : '01' }) |
14 | > db.z.find({ 'a.0.x' : '00' }) |
15 | < { "_id" : "zzz" , "a" : [ [ { "x" : "00" }, { "x" : "01" } ], [ { "x" : "10" }, { "x" : "11" } ] ] } |
16 | > db.z.find({ 'a.0.x' : '01' }) |
17 | < { "_id" : "zzz" , "a" : [ [ { "x" : "00" }, { "x" : "01" } ], [ { "x" : "10" }, { "x" : "11" } ] ] } |
18 | > db.z.find({ 'a.0.x' : '10' }) |
20 | > db.z.find({ 'a.0.x' : '11' }) |
22 | > db.z.find({ 'a.1.x' : '00' }) |
24 | > db.z.find({ 'a.1.x' : '01' }) |
26 | > db.z.find({ 'a.1.x' : '10' }) |
27 | < { "_id" : "zzz" , "a" : [ [ { "x" : "00" }, { "x" : "01" } ], [ { "x" : "10" }, { "x" : "11" } ] ] } |
28 | > db.z.find({ 'a.1.x' : '11' }) |
29 | < { "_id" : "zzz" , "a" : [ [ { "x" : "00" }, { "x" : "01" } ], [ { "x" : "10" }, { "x" : "11" } ] ] } |
好的,我们再来稍作改动。这个和上一个案例的区别仅仅是内部值的改动:在上一个案例中是一个对象,在下面的案例中将会是一个数字。这足以让数组的特性发生改变:
01 | > db.p.insert({a: [0], _id: "xxx" }) |
03 | < { "_id" : "xxx" , "a" : [ 0 ] } |
04 | > db.q.insert({a: [[0]], _id: "yyy" }) |
07 | > db.q.find({ 'a.0' : 0}) |
09 | > db.q.find({ 'a.0.0' : 0}) |
10 | < { "_id" : "yyy" , "a" : [ [ 0 ] ] } |
陷阱: 尽可能的避免数组或者嵌套数组以及其他一对多关系的数据存在于文档之中,并且在需要查询的时候,通常我们倾向于按照一对一关系去查询。然而对于使用数字键(例如{ 'a.0.x': Y }意味着字段a的第一个元素的x字段必须为Y)的混合型文档很可能会让人感觉非常别扭,当然这也取决于数据的复杂程度。
|
顶 翻译的不错哦! |