如何在MongoDB中查询含前置点的嵌套字典键
MongoDB查询含点开头的键名解决方案
问题背景
我在MongoDB集合中有如下格式的数据:
{ "_id": { "$oid": "63737b4b654d9b6a0c3a2006" }, "tag": { "tagName": 0.10534846782684326 } }
要检查特定tagName对应的键是否存在,通常使用以下查询语句:
mycollection.find({f"tag.{'tagName'}": {"$exists": True}})
但部分tagNames的键名以点.开头,例如:
{ "_id": { "$oid": "63737b4b654d9b6a0c3a2006" }, "tag": { ".tagName": 0.10534846782684326 } }
此时执行查询:
mycollection.find({f"tag.{'.tagName'}": {"$exists": True}})
无法找到对应文档,原因是查询条件中出现了双点,MongoDB会将其解析为嵌套字段的分隔符,而非键名的一部分。
MongoDB版本信息:
db version v4.4.13 Build Info: { "version": "4.4.13", "gitVersion": "df25c71b8674a78e17468f48bcda5285decb9246", "openSSLVersion": "OpenSSL 1.1.1f 31 Mar 2020", "modules": [], "allocator": "tcmalloc", "environment": { "distmod": "ubuntu2004", "distarch": "x86_64", "target_arch": "x86_64" } }
解决方案
方法1:使用$expr结合$objectToArray查询
将tag对象转换为键值对数组,通过检查数组中的键名来匹配目标字段。这种方法不受键名特殊字符限制,适用性更广。
示例代码:
target_key = ".tagName" mycollection.find({ "$expr": { "$in": [ target_key, {"$map": { "input": {"$objectToArray": "$tag"}, "as": "item", "in": "$$item.k" }} ] } })
原理说明:
$objectToArray:将tag对象转换为[{k: "键名", v: "值"}]格式的数组$map:从数组中提取所有键名($$item.k)$in:判断目标键名是否存在于提取出的键名列表中
方法2:转义键名中的点(MongoDB 3.6+支持)
MongoDB允许使用反斜杠\转义键名中的点,在Python中需要用双反斜杠\\表示转义后的反斜杠。
示例代码:
target_key = ".tagName" escaped_key = target_key.replace(".", "\\.") mycollection.find({f"tag.{escaped_key}": {"$exists": True}})
原理说明:
转义后生成的查询条件为"tag.\\.tagName": {"$exists": True},MongoDB会将\\.解析为键名中的实际点,而非嵌套字段分隔符,从而正确匹配.tagName键。
内容的提问来源于stack exchange,提问作者Thoth
相关产品推荐
相关产品推荐

