2017-02-25 136 views
2

我寫了一個python腳本解析Apache日誌,並將其存儲在MongoDB中採用以下格式:如何將文件附加到現有文件中的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 
} 

我需要找到的404,200的數量和每個IP地址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中數據的方式?

任何幫助,高度讚賞。

回答

1

您可以使用aggregationstatus_code組合起來,然後檢索一個數組,計算每個組的status_code/server_ip。 MongoDB中殼那就是:

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} 
+0

這工作就像一個魅力。這是3分鐘前。現在需要50秒來獲取所有數據。 – vijay

+1

對於這樣的基本查詢,50秒仍然非常緩慢,請務必檢查我的答案。 – leonziyo

+0

我在一個集合中有400K個文檔。 – vijay

0

你有任何索引在你的收藏?如果沒有,那就是它運行緩慢的原因。你可以在這樣的外殼創建一個:

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

這可以根據您的集合的大小而定。

順便說一句,你應該使用像其他答案建議的聚合框架,但是你需要首先創建索引的索引。

相關問題