查找与顺序无关的嵌套数组的完全匹配

假设这些数据:

{ "_id" : ObjectId("594d43d1da7887921c701575"), "hashSets" : [ { "data1" : [ "2bf2cededea424f47d64d33c511dd431", "40499da7ee1456a2f79dc39a718aaf9b" ], "data2" : [ "b068931cc450442b63f5b3d276ea4297", "16ebd6af0cadece819da7468a9fd79f4", "8717cfca734e8987971f63b20eeb8024" ] }, { "data1" : [ "098F6BCD4621D373CADE4E832627B4F6", "5A105E8B9D40E1329780D62EA2265D8A", "AD0234829205B9033196BA818F7A872B" ], "data2" : [ "8AD8757BAA8564DC136C1E07507F4A98" ] } ], "__v" : 0 } 

我正在尝试查询“hashSets”上的完全匹配,但“hashSets”数组中对象的顺序可能不同,并且数据数组中哈希的顺序可能有所不同。

我发现这个post有点类似: MongoDB查找精确数组匹配,但顺序无关紧要

虽然使用$ size和$ all是有道理的,但我不太清楚如何将它应用于嵌套的数组/对象。

我正在使用这个简单的查询,但似乎命令必须是相同的:

 db.analysis.find({hashSets:input.hashSets}) 

编辑:为了清晰起见:

 input.hashSets = [ { "data1" : [ "AD0234829205B9033196BA818F7A872B", "098F6BCD4621D373CADE4E832627B4F6", "5A105E8B9D40E1329780D62EA2265D8A" ], "data2" : [ "8AD8757BAA8564DC136C1E07507F4A98" ] }, { "data1" : [ "40499da7ee1456a2f79dc39a718aaf9b", "2bf2cededea424f47d64d33c511dd431" ], "data2" : [ "b068931cc450442b63f5b3d276ea4297", "8717cfca734e8987971f63b20eeb8024", "16ebd6af0cadece819da7468a9fd79f4" ] } ]; 

注意数据的内容是相同的,但是各个数组的数据顺序已经改变。 希望更有意义。

你似乎在谈论$elemMatch需要$all

例如,如果我改变你的示例的结构来颠倒几个元素的顺序:

 [ { "data2" : [ "8AD8757BAA8564DC136C1E07507F4A98" ], "data1" : [ "098F6BCD4621D373CADE4E832627B4F6", "5A105E8B9D40E1329780D62EA2265D8A", "AD0234829205B9033196BA818F7A872B" ] }, { "data2" : [ "b068931cc450442b63f5b3d276ea4297", "16ebd6af0cadece819da7468a9fd79f4", "8717cfca734e8987971f63b20eeb8024" ], "data1" : [ "2bf2cededea424f47d64d33c511dd431", "40499da7ee1456a2f79dc39a718aaf9b" ] } ] 

然后,我可以在$all条件中使用$elemMatch来匹配数组的元素,这两个元素的顺序与“keys”顺序不同:

 db.hashsets.find({ "hashSets": { "$all": input.hashSets.map( e => ({ "$elemMatch": e }) ) } }) 

这将产生一个“查询”,如:

 { "hashSets": { "$all": [ { "$elemMatch" : { "data2" : [ "8AD8757BAA8564DC136C1E07507F4A98" ], "data1" : [ "098F6BCD4621D373CADE4E832627B4F6", "5A105E8B9D40E1329780D62EA2265D8A", "AD0234829205B9033196BA818F7A872B" ] } }, { "$elemMatch" : { "data2" : [ "b068931cc450442b63f5b3d276ea4297", "16ebd6af0cadece819da7468a9fd79f4", "8717cfca734e8987971f63b20eeb8024" ], "data1" : [ "2bf2cededea424f47d64d33c511dd431", "40499da7ee1456a2f79dc39a718aaf9b" ] } } ] } } 

如果你需要进一步的实际“键”,然后改变映射或input做到这一点:

 db.hashsets.find({ "hashSets": { "$all": input.hashSets.map( e => ({ "$elemMatch": { "data2": { "$all": e.data2 }, "data1": { "$all": e.data1 } }}) ) } }) 

要产生一个像这样的查询:

 { "hashSets": { "$all": [ { "$elemMatch" : { "data2" : { "$all": [ "8AD8757BAA8564DC136C1E07507F4A98" ]}, "data1" : { "$all": [ "098F6BCD4621D373CADE4E832627B4F6", "5A105E8B9D40E1329780D62EA2265D8A", "AD0234829205B9033196BA818F7A872B" ]} } }, { "$elemMatch" : { "data2" : { "$all": [ "b068931cc450442b63f5b3d276ea4297", "16ebd6af0cadece819da7468a9fd79f4", "8717cfca734e8987971f63b20eeb8024" ]}, "data1" : { "$all": [ "2bf2cededea424f47d64d33c511dd431", "40499da7ee1456a2f79dc39a718aaf9b" ]} } } ] } } 

或者最灵活,包括大小:

  db.hashsets.find({ "hashSets": { "$all": input.hashSets.map( e => { var obj = {}; Object.keys(e).forEach(k => { obj[k] = { "$all": e[k], "$size": e[k].length } }); return { "$elemMatch": obj }; }), "$size": input.hashSets.length } }) 

当然在“满”中是这样的:

 { "hashSets" : { "$all" : [ { "$elemMatch" : { "data2" : { "$all" : [ "8AD8757BAA8564DC136C1E07507F4A98" ], "$size" : 1 }, "data1" : { "$all" : [ "098F6BCD4621D373CADE4E832627B4F6", "5A105E8B9D40E1329780D62EA2265D8A", "AD0234829205B9033196BA818F7A872B" ], "$size" : 3 } } }, { "$elemMatch" : { "data2" : { "$all" : [ "b068931cc450442b63f5b3d276ea4297", "16ebd6af0cadece819da7468a9fd79f4", "8717cfca734e8987971f63b20eeb8024" ], "$size" : 3 }, "data1" : { "$all" : [ "2bf2cededea424f47d64d33c511dd431", "40499da7ee1456a2f79dc39a718aaf9b" ], "$size" : 2 } } } ], "$size" : 2 } }