Python Elasticsearch批量索引数据类型

3
我正在使用以下代码在Elasticsearch中创建索引并加载数据:

我正在使用以下代码来创建索引和加载Elasticsearch中的数据

from elasticsearch import helpers, Elasticsearch
import csv
es = Elasticsearch()
es = Elasticsearch('localhost:9200')
index_name='wordcloud_data'
with open('./csv-data/' + index_name +'.csv') as f:
    reader = csv.DictReader(f)
    helpers.bulk(es, reader, index=index_name, doc_type='my-type')

print ("done")

我的CSV数据如下:

date,word_data,word_count
2017-06-17,luxury vehicle,11
2017-06-17,signifies acceptance,17
2017-06-17,agency imposed,16
2017-06-17,customer appreciation,11

数据加载正常,但数据类型不准确。如何强制将word_count设为整数而非文本?它是如何确定数据类型的?是否有自动识别整型数据类型的方法或通过传递某些参数来实现?
另外,如果我想增加ignore_above或移除某些字段的限制以便无限制地存储字符,该怎么办?
{
  "wordcloud_data" : {
    "mappings" : {
      "my-type" : {
        "properties" : {
          "date" : {
            "type" : "date"
          },
          "word_count" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "word_data" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}
2个回答

5

您需要创建映射来描述字段类型。

使用elasticsearch-py客户端,可以通过es.indices.put_mappingindex.create方法来完成此操作,通过传递描述映射的JSON文档来实现,就像在这个SO答案中展示的那样。它应该是这样的:

es.indices.put_mapping(
    index="wordcloud_data",
    doc_type="my-type",
    body={
        "properties": {  
            "date": {"type":"date"},
            "word_data": {"type": "text"},
            "word_count": {"type": "integer"}
        }
    }
)

然而,我建议看一下elasticsearch-dsl包,它提供了更加优雅的声明式API来描述事物。以下是一个大致的代码示例(未经测试):

from elasticsearch_dsl import DocType, Date, Integer, Text
from elasticsearch_dsl.connections import connections
from elasticsearch.helpers import bulk

connections.create_connection(hosts=["localhost"])

class WordCloud(DocType):
    word_data = Text()
    word_count = Integer()
    date = Date()

    class Index:
        name = "wordcloud_data"
        doc_type = "my_type"   # If you need it to be called so

WordCloud.init()
with open("./csv-data/%s.csv" % index_name) as f:
    reader = csv.DictReader(f)
    bulk(
        connections.get_connection(),
        (WordCloud(**row).to_dict(True) for row in reader)
    )

请注意,我没有尝试过我发布的代码 - 只是写了它。手头没有ES服务器进行测试。可能会有一些小错误或错别字(如果有,请指出),但总体思路应该是正确的。

谢谢,我会尝试这个并告诉你结果。 - Naresh MG
我只是按照文件中的相同顺序更改了顺序...不确定是否重要,从我所看到的来看,一切似乎都正常工作...这是其中一个文档,整数类型是否应该用双引号存储 "word_count" : "12",?---- { "_index" : "wordss", "_type" : "my-type", "_id" : "AVzS4_2-UW5hFY6GiWVj", "_score" : 1.0, "_source" : { "word_date" : "2017-06-17T00:00:00", "word_count" : "12", "word_data" : "手机" } - Naresh MG
@NareshMG 不,它应该被存储和返回为数字,而不是字符串(字符串将被接受作为输入,但会被强制转换为类型映射定义)。可能需要完全删除现有数据(删除索引)并重新创建。仅定义映射不会更新已经存在的数据。如果您没有这样做,您的数据库中将有混合类型数据。 - drdaeman

1
感谢。@drdaeman的解决方案对我有效。尽管如此,值得一提的是,在elasticsearch-dsl 6+中。
class Meta:
     index = "wordcloud_data"
     doc_type = "my-type"

这段代码会引发“无法写入通配符索引”的异常。请将以下内容更改为:
class Index:
   name = 'wordcloud_data'
   doc_type = 'my_type'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接