Выберите несколько значений из документа

#python #mongodb #mongodb-query #pymongo

Вопрос:

Фон

У меня есть данные, хранящиеся в следующем формате

 {
    "player_id": "VU3R5HNTAGMK",
    "markers": {
        "BICF2P964092": "GC",
        "BICF2G630653981": "CG",
        "BICF2P483996": "CT",
        "BICF2S23452916": "CG",
        "chr26_19147949": "TC",
    }
}
 

Вы можете себе представить, что у меня хранятся данные для нескольких игроков, и каждый из них уникален player_id , и у всех у них разное количество маркеров с разными значениями маркеров.

В приведенном выше случае маркер есть BICF2P964092 , и его значение маркера равно GC .

Я пытаюсь запросить свою базу данных mongo различными способами. Один из очевидных способов-использовать идентификатор игрока. Для этого я делаю следующее col.find({"player_id": "VU3R5HNTAGMK"})

Еще одна вещь, которую я хочу сделать, это, может быть, я просто хочу знать значение определенного маркера для конкретного игрока. Поэтому для этого я могу сделать следующее col.find({"player_id": "VU3R5HNTAGMK"}, {'markers.BICF2P964092'})

вопрос

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

col.find({"player_id": "VU3R5HNTAGMK"},{'markers': {'$in': ["BICF2P964092", "chr26_19147949"]}})

col.find({"player_id": "VU3R5HNTAGMK"}, {'markers.BICF2P964092'}, {'markers.chr26_19147949'})

Я был бы очень признателен, если бы кто-нибудь помог мне написать запрос, в котором я мог бы получить несколько значений маркеров для указанных marker и player_id

Ответ №1:

Вы можете просто сделать следующее

 col.find({“player_id”: “VU3R5HNTAGMK”}, {“markers.”   m: 1 for m in [“ BICF2P964092", “BICF2G630653981”]})
 

Ответ №2:

Поскольку вы пометили этот pymongo, вам, возможно, будет лучше обработать значения маркеров в python после поиска; например

 docs = col.find({"player_id": "VU3R5HNTAGMK"})

for doc in docs:
    for marker, value in doc.get('markers').items():
        if marker in ["BICF2P964092", "chr26_19147949"]:
            print(marker, value)
 

Ответ №3:

Решение @Belly Buster хорошо, если вы хотите справиться с этим с помощью python.

Но есть способ полностью справиться с этим на стороне MongoDB с помощью агрегации.

Вы можете комбинировать $objectToArray , $filter , и $arrayToObject операторов на $project этапе.

 collection.aggregate([
  {
    "$match": {
      "player_id": "VU3R5HNTAGMK"  # <-- All your match conditons
    }
  },
  {
    "$project": {
      "player_id": 1,  # All the other keys which you want to project
      "markers": {
        "$arrayToObject": {
          "$filter": {
            "input": {
              "$objectToArray": "$markers"
            },
            "as": "elem",
            "cond": {
              "$in": [
                "$elem.k",
                [
                  # <-- List of key names you want to project
                  "BICF2G630653981",
                  "BICF2P483996"
                ]
              ]
            },
          },
        },
      },
    }
  },
])
 

Примечание: Для работы этого запроса агрегации необходимо использовать версию MongoDB >= 3.4.4.