【问题标题】:How to append a document to existing document in mongodb如何将文档附加到MongoDB中的现有文档
【发布时间】:2017-02-25 23:07:01
【问题描述】:

我写了一个 python 脚本来解析 Apache 日志并将其存储在 mongodb 中,格式如下:

{
    "_id": ObjectId("589e77cf74eea90879f49c80"),
    "http_version": "HTTP/1.1",
    "time": ISODate("2017-02-11T02:32:46Z"),
    "server_ip": "x.x.x.x",
    "method": "GET",
    "content_length": 529,
    "referral": "-",
    "uri": "/xxxxxxx.sdsd",
    "agent": "Mozilla/5.00 (Nikto/2.1.5) (Evasions:None) (Test:map_codes)",
    "status_code": 404
}

我需要找出每个 IP 地址的 404、200 和 302 个请求的计数。我又写了一个脚本来获取值并将其存储在字典中。但是,该脚本需要 2 分钟才能获取结果。

db=conn.http_bank
resp= db.http_bank.distinct("server_ip")
total_count=db.http_bank.find().count()
print total_count

def status_code(db,i):

dict_status_code={}
dict_status_code[i]={}
dict_status_code[i].update({'200':db.http_bank.find({"server_ip":i,"status_code":200}).count()})
dict_status_code[i].update({'404':db.http_bank.find({"server_ip":i,"status_code":404}).count()})
dict_status_code[i].update({'302':db.http_bank.find({"server_ip":i,"status_code":302}).count()})

print dict_status_code

print status_code(db,"x.x.x.x")

我需要更改 Python 代码逻辑还是应该更改在 MongoDB 中存储数据的方式?

非常感谢任何帮助。

【问题讨论】:

    标签: python mongodb python-2.7 mongodb-query


    【解决方案1】:

    您可以使用aggregationstatus_code 进行分组,然后检索一个数组,其中包含每个组status_code/server_ip 的计数。在 mongoDB shell 中它会是:

    db.http_bank.aggregate([{
        $group: {
            "_id": {
                "status_code": "$status_code",
                "server_ip": "$server_ip"
            },
            "count": { "$sum": 1 }
        }
    }, {
        $match: {
            "_id.status_code": { "$in": [200, 302, 404] }
        }
    }])
    

    给出:

    { "_id" : { "status_code" : 404, "server_ip" : "1.1.1.1" }, "count" : 2 }
    { "_id" : { "status_code" : 302, "server_ip" : "3.3.3.3" }, "count" : 2 }
    { "_id" : { "status_code" : 200, "server_ip" : "1.1.1.1" }, "count" : 1 }
    { "_id" : { "status_code" : 302, "server_ip" : "2.2.2.2" }, "count" : 1 }
    

    在 python 中你可以像 this 一样做:

    from pymongo import MongoClient
    import datetime
    
    db = MongoClient().testDB
    
    pipeline = [
        {
            "$match":
            {
                "time":
                {
                    "$gte": datetime.datetime(2015, 1, 1, 00, 00, 00),
                    "$lte": datetime.datetime(2018, 1, 1, 00, 00, 00)
                }
            }
        },
        {
            "$group": {
                "_id": {
                    "status_code": "$status_code", 
                    "server_ip": "$server_ip"
                }, 
                "count": { 
                    "$sum": 1 
                }
            }
        },
        {
            "$match": {
                "_id.status_code": { 
                    "$in" : [200,302,404] 
                }
            }
        }
    ]
    
    res = list(db.http_bank.aggregate(pipeline))
    
    dict_status_code={}
    dict_status_code[1]={}
    
    for i, val in enumerate(res):
    
        data = {
            str(int(val["_id"]["status_code"])) : val["count"]
        }
        key = val["_id"]["server_ip"]
        print key, " ==> ", data
    

    给予:

    1.1.1.1  ==>  {'404': 2}
    3.3.3.3  ==>  {'302': 2}
    1.1.1.1  ==>  {'200': 1}
    2.2.2.2  ==>  {'302': 1}
    

    【讨论】:

    • 这就像一个魅力。之前是 3 分钟。现在获取所有数据需要 50 秒。
    • 50 秒对于这样一个基本查询来说仍然非常慢,请务必检查我的答案。
    • 我在一个集合中有 400K 文档。
    • @Bertrand Martel resp= db.http_bank.distinct("server_ip") for ip in resp: ##logic 你提到了
    • 我已经更新了符合您要求的帖子,例如按server_ipstatus_code 分组。你不需要再循环distinctserver_ip。我把你的 dict dict_status_code 的人口留给你,结果
    【解决方案2】:

    您的收藏有索引吗?如果不是,那么这就是它运行缓慢的原因。您可以像这样在 shell 中创建一个:

    db.http_bank.createIndex({ server_ip: 1, status_code: 1 })
    

    这可能需要一段时间,具体取决于您收藏的大小。

    顺便说一句,您应该像其他答案所建议的那样使用聚合框架,但无论哪种方式您都需要索引,因此请先创建它。

    【讨论】:

      猜你喜欢
      • 2011-07-16
      • 2010-10-27
      • 2015-12-21
      • 2011-12-19
      • 1970-01-01
      • 2014-02-22
      • 2019-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多