2015-09-04 26 views
0

我正在學習ElasticSearch,希望將我的業務數據轉儲到ES中並使用Kibana查看它。經過一週的各種問題後,我終於在2臺Ubuntu 14.04臺式機(集羣)上運行ES和Kibana(分別爲1.7.0和4)。ElasticSearch:將舊訪問者數據導入索引

我現在遇到的問題是如何最好地將數據導入ES。數據流是我捕獲PHP全局變量$ _REQUEST和$ _SERVER爲每個訪問具有唯一ID的文本文件。從那裏,如果他們填寫一張表格,我將這些數據捕獲到一個文本文件中,該文件中的這個唯一ID也在不同的目錄中。然後,我的客戶告訴我,如果填寫表單滿50天,可能會有任何問題。

所以我開始訪問者數據 - $ _REQUEST和$ _SERVER。其中很多是冗餘的,所以我只是試圖捕獲他們到達的時間戳,他們的IP,他們訪問的服務器的IP,他們訪問的域,唯一的ID和他們的用戶代理。所以我創造了這個映射:

time_date_mapping = { 'type': 'date_time' } 
str_not_analyzed = { 'type': 'string'} # Originally this included 'index': 'not analyzed' as well 

visit_mapping = { 
    'properties': { 
     'uniqID': str_not_analyzed, 
     'pages': str_not_analyzed, 
     'domain': str_not_analyzed, 
     'Srvr IP': str_not_analyzed, 
     'Visitor IP': str_not_analyzed, 
     'Agent': { 'type': 'string' }, 
     'Referrer': { 'type': 'string' }, 
     'Entrance Time': time_date_mapping, # Stored as a Unix timestamp 
     'Request Time': time_date_mapping, # Stored as a Unix timestamp 
     'Raw': { 'type': 'string', 'index': 'not_analyzed' }, 
    }, 
} 

我然後將其輸入到ES:

es.index(
      index=Visit_to_ElasticSearch.INDEX, 
      doc_type=Visit_to_ElasticSearch.DOC_TYPE, 
      id=self.uniqID, 
      timestamp=int(math.floor(self._visit['Entrance Time'])), 
      body=visit 
     ) 

當我看到數據在指數ES唯一入口時,_id,_type,域和uniqID被索引搜索(根據Kibana)。所有數據都存在於文檔中,但大多數字段顯示「無法搜索未索引的字段」。

此外,我試圖得到代理的餅圖。但我無法想象得到可視化,因爲無論我點擊代理字段上的哪個框,都不可能進行聚合。剛纔提到它,因爲它似乎被索引的字段顯示出來。

我試圖模擬彈出github的elasticsearch.py​​示例中的映射示例。有人能糾正我如何使用該地圖嗎?

由於

------------映射-------------

{ 
    "visits": { 
    "mappings": { 
     "visit": { 
     "properties": { 
      "Agent": { 
      "type": "string" 
      }, 
      "Entrance Time": { 
      "type": "date", 
      "format": "dateOptionalTime" 
      }, 
      "Raw": { 
      "properties": { 
       "Entrance Time": { 
       "type": "double" 
       }, 
       "domain": { 
       "type": "string" 
       }, 
       "uniqID": { 
       "type": "string" 
       } 
      } 
      }, 
      "Referrer": { 
      "type": "string" 
      }, 
      "Request Time": { 
      "type": "string" 
      }, 
      "Srvr IP": { 
      "type": "string" 
      }, 
      "Visitor IP": { 
      "type": "string" 
      }, 
      "domain": { 
      "type": "string" 
      }, 
      "uniqID": { 
      "type": "string" 
      } 
     } 
     } 
    } 
    } 
} 

-------- -----更新和新的映射-----------

所以我刪除了索引並重新創建它。在我知道將數據映射到特定字段類型之前,原始索引中有一些數據來自它。這似乎解決了只有幾個字段被索引的問題。

但是,我的映射部分似乎被忽略。具體代理字符串映射:

visit_mapping = { 
    'properties': { 
     'uniqID': str_not_analyzed, 
     'pages': str_not_analyzed, 
     'domain': str_not_analyzed, 
     'Srvr IP': str_not_analyzed, 
     'Visitor IP': str_not_analyzed, 
     'Agent': { 'type': 'string', 'index': 'not_analyzed' }, 
     'Referrer': { 'type': 'string' }, 
     'Entrance Time': time_date_mapping, 
     'Request Time': time_date_mapping, 
     'Raw': { 'type': 'string', 'index': 'not_analyzed' }, 
    }, 
} 

下面是我用一個全新的指數http://localhost:9200/visits_test2/_mapping

{ 
    "visits_test2": { 
    "mappings": { 
     "visit": { 
      "properties": { 
      "Agent":{"type":"string"}, 
      "Entrance Time": {"type":"date","format":"dateOptionalTime"}, 
      "Raw": { 
       "properties": { 
       "Entrance Time":{"type":"double"}, 
       "domain":{"type":"string"}, 
       "uniqID":{"type":"string"} 
       } 
      }, 
      "Referrer":{"type":"string"}, 
      "Request Time": {"type":"date","format":"dateOptionalTime"}, 
      "Srvr IP":{"type":"string"}, 
      "Visitor IP":{"type":"string"}, 
      "domain":{"type":"string"}, 
      "uniqID":{"type":"string"} 
      } 
     } 
     } 
    } 
    } 

注輸出。原因是我想確保沒有任何東西從一個轉到另一個。

請注意,我正在使用Python庫elasticsearch.py​​並遵循其映射語法的示例。

--------- Python代碼將數據輸入到ES,根據註釋請求-----------

下面是一個文件名mapping.py,我有還沒有完全評論代碼,因爲這只是測試這種數據錄入ES的方法是否可行的代碼。如果它不是自我解釋,請告訴我,我會添加其他評論。

請注意,在使用Python之前,我在PHP中進行了多年編程。爲了更快地啓動和運行Python,我創建了一些包含基本字符串和文件操作函數的文件,並將它們編譯爲一個包。它們是用Python編寫的,旨在模仿內置PHP函數的行爲。所以當你看到對php_basic_ *的調用時,它就是其中的一個功能。

# Standard Library Imports 
import json, copy, datetime, time, enum, os, sys, numpy, math 
from datetime import datetime 
from enum import Enum, unique 
from elasticsearch import Elasticsearch 

# My Library 
import basicconfig, mybasics 
from mybasics.cBaseClass import BaseClass, BaseClassErrors 
from mybasics.cHelpers import HandleErrors, LogLvl 

# This imports several constants, a couple of functions, and a helper class 
from basicconfig.startup_config import * 

# Connect to ElasticSearch 
es = Elasticsearch([{'host': 'localhost', 'port': '9200'}]) 

# Create mappings of a visit 
time_date_mapping = { 'type': 'date_time' } 
str_not_analyzed = { 'type': 'string'} # This originally included 'index': 'not_analyzed' as well 

visit_mapping = { 
    'properties': { 
     'uniqID': str_not_analyzed, 
     'pages': str_not_analyzed, 
     'domain': str_not_analyzed, 
     'Srvr IP': str_not_analyzed, 
     'Visitor IP': str_not_analyzed, 
     'Agent': { 'type': 'string', 'index': 'not_analyzed' }, 
     'Referrer': { 'type': 'string' }, 
     'Entrance Time': time_date_mapping, 
     'Request Time': time_date_mapping, 
     'Raw': { 'type': 'string', 'index': 'not_analyzed' }, 
     'Pages': { 'type': 'string', 'index': 'not_analyzed' }, 
    }, 
} 


class Visit_to_ElasticSearch(object): 
    """ 

    """ 

    INDEX = 'visits' 
    DOC_TYPE = 'visit' 



    def __init__(self, fname, index=True): 
     """ 

     """ 

     self._visit = json.loads(php_basic_files.file_get_contents(fname)) 
     self._pages = self._visit.pop('pages') 

     self.uniqID = self._visit['uniqID'] 
     self.domain = self._visit['domain'] 
     self.entrance_time = self._convert_time(self._visit['Entrance Time']) 

     # Get a list of the page IDs 
     self.pages = self._pages.keys() 

     # Extra IPs and such from a single page 
     page = self._pages[self.pages[0]] 
     srvr = page['SERVER'] 
     req = page['REQUEST'] 

     self.visitor_ip = srvr['REMOTE_ADDR'] 
     self.srvr_ip = srvr['SERVER_ADDR'] 
     self.request_time = self._convert_time(srvr['REQUEST_TIME']) 

     self.agent = srvr['HTTP_USER_AGENT'] 

     # Now go grab data that might not be there... 
     self._extract_optional() 

     if index is True: 
      self.index_with_elasticsearch() 


    def _convert_time(self, ts): 
     """ 

     """ 

     try: 
      dt = datetime.fromtimestamp(ts) 
     except TypeError: 
      dt = datetime.fromtimestamp(float(ts)) 

     return dt.strftime('%Y-%m-%dT%H:%M:%S')   


    def _extract_optional(self): 
     """ 

     """ 

     self.referrer = '' 


    def index_with_elasticsearch(self): 
     """ 

     """ 

     visit = { 
      'uniqID': self.uniqID, 
      'pages': [], 
      'domain': self.domain, 
      'Srvr IP': self.srvr_ip, 
      'Visitor IP': self.visitor_ip, 
      'Agent': self.agent, 
      'Referrer': self.referrer, 
      'Entrance Time': self.entrance_time, 
      'Request Time': self.request_time, 
      'Raw': self._visit, 
      'Pages': php_basic_str.implode(', ', self.pages), 
     } 

     es.index(
      index=Visit_to_ElasticSearch.INDEX, 
      doc_type=Visit_to_ElasticSearch.DOC_TYPE, 
      id=self.uniqID, 
      timestamp=int(math.floor(self._visit['Entrance Time'])), 
      body=visit 
     ) 


es.indices.create(
    index=Visit_to_ElasticSearch.INDEX, 
    body={ 
     'settings': { 
      'number_of_shards': 5, 
      'number_of_replicas': 1, 
     } 
    }, 
    # ignore already existing index 
    ignore=400 
) 

如果它的事項,這是簡單的循環我用的數據轉儲到ES:

for f in all_files: 
    try: 
     visit = mapping.Visit_to_ElasticSearch(f) 
    except IOError: 
     pass 

其中all_files是所有訪問文件的列表(完整路徑),我有我測試數據集。

這裏是從谷歌機器人訪問樣本訪問文件:

{u'Entrance Time': 1407551587.7385, 
    u'domain': u'############', 
    u'pages': {u'6818555600ccd9880bf7acef228c5d47': {u'REQUEST': [], 
     u'SERVER': {u'DOCUMENT_ROOT': u'/var/www/####/', 
     u'Entrance Time': 1407551587.7385, 
     u'GATEWAY_INTERFACE': u'CGI/1.1', 
     u'HTTP_ACCEPT': u'*/*', 
     u'HTTP_ACCEPT_ENCODING': u'gzip,deflate', 
     u'HTTP_CONNECTION': u'Keep-alive', 
     u'HTTP_FROM': u'googlebot(at)googlebot.com', 
     u'HTTP_HOST': u'############', 
     u'HTTP_IF_MODIFIED_SINCE': u'Fri, 13 Jun 2014 20:26:33 GMT', 
     u'HTTP_USER_AGENT': u'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)', 
     u'PATH': u'/usr/local/bin:/usr/bin:/bin', 
     u'PHP_SELF': u'/index.php', 
     u'QUERY_STRING': u'', 
     u'REDIRECT_SCRIPT_URI': u'http://############/', 
     u'REDIRECT_SCRIPT_URL': u'############', 
     u'REDIRECT_STATUS': u'200', 
     u'REDIRECT_URL': u'############', 
     u'REMOTE_ADDR': u'############', 
     u'REMOTE_PORT': u'46271', 
     u'REQUEST_METHOD': u'GET', 
     u'REQUEST_TIME': u'1407551587', 
     u'REQUEST_URI': u'############', 
     u'SCRIPT_FILENAME': u'/var/www/PIAN/index.php', 
     u'SCRIPT_NAME': u'/index.php', 
     u'SCRIPT_URI': u'http://############/', 
     u'SCRIPT_URL': u'/############/', 
     u'SERVER_ADDR': u'############', 
     u'SERVER_ADMIN': u'[email protected]############', 
     u'SERVER_NAME': u'############', 
     u'SERVER_PORT': u'80', 
     u'SERVER_PROTOCOL': u'HTTP/1.1', 
     u'SERVER_SIGNATURE': u'<address>Apache/2.2.22 (Ubuntu) Server at ############ Port 80</address>\n', 
     u'SERVER_SOFTWARE': u'Apache/2.2.22 (Ubuntu)', 
     u'uniqID': u'bbc398716f4703cfabd761cc8d4101a1'}, 
     u'SESSION': {u'Entrance Time': 1407551587.7385, 
     u'uniqID': u'bbc398716f4703cfabd761cc8d4101a1'}}}, 
    u'uniqID': u'bbc398716f4703cfabd761cc8d4101a1'} 
+0

你可以使用'curl -XGET localhost:9200/your_index/_mapping'來更新你的問題,在ES中使用有效**的映射嗎? – Val

+0

好吧,你說的唯一的字段是索引的是'Raw'字段中的字段,它與你試圖聲明的字段不匹配(即它應該只是一個'not_analyzed'字符串)。所以你的索引中有些東西。在某些時候,你的'visit'文件必須在'Raw'字段中有一個字典,而不是一個字符串。也許正確擦除並重新索引您的數據? – Val

+0

我按照你的指示刪除了索引。這似乎解決了索引問題。但是,根據新的映射,沒有「not_analyzed」字段。也許這將通過'localhost:9200/your_index/_mapping'顯示?所以,我試圖得到代理字符串的餅圖,它總是告訴我它被分析 - 代理的新映射是「代理」:{'type':'string','index':'not_analyzed '},'。因此,當我點擊Discover中的Agent時,我會得到有意義的計數 - 即完整代理字符串。餅圖中包含代理字符串中單個單詞的切片 - 比如mozilla&2.0。 –

回答

0

現在我更好地理解了爲什麼Raw場是因爲它被分配self._visit的對象,而不是一個簡單的string這又與初始化json.loads(php_basic_files.file_get_contents(fname))

無論如何,基於你上面給出的所有信息,我的意見是映射從未通過put_mapping安裝。從那裏開始,沒有其他辦法可以按照你喜歡的方式工作。我建議你修改你的代碼來安裝映射之前你索引你的第一個visit文件。

相關問題