Извлечь подобъект в массив документа с помощью pymongo - PullRequest
1 голос
/ 04 марта 2020

У меня есть несколько документов, и каждый документ имеет набор твитов. Я могу найти документ по имени следующим образом:

client = MongoClient('localhost', 27017)
db = client['sample_app']
s = db['s']
s.find(
            {
                "name": "temp16"
            }
        )

Когда я запускаю вышеуказанный запрос, я получаю следующие данные:

{"_id": {"$oid": "5e57db66c6bb04eb902589a2"}, "name": "temp16", "tweets": [{"tweet_id": "1234762637361086465", "tweet_text": "Had an extensive review regarding preparedness on the COVID-19 Novel Coronavirus. Different ministries & states are working together, from screening people arriving in India to providing prompt medical attention.", "tweet_handle": "@narendramodi", "labels": ["A", "B", "C", "D", "E"]}, {"tweet_text": "There is no need to panic. We need to work together, take small yet important measures to ensure self-protection.", "tweet_id": "1234762662413660165", "tweet_handle": "@narendramodi", "labels": ["A", "B", "C", "D", "E", "F"]}]}

Мое намерение - получить твит с идентификатором "1234762662413660165" только в этом документе. Поэтому я пробую следующее:

s.find(
            {
                "name": "temp16",
                'tweets': {"tweet_id": "1234762662413660165"}
            },
        )

Однако я получаю None

Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Вам нужно использовать $elemMatch

import pymongo
db = pymongo.MongoClient()['mydatabase']
db.mycollection.insert_one({"name": "temp16", "tweets": [{"tweet_id": "1234762637361086465", "tweet_text": "Had an ...", "tweet_handle": "@narendramodi", "labels": ["A", "B", "C", "D", "E"]}, {"tweet_text": "There is ...", "tweet_id": "1234762662413660165", "tweet_handle": "@narendramodi", "labels": ["A", "B", "C", "D", "E", "F"]}]})

tweets = db.mycollection.find({"name": "temp16", 'tweets': {'$elemMatch': {"tweet_id": "1234762662413660165"}}})

for tweet in tweets:
    print(tweet)
0 голосов
/ 04 марта 2020

вот два способа сделать это с помощью конвейеров агрегации:

db.collection.aggregate(
    { $match: { name: 'temp16' } },
    { $unwind: '$tweets' },
    { $match: { 'tweets.tweet_id': '1234762662413660165' } },
    { $replaceWith: '$tweets' }
)

db.collection.aggregate(
    { $match: { name: 'temp16' } },
    {
        $replaceWith: {
            $arrayElemAt: [
                {
                    $filter: {
                        input: "$tweets",
                        as: "tweet",
                        cond: { $eq: ["$$tweet.tweet_id", '1234762662413660165'] }
                    }
                }, 0]
        }
    }
)

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

...