Как превратить множественное совпадение в агрегат, сравнивающий полную строку в MongoDB?

Я пытаюсь сделать предложение $and внутри предложения $match. Это предложение $and должно содержать полное сравнение со строкой, которую я предоставляю. Я хотел бы убедиться, что сравнение с attributes.value должно соответствовать той строке, которую я передаю. Со следующим выражением:

db.getCollection('cards').aggregate([
    {
        "$match": {
            'attributes.key': 'setCode',
            'attributes.value': 'qc'
        }
    },
    {
        "$match": {
            'attributes.key': 'code',
            'attributes.value': 'potions'
        }
    }]);

Некоторые примеры данных, возвращаемых приведенным выше запросом:

[
  {
    "_id": {"$oid": "66ab6eec2982eff57de4423a"},
    "attributes": [
      {
        "key": "name",
        "displayText": "",
        "value": "Weakness Potion",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "code",
        "displayText": "",
        "value": "weakness-potion",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "text",
        "displayText": "",
        "value": "To play this card, discard 1 of your Potions Lessons from play. Do 5 damage to your opponent. During your opponent's next turn, prevent all damage done to you by your opponent's Creatures.",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "illustrator",
        "displayText": "",
        "value": "Keith Garletts",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "orientation",
        "displayText": "",
        "value": "vertical",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "set",
        "displayText": "",
        "value": "Quidditch Cup",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "setCode",
        "displayText": "",
        "value": "qc",
        "values": [],
        "searchable": true,
        "visible": false,
        "language": ""
      },
      {
        "key": "type",
        "displayText": "",
        "value": "Spell",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "typeCode",
        "displayText": "",
        "value": "spell",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "rarity",
        "displayText": "",
        "value": "Uncommon",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "rarityCode",
        "displayText": "",
        "value": "uncommon",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonType",
        "displayText": "",
        "value": "Potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonTypeCode",
        "displayText": "",
        "value": "potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonCost",
        "displayText": "",
        "value": "7",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "actionCost",
        "displayText": "",
        "value": "1",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "cardNumber",
        "displayText": "",
        "value": "50",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "subType",
        "displayText": "",
        "value": "",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      }
    ],
    "language": "en"
  },
  {
    "_id": {"$oid": "66ab6eec2982eff57de4423d"},
    "attributes": [
      {
        "key": "name",
        "displayText": "",
        "value": "Bruisewort Balm",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "code",
        "displayText": "",
        "value": "bruisewort-balm",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "text",
        "displayText": "",
        "value": "Shuffle up to 5 non-Healing cards from your discard pile into your deck.",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "illustrator",
        "displayText": "",
        "value": "Alex Horley",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "orientation",
        "displayText": "",
        "value": "vertical",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "set",
        "displayText": "",
        "value": "Quidditch Cup",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "setCode",
        "displayText": "",
        "value": "qc",
        "values": [],
        "searchable": true,
        "visible": false,
        "language": ""
      },
      {
        "key": "type",
        "displayText": "",
        "value": "Spell",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "typeCode",
        "displayText": "",
        "value": "spell",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "rarity",
        "displayText": "",
        "value": "Common",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "rarityCode",
        "displayText": "",
        "value": "common",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonType",
        "displayText": "",
        "value": "Potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonTypeCode",
        "displayText": "",
        "value": "potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonCost",
        "displayText": "",
        "value": "3",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "actionCost",
        "displayText": "",
        "value": "1",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "cardNumber",
        "displayText": "",
        "value": "53",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "subType",
        "displayText": "",
        "value": "",
        "values": ["Healing"],
        "searchable": true,
        "visible": true,
        "language": ""
      }
    ],
    "language": "en"
  },
  {
    "_id": {"$oid": "66ab6eec2982eff57de44256"},
    "attributes": [
      {
        "key": "name",
        "displayText": "",
        "value": "Potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "code",
        "displayText": "",
        "value": "potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "text",
        "displayText": "",
        "value": "Provides 1 Potions lesson.",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "illustrator",
        "displayText": "",
        "value": "Shanth Enjeti, Melissa Ferreira",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "orientation",
        "displayText": "",
        "value": "horizontal",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "set",
        "displayText": "",
        "value": "Quidditch Cup",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "setCode",
        "displayText": "",
        "value": "qc",
        "values": [],
        "searchable": true,
        "visible": false,
        "language": ""
      },
      {
        "key": "type",
        "displayText": "",
        "value": "Lesson",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "typeCode",
        "displayText": "",
        "value": "lesson",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "rarity",
        "displayText": "",
        "value": "Common",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "rarityCode",
        "displayText": "",
        "value": "common",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonType",
        "displayText": "",
        "value": "Potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "lessonTypeCode",
        "displayText": "",
        "value": "potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "actionCost",
        "displayText": "",
        "value": "1",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "cardNumber",
        "displayText": "",
        "value": "78",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "providesLesson",
        "displayText": "",
        "value": "Potions",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      },
      {
        "key": "subType",
        "displayText": "",
        "value": "",
        "values": [],
        "searchable": true,
        "visible": true,
        "language": ""
      }
    ],
    "language": "en"
  }
]

Как видите, я получаю результаты, соответствующие коду, например potion, potions, cauldron potion. Я также получаю результаты, в которых другие атрибуты с разными ключами содержат слово potions.

Итак, мое предложение $match не учитывает attributes.key со значениями setCode и code, потому что оно сравнивается с другими атрибутами.

Как я могу убедиться, что приведенное выше условие $match соответствует только заданным ключам и заданным значениям?

Спасибо всем!

Приведите примеры данных. Вероятно, вам придется использовать $elemMatch с attributes, иначе любая комбинация полей .key и .value с этим текстом будет совпадать.

aneroid 09.08.2024 20:06

Спасибо @aneroid, добавил несколько образцов результатов для дальнейшей проверки. Как, по вашему мнению, elemMatch будет работать с этим набором данных?

napfernandes 09.08.2024 22:17
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
2
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Добиться желаемых результатов можно, следуя предложению @aneroid с помощью $elemMatch:

db.getCollection('cards').aggregate([{
  "$match": {
    "attributes": {
      $elemMatch: {
        key: "setCode",
        value: "qc"
      }
    }
  }
}, {
  "$match": {
    "attributes": {
      $elemMatch: {
        key: "code",
        value: "potions"
      }
    }
  }
}]);

Если кто-нибудь знает лучший способ добиться того же результата с помощью более простого запроса, дайте мне знать!

Как уже отмечал @aneroid, нет необходимости использовать $elemMatch. Второй вариант его ответа должен быть «более простым запросом», который вы ищете.

ray 10.08.2024 05:06

Added a separate answer for the new example data.

Ответ на данные предыдущего примера:

Поскольку attributes — это объект, а не массив полей «ключ-значение», вам не нужно делать attr.key и attr.value. (И вам также не понадобится $elemMatch для данных вашего примера.)

Используйте ключи и значения непосредственно в совпадении:

db.getCollection('cards').aggregate([
  {
    $match: {
      "attributes.setCode": "qc",
      "attributes.code": "potions"
    }
  }
])

Игровая площадка Монго

И если вам не нужен конвейер агрегации для каких-то других шагов, его можно использовать непосредственно в запросе find:

db.cards.find({
  "attributes.setCode": "qc",
  "attributes.code": "potions"
})

Игровая площадка Монго

На самом деле я добавил правильный образец: предыдущий был с проекционным результатом, извините за это. Это массив в конце. С помощью elemMatch мне удалось добиться результатов. Посмотрите мой ответ ниже =)

napfernandes 10.08.2024 08:32

Добавлен отдельный ответ для новых данных примера. Это становилось нечитабельным.

aneroid 10.08.2024 11:23
Ответ принят как подходящий

Для текущего примера данных используйте $elemMatch с $all:

db.cards.aggregate([
  {
    $match: {
      "attributes": {
        $all: [
          { $elemMatch: { "key": "setCode", "value": "qc" } },
          { $elemMatch: { "key": "code", "value": "potions" } }
        ]
      }
    }
  }
])

Игровая площадка Монго

И это также работает с find:

db.cards.find({
  "attributes": {
    $all: [
      { $elemMatch: { "key": "setCode", "value": "qc" } },
      { $elemMatch: { "key": "code", "value": "potions" } }
    ]
  }
})

Игровая площадка Mongo с находкой

Другие вопросы по теме