3

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

例如,假设以下输入文本:

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

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

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

类别:[金融,政治,..]

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

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

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

4

4 回答 4

6

我建议如下:

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

例如,创建此文档:

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 Airesor Los 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结果中的元素,指示匹配的过滤器。

于 2013-03-04T09:40:42.750 回答
2

看起来这也可能非常适合Percolator

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

您需要创建一个索引(使用create index API),我们称之为 test 例如:

curl -XPUT localhost:9200/test

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

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

然后渗透,这意味着我们发送一个文档,然后我们返回它与我们之前索引的查询中的哪些查询匹配:

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 中被索引,那么最好的策略是进行命名查询以在单个请求中获取您的文档匹配的那些。

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

希望这可以帮助!

于 2013-03-04T12:39:10.177 回答
0

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

于 2013-03-01T11:36:07.013 回答
-2

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

查询命令+查询语法

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

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

于 2013-02-27T09:41:05.503 回答