【问题标题】:Multi-field operations in elasticsearchelasticsearch中的多字段操作
【发布时间】:2012-07-19 08:20:15
【问题描述】:

我开始研究 elasticsearch,我想知道是否可以使用它来完成此操作:(我进行了一些搜索,但我承认我不知道要查找什么)。

我有如下两个联系人数据:

{
  "id"     : "id1",
  "name"   : "Roger",
  "phone1" : "123",
  "phone2" : "",
  "phone3" : "980"
}

{
  "id"     : "id2",
  "name"   : "Lucas",
  "phone1" : "789",
  "phone2" : "123",
  "phone3" : ""
}

我很想知道 elasticsearch 是否可以帮助我找到电话号码重复项,即使它们位于不同的电话字段中(“123”在这两条记录中都存在)。 我已经看到我可以在多个字段中搜索一个字符串,所以如果我搜索 123,我可以得到这两条记录作为结果。但是,我希望能够发出一个可以返回给我的请求,如下所示:

{
  "phones" : {
    "123" : ["id1", "id2"],
    "980" : ["id1"],
    "789" : ["id2"]
  }
}

甚至这会很有用(联系人的数量与号码):

{
  "phones" : {
    "123" : 2,
    "980" : 1,
    "789" : 1
  }
}

知道这是否可能吗?如果它可以做到,那就太棒了。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    我同意 DrTech 更改数据结构的建议。但是,如果出于某种原因,您更愿意保持原样,您可以使用多字段术语 facet 获得相同的结果:

    curl "localhost:9200/phonefacet/_search?pretty=true&search_type=count" -d '{
        "query" : {
            "match_all" : {  }
        },
        "facets" : {
            "tag" : {
                "terms" : {
                    "fields" : ["phone1", "phone2", "phone3"],
                    "size" : 10
                }
            }
        }
    }'
    

    结果如下所示:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 5,
        "successful" : 5,
        "failed" : 0
      },
      "hits" : {
        "total" : 2,
        "max_score" : 0.0,
        "hits" : [ ]
      },
      "facets" : {
        "tag" : {
          "_type" : "terms",
          "missing" : 2,
          "total" : 4,
          "other" : 0,
          "terms" : [ {
            "term" : "123",
            "count" : 2
          }, {
            "term" : "980",
            "count" : 1
          }, {
            "term" : "789",
            "count" : 1
          } ]
        }
      }
    }
    

    【讨论】:

    • 我不知道你能做到这一点!不错!
    • 哇不错!既然你们都建议改变架构,你们提出的建议有什么缺点/性能问题吗?我更喜欢保留字段的标签(实际上更像是 modile_phone、home_phone 等......)
    • 我只是在想,从架构设计的角度来看,如果您将电话字段用作数组,那么在 elasticsearch 中将其表示为数组可能会更好。与 DrTech 提出的相比,我想不出您的架构中有任何重大的性能问题。在一种情况下,elasticsearch 必须读取 3 个字段并合并结果,而在另一个 1 个字段中,其大小等于 3 个字段。与在内存中读取和保存字段值相比,合并不应该那么昂贵。
    • 我会接受这两个答案,但这个更符合我的问题。谢谢你们,我已经喜欢弹性搜索了!^^
    • 我阅读并尝试了更多 es 查询,现在完全理解您的查询的作用,但我还有另一个问题。您是否知道结果是否可以不受大小限制,而是受计数限制,例如返回至少 2 条记录中存在的每个电话?(我已经找到了如何订购但找不到是否可以对结果进行任何过滤)。跨度>
    【解决方案2】:

    您可以使用terms facet 到达那里,但您必须更改数据结构以将所有电话号码包含在单个字段中:

    创建您的索引:

    curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1' 
    

    索引您的数据:

    curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1'  -d '
    {
       "name" : "Roger",
       "id" : "id1",
       "phone" : [
          "123",
          "980"
       ]
    }
    '
    
    curl -XPOST 'http://127.0.0.1:9200/test/test?pretty=1'  -d '
    {
       "name" : "Lucas",
       "id" : "id2",
       "phone" : [
          "789",
          "123"
       ]
    }
    '
    

    搜索所有字段,返回 phone 中的词条数:

    curl -XGET 'http://127.0.0.1:9200/test/test/_search?pretty=1'  -d '
    {
       "facets" : {
          "phone" : {
             "terms" : {
                "field" : "phone"
             }
          }
       }
    }
    '
    
    # {
    #    "hits" : {
    #       "hits" : [
    #          {
    #             "_source" : {
    #                "name" : "Roger",
    #                "id" : "id1",
    #                "phone" : [
    #                   "123",
    #                   "980"
    #                ]
    #             },
    #             "_score" : 1,
    #             "_index" : "test",
    #             "_id" : "StaJK9A5Tc6AR7zXsEKmGA",
    #             "_type" : "test"
    #          },
    #          {
    #             "_source" : {
    #                "name" : "Lucas",
    #                "id" : "id2",
    #                "phone" : [
    #                   "789",
    #                   "123"
    #                ]
    #             },
    #             "_score" : 1,
    #             "_index" : "test",
    #             "_id" : "x8w39F-DR9SZOQoHpJw2FQ",
    #             "_type" : "test"
    #          }
    #       ],
    #       "max_score" : 1,
    #       "total" : 2
    #    },
    #    "timed_out" : false,
    #    "_shards" : {
    #       "failed" : 0,
    #       "successful" : 5,
    #       "total" : 5
    #    },
    #    "facets" : {
    #       "phone" : {
    #          "other" : 0,
    #          "terms" : [
    #             {
    #                "count" : 2,
    #                "term" : "123"
    #             },
    #             {
    #                "count" : 1,
    #                "term" : "980"
    #             },
    #             {
    #                "count" : 1,
    #                "term" : "789"
    #             }
    #          ],
    #          "missing" : 0,
    #          "_type" : "terms",
    #          "total" : 4
    #       }
    #    },
    #    "took" : 5
    # }
    

    【讨论】:

    • 谢谢,我就是这么想的,但我很好奇是否还有其他方法。更改存储数据的架构目前不是问题,所以我会听从您的建议。
    猜你喜欢
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多