【问题标题】:Extract sub object in array of a document with pymongo使用 pymongo 提取文档数组中的子对象
【发布时间】:2020-03-04 18:32:06
【问题描述】:

我有多个文档,每个文档都有一组推文。 我可以按名称找到文档,如下所示:

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

我的目的是仅在本文档中获取 ID 为 "1234762662413660165" 的推文。所以我尝试以下方法:

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

但是我得到None

我做错了什么?

【问题讨论】:

    标签: mongodb pymongo


    【解决方案1】:

    你需要使用$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)
    

    【讨论】:

    • 您好,谢谢您的回答,但我正在获取整个文档
    • 我只想要推文
    • db.mycollection.find({"name":"temp16"}, {"tweets":{"$elemMatch": {"tweet_id": "1234762662413660165"}}}) 为我工作
    • 如果您只想要推文文本,您可以将最后一行更改为print(tweet.get('tweets')[0].get('tweet_text'))
    【解决方案2】:

    这里有两种使用聚合管道的方法:

    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]
            }
        }
    )
    

    第一个简短而甜蜜,但它增加了在内存中展开和创建文档的开销。

    【讨论】:

    • 感谢您的回答,我可以在 mongo shell 中完成,但无法在 pymongo 中复制
    • 我不熟悉 pymongo,但 this 似乎是您使用它运行聚合管道的方式。基本上只是将每个阶段作为一个数组项提供。
    猜你喜欢
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2016-11-07
    • 2020-03-23
    相关资源
    最近更新 更多