$ elemmatch无法在MongoDB中运行

时间:2014-05-20 08:08:00

标签: mongodb

我正在尝试使用mongodb 2.6.1版中的以下查询来过滤mongo数据但是收到错误。

MongoDB版本2.4.6(工作):

> db.BC_1839.find({data: {$elemMatch:{$where : "this.First_name.toLowerCase().indexOf('kim') ==0"}}});

输出:

{ 
    "_id" : ObjectId("53719a9d5b9e5c8c110001b9"),
    "data" : [
        {
            "First_name" : "Kimberely",
            "Last_name" : "Weyman",
            "Company_name" : "Scientific Agrcltl Svc Inc",  
            "Address" : "7721 Harrison St",
            "City" : "Kingsway West",
            "State" : "NS",
            "Post" : "2208",   
            "Phone1" : "02-7091-8948",   
            "Phone2" : "0441-151-810", 
            "Email" : "kweyman@weyman.com.au",
            "Web" : "http://www.scientificagrcltlsvcinc.com.au", 
            "active" : "true"
        } 
    ], 
    "history" : [    
        { 
            "timestamp" : "2014-05-13 06:07:55",
            "event": "creation",
            "createdby" : "Srikesh Infotech",
            "creation_data" : [
                {
                    "crm_base_contact_id" : "1839",
                    "crm_imported_files_id" : "1464"
                }  
            ] 
        },
        {
            "timestamp" : "2014-05-13 06:09:05",
            "event" : "Task",
            "createdby" : "Srikesh Infotech",
            "Task_data" : [ 
                {
                    "Campaign ID" : "193",  
                    "Campagin Name" : "Test Campa1"
                }
            ]
        }
    ], 
    "ref" : [ 
        { "crm_base_contact_id" : "1839", "crm_imported_files_id" : "1464" }
    ]
}

MongoDB版本2.6.1(不工作):

> db.BC_1839.find({data: {$elemMatch:{$where : "this.First_name.toLowerCase().indexOf('kim') ==0"}}});

输出:

error: {
        "$err" : "Can't canonicalize query: BadValue $elemMatch cannot contain $
where expression",
        "code" : 17287
}

相同的查询在mongodb版本2.4.6中执行但在mongodb版本2.6.1中不执行为什么???

1 个答案:

答案 0 :(得分:3)

它根本不应该在早期版本中工作,因为至少你修改了this的范围,现在引用"数据"作为顶级元素。简而言之,不再允许这样做,除非你绝对必须,否则你真的不应该使用JavaScript方法。即便如此,在大多数情况下仍有更好的方法。

但实际上这是JavaScript匹配的必要使用,因为当存在其他运算符时,它不需要这样做。

您应该使用$regex表单:

db.docs.find({ "data.First_name": /^kim/i })

或在字段中的任何位置,删除插入符^

db.docs.find({ "data.First_name": /kim/i })

这与JavaScript执行效率低得多,但没有通过该解释器引擎处理的开销。当然,它无处不在。

还要考虑依赖JavaScript解析的查询实际上是在做什么:

  • 调用JavaScript解释器实例
  • 将每个文档的BSON文档类型转换为JavaScript类型
  • 根据文档
  • 评估解释器中的JavaScript代码
  • 每个文档
  • 将JavaScript true|false转换回来

考虑到$regex(但是不区分大小写不匹配)正在执行相同的操作,但使用" pcre" C库本身没有转换和每个文档的重铸,那么它显然是两者的理智选择。