Найти точное совпадение с вложенными массивами, где порядок не имеет значения

1

Предположим, что эти данные:

{
    "_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, но порядок не имеет значения

Хотя использование $ size и $ all имеет смысл, я не совсем уверен, как применить его с вложенными массивами/объектами.

Я использовал этот простой запрос, но, похоже, порядок должен быть таким же:

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

EDIT: Для ясности:

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

Обратите внимание, что содержимое данных одинаков, но порядок данных в различных массивах изменился. Надеюсь, что это имеет больше смысла.

  • 0
    что такое input.hashSets ? Пример запроса, который вы пробовали, был бы полезен, может быть, это плохо, но я не могу понять, что вы ищете
  • 0
    input.hashSets идентичен приведенным выше данным, за исключением того, что порядок любого из массивов может отличаться.
Показать ещё 3 комментария
Теги:
arrays
mongodb-query

1 ответ

2
Лучший ответ

Кажется, вы говорите о необходимости $elemMatch с $all.

Например, если я изменяю структуру вашего образца, чтобы изменить порядок нескольких элементов:

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

Затем я могу применить это, используя $elemMatch внутри условия $all чтобы соответствовать элементам массива, как в обратном порядке с "ключами" в другом порядке:

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
        }
}
  • 0
    Ваш ответ, включая размер, это то, что я искал. Кажется, работает! Спасибо за помощь!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню