如何将文档附加到mongodb中的现有文档

时间:2017-02-25 23:07:02

标签: python mongodb python-2.7 mongodb-query

我写了一个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中存储数据的方式?

非常感谢任何帮助。

2 个答案:

答案 0 :(得分: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}

答案 1 :(得分:0)

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

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

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

顺便说一下,你应该像其他答案所建议的那样使用聚合框架,但是你需要索引,所以先创建它。