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

Posted

技术标签:

【中文标题】查找与顺序无关紧要的嵌套数组的完全匹配【英文标题】:Find exact match with nested arrays where order doesn't matter 【发布时间】:2017-11-27 08:02:21 【问题描述】:

假设这个数据:


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

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

我发现这个帖子有点相似:MongoDB Find Exact Array Match but order doesn't matter

虽然使用 $size 和 $all 很有意义,但我不太确定如何将它应用于嵌套数组/对象。

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

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

编辑: 为清楚起见:

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

注意数据的内容是一样的,只是各个数组中数据的顺序发生了变化。希望这更有意义。

【问题讨论】:

什么是input.hashSets?您尝试的查询示例会很方便,这可能是我的错,但我无法真正理解您在寻找什么 input.hashSets 与上面的数据相同,只是任何数组的顺序可能不同。 还是不清楚你的意思。它是否与上面的"hasSets"“完全”相同,尽管可能顺序相反?或者是您希望匹配的"data1""data2" 中的“键”值。如果您仅显示示例 input.hashSets 变量的内容,会更清楚 我问是因为如果它只是相同的结构并且我反转元素的顺序并将其传递给$all,那么文档将按预期返回。所以我认为你需要用目前不适合你的东西来澄清你的情况。 用更多信息编辑了帖子。见上文 【参考方案1】:

您似乎在谈论对$elemMatch$all 的需求。

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

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

然后我可以在$all 条件内使用$elemMatch 来匹配数组的元素,两者都以相反的顺序与“键”以不同的顺序:

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"
                        ]
                
        
      ]
  

如果您需要进一步了解实际的“键”,请更改映射或输入来执行此操作:

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
        

【讨论】:

您的答案(包括尺寸)正是我想要的。似乎工作!感谢您的帮助!

以上是关于查找与顺序无关紧要的嵌套数组的完全匹配的主要内容,如果未能解决你的问题,请参考以下文章

嵌套连接

数据结构顺序字符串(插入删除查找BF模式匹配)

Perl语言学习笔记 15 智能匹配与give-when结构

随机存取顺序存取随机存储和顺序存储

在 Python 中查找输入字符串到元组列表的所有可能匹配项(以任何顺序/顺序)

查找算法总结—顺序二分二叉红黑