使用python将dicts或JSON文件列表导入弹性搜索

时间:2017-03-06 10:49:23

标签: python json elasticsearch

我有一个.json.gz文件,我希望加载到弹性搜索中。

我的第一次尝试是使用json模块将JSON转换为dicts列表。

import gzip
import json
from pprint import pprint
from elasticsearch import Elasticsearch

nodes_f = gzip.open("nodes.json.gz")
nodes = json.load(nodes_f)

Dict示例:

pprint(nodes[0])

{u'index': 1,
 u'point': [508163.122, 195316.627],
 u'tax': u'fehwj39099'}

使用Elasticsearch:

es = Elasticsearch()

data = es.bulk(index="index",body=nodes)

然而,这会返回:

elasticsearch.exceptions.RequestError: TransportError(400, u'illegal_argument_exception', u'Malformed action/metadata line [1], expected START_OBJECT or END_OBJECT but found [VALUE_STRING]')

除此之外,我希望能够找到给定tax查询的point,以防这对我应该如何使用elasticsearch索引数据产生影响。

3 个答案:

答案 0 :(得分:4)

Alfe指出了我正确的方向,但我无法让他的代码发挥作用。

我找到了两个解决方案:

逐行显示for循环:

es = elasticsearch.Elasticsearch()

for node in nodes:
    _id = node['index']
    es.index(index='nodes',doc_type='external',id=_id,body=node)

批量使用helper

actions = [
    {
    "_index" : "nodes_bulk",
    "_type" : "external",
    "_id" : str(node['index']),
    "_source" : node
    }
for node in nodes
]

helpers.bulk(es,actions)

对于22代码列表,批量增加约343724倍。

答案 1 :(得分:0)

ES批量库显示了一些问题,包括性能问题,无法设置特定_id等。但由于ES的批量API不是很复杂,我们自己做了:

import requests

headers = { 'Content-type': 'application/json',
            'Accept': 'text/plain'}

jsons = []
for d in docs:
   _id = d.pop('_id')  # take _id out of dict
   jsons.append('{"index":{"_id":"%s"}}\n%s\n' % (_id, json.dumps(d)))
data = ''.join(jsons)
response = requests.post(url, data=data, headers=headers)

我们需要设置一个特定的_id,但我想您可以跳过此部分,以防您希望ES自动设置随机_id

希望有所帮助。

答案 2 :(得分:0)

这是我使用批量api的工作代码:

定义字典列表:

from elasticsearch import Elasticsearch, helpers
es = Elasticsearch([{'host':'localhost', 'port': 9200}])

doc = [{'_id': 1,'price': 10, 'productID' : 'XHDK-A-1293-#fJ3'},
   {'_id':2, "price" : 20, "productID" : "KDKE-B-9947-#kL5"}, 
   {'_id':3, "price" : 30, "productID" : "JODL-X-1937-#pV7"},
   {'_id':4, "price" : 30, "productID" : "QQPX-R-3956-#aD8"}]

helpers.bulk(es, doc, index='products',doc_type='_doc', request_timeout=200)