MongoDB如何实现不依赖嵌套文档字段顺序的过滤查询?
问题原因
MongoDB 对嵌套文档的全量相等匹配默认是严格匹配字段顺序和全部字段的,你第一次编写的filter中data字段的顺序和数据库中存储的顺序一致,所以可以正常匹配到文档,调整字段顺序后匹配逻辑会判定两个对象不相等,自然无法找到对应文档。
不依赖字段顺序的过滤实现方式
方式1:点符号查询(最推荐)
这是实际开发中最稳妥、性能最优的方案,直接对嵌套字段逐个指定匹配条件,完全不依赖字段顺序,还可以利用预先建立的嵌套字段索引提升查询效率。
示例代码:
filter := bson.M{ "_id": "anID", "data.field1": 100, "data.field2": "str", }
这种写法不管数据库中data下的字段存储顺序如何,只要对应字段的值匹配就会命中,而且如果只需要匹配部分嵌套字段,不需要列出所有字段,灵活性很高。
方式2:$expr动态比对(全嵌套文档匹配场景用)
如果你确实需要完整匹配嵌套文档的所有字段,又不想关心顺序,可以用$expr结合$objectToArray、$sortArray做无顺序比对,示例代码如下(需要 MongoDB 5.2及以上版本支持$sortArray):
matchData := bson.M{"field2": "str", "field1": 100} filter := bson.M{ "_id": "anID", "$expr": bson.M{ "$eq": bson.A{ // 将数据库中data字段转成键值对数组并按key排序 bson.M{"$sortArray": bson.M{ "input": bson.M{"$objectToArray": "$data"}, "sortBy": bson.M{"k": 1}, }}, // 将待匹配的data也做同样的转换排序 bson.M{"$sortArray": bson.M{ "input": bson.M{"$objectToArray": matchData}, "sortBy": bson.M{"k": 1}, }}, }, }, }
这种方式的缺点是无法利用普通的字段索引,全表扫描场景下性能远低于点符号查询,仅适合小数据量、必须全量匹配嵌套文档的特殊场景。
附加说明
你示例代码中存在一个笔误:定义的新数据变量是newData,但更新语句里写的是nextData,实际运行会报错,注意修正。
内容的提问来源于stack exchange,提问作者septerr
相关产品推荐
相关产品推荐

