我正在學習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'}
你可以使用'curl -XGET localhost:9200/your_index/_mapping'來更新你的問題,在ES中使用有效**的映射嗎? – Val
好吧,你說的唯一的字段是索引的是'Raw'字段中的字段,它與你試圖聲明的字段不匹配(即它應該只是一個'not_analyzed'字符串)。所以你的索引中有些東西。在某些時候,你的'visit'文件必須在'Raw'字段中有一個字典,而不是一個字符串。也許正確擦除並重新索引您的數據? – Val
我按照你的指示刪除了索引。這似乎解決了索引問題。但是,根據新的映射,沒有「not_analyzed」字段。也許這將通過'localhost:9200/your_index/_mapping'顯示?所以,我試圖得到代理字符串的餅圖,它總是告訴我它被分析 - 代理的新映射是「代理」:{'type':'string','index':'not_analyzed '},'。因此,當我點擊Discover中的Agent時,我會得到有意義的計數 - 即完整代理字符串。餅圖中包含代理字符串中單個單詞的切片 - 比如mozilla&2.0。 –