使用elasticsearch对文本进行分类

我目前正在开发一个涉及从文本中识别不同“关键字”的项目。

作为示例,我们假设以下输入文本:

“这是布宜诺斯艾利斯关于肉类的一些文字的例子”。

进一步假设我的elasticsearch实例存储了以下文档:

城市:[巴塞罗那,布宜诺斯艾利斯,洛杉矶……]

分类:[金融,政治,……]

我需要一种方法来从输入文本中识别相应的城市和类别。

我的第一种方法是使用“或”运算符进行搜索查询,并查看哪一个具有最高排名。 之后,我还将匹配的文件与文本重新匹配,以确保这些文本真的存在(换句话说,确保“洛杉矶”匹配,因为“洛杉矶”一词在文本中,只有“洛杉矶”或“洛杉矶)。

我想知道它是否是使用Elasticsearch做这种事情的最佳实践方式。

我建议如下:

  • 使用match_phrase查询来识别术语losangeles存在并以相同的顺序和位置存在
  • 将每个查询包装在命名filter中,以便您可以识别匹配的查询。

例如,创建此文档:

 curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1' -d ' { "text" : "This is an example of some text written from Buenos Aires about Meat" } ' 

然后运行此查询寻找Buenos AiresLos Angeles

 curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1' -d ' { "query" : { "constant_score" : { "filter" : { "or" : [ { "fquery" : { "_name" : "buenos_aires", "query" : { "match_phrase" : { "text" : "Buenos Aires" } } } }, { "fquery" : { "_name" : "los_angeles", "query" : { "match_phrase" : { "text" : "Los Angeles" } } } } ] } } } } ' # { # "hits" : { # "hits" : [ # { # "_source" : { # "text" : "This is an example of some text written from Buenos Aires about Meat" # }, # "_score" : 1, # "_index" : "test", # "_id" : "JIwnN_FVTv-0i5YGrlHLeg", # "_type" : "test", # "matched_filters" : [ # "buenos_aires" # ] # } # ], # "max_score" : 1, # "total" : 1 # }, # "timed_out" : false, # "_shards" : { # "failed" : 0, # "successful" : 5, # "total" : 5 # }, # "took" : 58 # } 

请注意结果中的matched_filters元素,指示哪个filter匹配。

看起来这也可能非常适合filter 。

您可以将查询索引为单独索引上的文档,然后渗透文档以了解它们匹配的查询。 看看percolate API 。

您需要创建一个索引(使用创建索引API ),让我们称之为测试,例如:

 curl -XPUT localhost:9200/test 

然后注册我们的“布宜诺斯艾利斯”查询给它一个名字。 匹配短语查询似乎是一个不错的选择,正如DrTech在他的回答中所建议的那样。

 curl -XPUT localhost:9200/_percolator/test/buenosaires -d '{ "query" : { "match_phrase" : { "text" : "Buenos Aires" } } }' 

然后percolate,这意味着我们发送一个文档,然后我们回到它们之前索引的查询中匹配的查询:

 curl -XGET localhost:9200/test/type1/_percolate -d '{ "doc" : { "city" : "This is an example of some text written from Buenos Aires about Meat" } }' 

在这种情况下,您应该返回以下json,其中buenosaires是我们在索引时为查询提供的名称:

 {"ok":true, "matches":["buenosaires"]} 

DrTech的答案非常好。 我认为主要区别在于文本的实际位置。 如果它已经在elasticsearch中编入索引,那么最好的策略是使命名查询在单个请求中返回文档匹配的查询。

另一方面,如果您要对数据进行索引,并且需要在实际索引之前丰富文档,那么filter可能更适合。

希望这可以帮助!

将“关键字”标识为先前索引的值并避免诸如“los”“angeles”之类的情况的最佳选择是使用术语构面查询非分析字段。 注意内存成本,并在此处查看更多示例。 干杯

弹性搜索基本上基于Apache Lucene ,因此您可以使用任何您想要的Apaches查询:

查询命令 + 查询语法

在你的情况下,我建议看看“字段”查询:

http://www.elasticsearch.org/guide/reference/query-dsl/field-query.html