查询返回的结果超过预期

时间:2014-02-12 10:26:06

标签: mongodb

忍受我,这不是我的问题。只是想让别人理解。

作者注意:

  

possible duplicate问题解决方案允许$ elemMatch进行约束,因为> 所有元素都是数组。这有点不同。

     

因此,在接受的答案中,提出了要点。这种行为很好   记录不应 “将'apples'`与'oranges'进行比较”。这些领域是   不同的类型,虽然有一个解决方法,这是真正的最佳解决方案   世界不要这样做

     

快乐阅读:)

我有一系列我想要搜索的文档,该集合包含以下内容:

 { "_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 ] }

所以我想找到 x 落在1020之间的结果。所以这是对我来说合乎逻辑的查询:

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

但问题是这会在结果中返回两个文件:

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

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

此外,我怎样才能得到我期望的东西?

2 个答案:

答案 0 :(得分:2)

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

  

查询包含数组的字段

     

如果某个字段包含数组且您的查询有多个条件   运算符,如果是单个数组,整个字段将匹配   元素满足条件 数组元素的组合   符合条件

当数组元素的组合独立地匹配所有条件时,Mongo似乎愿意通过回馈结果来“玩笑”。

在我们的示例中,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}} ] })

如果这是用户预期的行为,意见可能会有所不同。但它肯定是有记录的,应该是预期的。

编辑,针对Neil对原始答案的虐待狂和高度教育性的编辑,寻求解决方案:

使用$elemMatch可以对数组进行“更严格”的元素比较。

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

注意:这将匹配x:[11,12] x:[11,25]

我相信当需要这样的查询时,需要对两个查询进行组合,并将结果合并。下面是一个查询,它返回x为不是数组的文档的正确结果:

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

但在这种情况下,最佳方法是将x的类型更改为始终为数组,即使它只包含一个元素。然后,只需要$ elemMatch查询就可以获得正确的结果,并且具有预期的行为。

答案 1 :(得分:2)

您可以先检查子文档是否和数组,并提供所需值的过滤器:

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

返回:

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