2014-02-12 158 views
1

包涵更多,这不是我的问题。只是想让别人理解。查询返回比预期的结果

作者指出:

possible duplicate问题的解决方案允许$ elemMatch约束因为>的元件的所有是一个数组。这有点不同。

所以,在接受的答案要点提出来了。这种行为是好的 记录和你不应该“比较'苹果'与'橙子'”。这些字段是 不同的类型,虽然是有办法解决这个,对于现实世界 最好的解决办法是不这样做

快乐的阅读:)

我的文档,我试图寻找一个集合,集合包含以下内容:

{ "_id" : ObjectId("52faa8a695fa10cc7d2b7908"), "x" : 1 } 
{ "_id" : ObjectId("52faa8ab95fa10cc7d2b7909"), "x" : 5 } 
{ "_id" : ObjectId("52faa8ad95fa10cc7d2b790a"), "x" : 15 } 
{ "_id" : ObjectId("52faa8b095fa10cc7d2b790b"), "x" : 25 } 
{ "_id" : ObjectId("52faa8b795fa10cc7d2b790c"), "x" : [ 5, 25 ] } 

所以我想找到结果,其中X1020值之间下降。所以这是一个似乎顺理成章的我查询:

db.collection.find({ x: {$gt: 10, $lt: 20} }) 

但问题是这样的返回结果两个文件:

{ "_id" : ObjectId("52faa8ad95fa10cc7d2b790a"), "x" : 15 } 
{ "_id" : ObjectId("52faa8b795fa10cc7d2b790c"), "x" : [ 5, 25 ] } 

我不希望看到第二个结果是没有的值在1020之间。 有人可以解释为什么我没有得到我期望的结果吗?我认为{“X”:15}应该是唯一的文档返回。

所以此外,我怎样才能得到我的期望?

+0

这是故意参考问题[这里](http://stackoverflow.com/questions/21715121/mongodb-descending-index-weird-behavior),但它的措辞作为海报不问的实际问题。他们的问题已经在其背景下得到了回答,但对这部分的回答为任何提出类似问题的人清除了这个问题。让我们看看谁是正确的。 –

+0

它是因为MongoDB不会过滤子文档 – Sammaye

+0

它可以过滤子文档,但不是这样:) –

回答

2

此行为是预期并在mongo文档here中解释。

查询包含数组

如果字段包含数组和您的查询有多个条件 运营商领域,该领域作为一个整体将,如果是单个阵列 元素满足匹配条件数组元素组合 符合条件

蒙戈似乎愿意扮演“臭美”,通过回馈结果的时候数组元素的组合独立匹配所有条件。

在我们的例子中,5匹配$ lt:20条件,25匹配$ gt:10条件。所以,这是一场比赛。

两项操作将返回[5,25]结果:

db.collection.find({ x: {$gt: 10, $lt: 20} }) 

db.collection.find({ $and : [{x: {$gt: 10}},{x:{ $lt: 20}} ] }) 

如果这是用户预期的行为,意见可以不同。但它肯定是有文件记载的,应该是可以预料的。

编辑,尼尔的残暴又富有教育意义的编辑到原来的答案,要求一个解决方案:

使用$elemMatch的可以为阵列只“更严格的”元素比较。

db.collection.find({ x: { $elemMatch:{ $gt:10, $lt:20 } } }) 

:上[11,25]

我认为需要这样的查询时,一个组合:[11,12] X:这两个X匹配需要两个查询,并将结果合并。下面是返回文件正确的结果,其中x是不是数组查询:

db.collection.find({ $where : "!Array.isArray(this.x)", x: {$gt: 10, $lt: 20} }) 

但是,在这种情况下,最好的办法是x的类型更改为总是是一个数组,即使它只包含一个元素。然后,只有$ elemMatch查询才能获得正确的结果,并具有预期的行为。

+0

很好的答案。很高兴你编辑更多的信息。但是,好吧,我会在显而易见的问题上添加一段。 –

+0

是的,没错。看到我的回答后:P –

+0

@kocko我发布了我的答案后才看到它,提前1分钟发布:)并微笑说我们都到达了那里:)不知道我是否应该感谢或讨厌Neil这个问题! :P绝对教会我一些东西:) – Jinxcat

2

可以首先检查子文档是和阵列,并提供一个过滤器为所需值:

db.collection.find(
    { 
    $and : 
     [ 
     { $where : "!Array.isArray(this.x)" }, 
     { x: { $gt: 10, $lt: 20 } } 
     ] 
    } 
) 

它返回:

{ "_id" : ObjectId("52fb4ec1cfe34ac4b9bab163"), "x" : 15 }  
+0

请注意,其当前表单中的查询将执行完整的集合扫描,并且不需要$并且不需要 – Sammaye

+0

我不想使用$ where。我正在阅读的书说通常效率很低。第63-66页:http://shop.oreilly.com/product/0636920028031.do –

+0

另请参阅我的原始问题和下面的评论唯一的答案:http://stackoverflow.com/questions/21715121/mongodb-descending -index-weird-behavior/ –