使用索引时mongo类型匹配更改

时间:2014-07-27 16:26:46

标签: mongodb

我正在尝试编写一个自动化测试,以确保我的集合中的某些字段在文档中具有一致的类型。对于这些字段中的每一个,我都有一个预期的类型。所以我要查询具有不同类型字段的文档,忽略该字段缺失的文档或null。

当字段上存在索引时,似乎不区分数字类型1(double),16(32位int)和18(64位int)。我正在使用mongo 2.6.1。这是一个演示问题的会话:

将文档插入新集合中,它有一个字段x,它是一个32位的int:

> db.typetest.insert({x:NumberInt(1)})
WriteResult({ "nInserted" : 1 })
> db.typetest.find()
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }

请注意,$ type仅匹配类型16(32位int),如预期的那样:

> db.typetest.find({x:{$type:1}})
> db.typetest.find({x:{$type:16}})
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }
> db.typetest.find({x:{$type:17}})
> db.typetest.find({x:{$type:18}})

我需要搜索与给定类型不匹配的文档,并且$不能按预期工作:

> db.typetest.find({x:{$not:{$type:1}}})
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }
> db.typetest.find({x:{$not:{$type:2}}})
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }
> db.typetest.find({x:{$not:{$type:16}}})
> db.typetest.find({x:{$not:{$type:18}}})
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }

创建索引后,$ type有效,但$ not $ type不区分3种数字类型:

> db.typetest.ensureIndex({x:1})
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
> 
> db.typetest.find({x:{$type:1}})
> db.typetest.find({x:{$type:16}})
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }
> db.typetest.find({x:{$type:17}})
> db.typetest.find({x:{$type:18}})
> 
> db.typetest.find({x:{$not:{$type:1}}})
> db.typetest.find({x:{$not:{$type:16}}})
> db.typetest.find({x:{$not:{$type:18}}})
> db.typetest.find({x:{$not:{$type:2}}})
{ "_id" : ObjectId("53d52620eb3748b3f9cde293"), "x" : 1 }

如果这是mongo的预期行为,那将是一件好事。如果这是mongo的错误或限制,我会对另一种执行此测试的方式感兴趣。如果可能的话,我想避免使用$ where(出于性能原因),因为这些测试将在我们的生产数据库中经常运行。

1 个答案:

答案 0 :(得分:1)

我测试了对MongoDB 2.6.1,2.6.3和2.4.10的否定$type查询。

看起来MongoDB 2.4.10会返回预期的结果,但2.6查询规划器中存在一个错误。

暗示使用不包含该字段的索引来否定$type按预期工作:

MongoDB 2.6.3> db.typetest.find({x:{$not:{$type:18}}}).hint({_id:1})
{ "_id" : ObjectId("53d600acbcad4e0896f33c90"), "x" : 1 }
Fetched 1 record(s) in 1ms

MongoDB 2.6.3> db.typetest.find({x:{$not:{$type:18}}}).hint({$natural:1})
{ "_id" : ObjectId("53d600acbcad4e0896f33c90"), "x" : 1 }
Fetched 1 record(s) in 1ms

MongoDB 2.6.3> db.typetest.find({x:{$not:{$type:18}}}).hint({x:1})
Fetched 0 record(s) in 1ms

我已将您的示例添加到错误报告SERVER-14706中,您可以观看/上传。