我写了一个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中存储数据的方式?
非常感谢任何帮助。
答案 0 :(得分:1)
您可以使用aggregation对status_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 })
这可能需要一段时间,具体取决于您的收藏品的大小。
顺便说一下,你应该像其他答案所建议的那样使用聚合框架,但是你需要索引,所以先创建它。