好的,我们再来稍作改动。这个和上一个案例的区别仅仅是内部值的改动:在上一个案例中是一个对象,在下面的案例中将会是一个数字。这足以让数组的特性发生改变:
> db.p.insert({a: [0], _id: "xxx"}) > db.p.find({'a': 0}) < { "_id" : "xxx", "a" : [ 0 ] } > db.q.insert({a: [[0]], _id: "yyy"}) > db.q.find({a: 0}) < Nothing found > db.q.find({'a.0': 0}) < Nothing found > db.q.find({'a.0.0': 0}) < { "_id" : "yyy", "a" : [ [ 0 ] ] }
陷阱: 尽可能的避免数组或者嵌套数组以及其他一对多关系的数据存在于文档之中,并且在需要查询的时候,通常我们倾向于按照一对一关系去查询。然而对于使用数字键(例如{ 'a.0.x': Y }意味着字段a的第一个元素的x字段必须为Y)的混合型文档很可能会让人感觉非常别扭,当然这也取决于数据的复杂程度。
5. 地理定位操作符$near
这个操作符很简单。你拥有大量包含位置字段的文档。位置字段表示的是地理位置信息。技巧就是MongoDB可以对两种不同类型的位置信息进行索引,每种类型都有稍微不同的API和行为。
第一种类型如下:
db.c.find({ location: { $near: [12.3, 32.1], $maxDistance: 777 }});
第二种类型如下:
db.c.find({ location: { $near: { $geometry: { type: "Point", coordinates: [ 12.3, 32.1 ] }, $maxDistance: 777 } }});
对每个被索引类型来说,地理信息查询语法稍稍有些不同。在通常所用的地理位置信息配对中$maxDistance与$near处于同等地位,而在Geo-JSON表示的地理位置信息配对中$maxDistance就是$near的子元素。
然而,还不止这些!有时你在结果集中会两次获得同一个位置点!为了能够理解这一点,我们需要回想一下前一个嵌套数组里存在的缺陷。看看下面代码:
> db.c.insert({ location: [[1, 2], [1, 0]] }); // inserting an array of two points> db.c.ensureIndex ({ location: "2d" }); > db.c.find({ location: { $near: [0, 0], $maxDistance: 500 } }); < { "_id" : ObjectId("52ca30ec3e47d3d91146f2b8"), "location" : [ [ 1, 2 ], [ 1, 0 ] ] } < { "_id" : ObjectId("52ca30ec3e47d3d91146f2b8"), "location" : [ [ 1, 2 ], [ 1, 0 ] ] }
从匹配给定选择子的数组里返回同一个位置点两次,认为是两个位置点。
在我开始使用Javascript编程的时候这些陷阱给提了醒。这里有一些我们平时不容易察觉的情况,其中一些跨浏览器效果不一致,还有一些你几乎用不到的特性,因此在某些情况下你要格外小心。以上这些都是众所周知的JavaScript领域中的问题,但在MongoDB领域中也没有处理的那么好。
几乎所有怪异的特性都在模拟MongoDB的过程中发现,然后整理并列举在这里,这个模拟MongoDB的项目叫做Minimongo, 主要由 David Glasser贡献。
更多精彩尽在2014年4月10日-12日在北京五洲皇冠国际酒店举办的第五届中国数据库技术大会,3月25日之前订票可享受8.8折最低票价。