【问题标题】:Make a JSON Query to retrieve most relavent result in ElasticSearch进行 JSON 查询以检索 ElasticSearch 中最相关的结果
【发布时间】:2014-01-16 01:44:12
【问题描述】:

我有这个映射

{
  "users":
  {
    "_all" : {"enabled" : false},
    "properties":
    {
        "user": 
        {
           "type":"multi_field",
           "fields":
           {
              "user":{"type":"string"},
              "original":{"type":"string","index":"not_analyzed"}
           }
        }
        "school":{"type":"string","index": "not_analyzed"},
        "college":{"type":"string","index":"not_analyzed"},
        "uni":{"type":"string","index":"not_analyzed"}
    }
  }
}

有这样的数据

{
  "user": "Abdul Jabbar",
  "school": "Aisha Bawany Academy",
  "college": "Pakistan Air Force",
  "uni": "Aptech Computer Education"
}

{
  "user": "Abdul Jabbar WebBestow",
  "school": "Sadaya Academy",
  "college": "Pakistan Air Force",
  "uni": "WebBestow"
}

{
  "user":"Abdul Jabbar Leopard",
  "school":"Innocent Public School",
  "college":"Lucene College of Science",
  "uni":"IBM"
}

{
  "user":"Abdul Jabbar Loharwada",
  "school":"Aisha Bawany Academy",
  "college":"Behria College",
  "uni":"Karachi University"
}

{
  "user":"Abdul Raheem Loharwada",
  "school":"Aisha Bawany Academy",
  "college":"Indus College",
  "uni":"Preston University"
} 

我想获取所有用户包含单词“Jabb”的用户,并且这些结果应该位于顶部,其中包含 “Aisha Bawany Academy”或“Pakistan Air Force”或“Aptech Computer Education”他们的任何学校、学院或大学领域以及那些包含单词“Jabb”但在他们的学校、学院或大学领域中没有相关数据的文件应低于最佳结果。

即使用户的全名是“Abdul Jabbar *”等等,但是当我们只输入“Jabb”时,它应该会带上包含单词“Jabb”的任何用户的上述文档。

如何进行这样的 JSON 查询?请帮助我们。

【问题讨论】:

    标签: json rest lucene elasticsearch


    【解决方案1】:

    使用您的新映射和数据,以下查询会为我返回结果。

    curl -XPOST "http://localhost:9200/test_index/_search" -d'
    {
       "query": {
          "bool": {
             "must": [
                {
                   "prefix": {
                      "user": "jabb"
                   }
                }
             ],
             "should": [
                {
                   "match": {
                      "school": {
                          "query": "Aisha Bawany Academy"
                      }
                   }
                },
                {
                   "match": {
                      "college": {
                          "query": "Aisha Bawany Academy"
                      }
                   }
                },
                {
                   "match": {
                      "uni": {
                          "query": "Aisha Bawany Academy"
                      }
                   }
                }
             ]
          }
       }
    }'
    

    问题可能是您将“College”更改为“college”等等,因此也必须更新查询。一般来说,ES 是区分大小写的。

    还要注意,在我的示例中,查询“jabb”是小写的。这是必要的,因为前缀查询不对查询文本进行任何分析,并且“用户”字段已使用标准分析器(因为映射中未指定分析器)进行分析,该分析器将标记修改为小写。即使某些被索引的文档有文本“Jabbar”,它也会被标记为“jabbar”,因此前缀查询“Jabb”不匹配任何标记。

    您可以在此处阅读有关前缀查询的信息:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html

    这里是标准分析器:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html

    此外,由于您希望将多个值与多个字段匹配,因此以下查询结构可能会更好:

    curl -XPOST "http://localhost:9200/test_index/_search" -d'
    {
       "query": {
          "bool": {
             "must": [
                {
                   "prefix": {
                      "user": "jabb"
                   }
                }
             ],
             "should": [
                {
                   "multi_match": {
                      "query": "Aisha Bawany Academy",
                      "fields": ["school", "college", "uni"]
                   }
                },
                {
                   "multi_match": {
                      "query": "Pakistan Air Force",
                      "fields": ["school", "college", "uni"]
                   }
                },
                {
                   "multi_match": {
                      "query": "Aptech Computer Education",
                      "fields": ["school", "college", "uni"]
                   }
                }
             ]
          }
       }
    }'
    

    【讨论】:

    • 感谢您的热情回复仕龙。但我不知道为什么您当前的查询仍然没有任何结果。可能是什么原因?我当前的映射是否存在问题?
    • 我们感觉被困在这里,请帮助我们。
    • 很难说。我将逐步发布我所做的事情,也许这会帮助您找出问题所在。
    • 雅虎!!!!!!谢谢斯隆。谢谢ssssssss 很多人。爱你。我喜欢你。效果很好。
    • 其实我的队友在 Mappings 上做了一些改动,所以我支持了他们,并且成功了。
    【解决方案2】:

    我使用您提供的四个文档创建了一个具有默认映射的索引。以下查询似乎可以完成您想要的:

    curl -XPOST "http://localhost:9200/test_index/_search" -d'
    {
       "query": {
          "bool": {
             "must": [
                {
                   "prefix": {
                      "user": "john"
                   }
                }
             ],
             "should": [
                {
                   "match": {
                      "School": {
                          "query": "DDD"
                      }
                   }
                },
                {
                   "match": {
                      "College": {
                          "query": "BBB"
                      }
                   }
                }
             ]
          }
       }
    }'
    

    产生结果:

    {
       "took": 3,
       "timed_out": false,
       "_shards": {
          "total": 2,
          "successful": 2,
          "failed": 0
       },
       "hits": {
          "total": 3,
          "max_score": 0.6043929,
          "hits": [
             {
                "_index": "test_index",
                "_type": "docs",
                "_id": "2",
                "_score": 0.6043929,
                "_source": {
                   "user": "Johnathan",
                   "School": "DDD",
                   "College": "AAA"
                }
             },
             {
                "_index": "test_index",
                "_type": "docs",
                "_id": "1",
                "_score": 0.43922842,
                "_source": {
                   "user": "John Doe",
                   "School": "AAA",
                   "College": "BBB"
                }
             },
             {
                "_index": "test_index",
                "_type": "docs",
                "_id": "4",
                "_score": 0.15109822,
                "_source": {
                   "user": "Johnson",
                   "School": "AAA",
                   "College": "EEE"
                }
             }
          ]
       }
    }
    

    注意,前缀查询在“must”子句中,所以只会返回匹配该查询的结果,而其他两个要求在“should”子句中,这样匹配的结果会排名更高。如果需要,您可以通过向匹配查询添加“提升”值来进一步自定义评分,尽管“匹配”与“布尔”结合使用默认 ES 行为做得不错。

    就第二个问题而言,通过 http 提供的默认安装 elasticsearch 绝对容易被篡改。有很多方法可以处理这个问题。您可以安装身份验证插件和/或像 nginx 这样的反向代理来处理身份验证,这样只有登录的用户才能访问 Elasticsearch。您还可以使用列入白名单的 IP,以便只有受信任的 IP 才能访问 ES。我们在Qbox 上提供了这两种方法,但是在与 javascript 应用程序一起使用时都存在一些问题。我们发现一种适用于客户端应用程序的方法是默认要求所有 ES 访问的身份验证,但在 nginx conf 中创建一个“仅搜索”端点,允许任何未经身份验证的用户搜索,但不能编辑数据.在这种情况下,您可能还想在 ES conf 中禁用脚本。如果这些方法都不起作用,那么您可能希望将 ES 关闭到 http 流量并围绕它构建自己的应用程序包装器,以便您可以以任何需要的方式保护它。

    【讨论】:

    • 伟大的斯隆阿伦斯!非常感谢伙计。你真是太棒了。你能给我一个你说的提升例子吗?我们真的需要完成这个。你无法想象这个查询对我们有多重要。我会让我的朋友在这方面工作。如果可能的话,请给我们举个例子。再次感谢。
    • 感谢斯隆阿伦斯。虽然我们昨晚有这个问题,但直到那时我每 5 分钟访问一次,看看是否有人回答了。再次感谢。请评分提升示例。
    【解决方案3】:

    在前面的示例中添加提升非常简单。假设我希望“College”上的匹配比“School”提升更多,您可以按如下方式修改查询:

    curl -XPOST "http://localhost:9200/test_index/_search" -d'
    {
       "query": {
          "bool": {
             "must": [
                {
                   "prefix": {
                      "user": "john"
                   }
                }
             ],
             "should": [
                {
                   "match": {
                      "School": {
                          "query": "DDD",
                          "boost":1
                      }
                   }
                },
                {
                   "match": {
                      "College": {
                          "query": "BBB",
                          "boost":2
                      }
                   }
                }
             ]
          }
       }
    }'
    

    然后结果集如下:

    {
       "took": 4,
       "timed_out": false,
       "_shards": {
          "total": 2,
          "successful": 2,
          "failed": 0
       },
       "hits": {
          "total": 3,
          "max_score": 0.49520478,
          "hits": [
             {
                "_index": "test_index",
                "_type": "docs",
                "_id": "1",
                "_score": 0.49520478,
                "_source": {
                   "user": "John Doe",
                   "School": "AAA",
                   "College": "BBB"
                }
             },
             {
                "_index": "test_index",
                "_type": "docs",
                "_id": "2",
                "_score": 0.36333188,
                "_source": {
                   "user": "Johnathan",
                   "School": "DDD",
                   "College": "AAA"
                }
             },
             {
                "_index": "test_index",
                "_type": "docs",
                "_id": "4",
                "_score": 0.09083297,
                "_source": {
                   "user": "Johnson",
                   "School": "AAA",
                   "College": "EEE"
                }
             }
          ]
       }
    }
    

    您可能需要稍微调整一下数字才能得到您想要的结果。希望有帮助! :)

    【讨论】:

    • 好的,让我看看这个斯隆。我会让你知道。谢谢你这么好的支持。非常感谢。
    • 您所说的布尔查询不起作用并给出空结果。我们更改了一些映射和数据。它现在不工作。我正在提供我的查询和相关数据的映射。如果可能,请检查。
    • 我们想念你@Sloan Ahrens,请帮助我们。
    • 我们已经用最新数据更新了我们的问题,请查看@Sloan Alrens
    【解决方案4】:

    让我们看看查看我的所有步骤是否有助于您找出问题所在。

    如果存在则先删除索引,重新开始:

    curl -XDELETE "http://localhost:9200/test_index"
    

    然后创建它:

    curl -XPUT "http://localhost:9200/test_index/"
    

    然后为“用户”创建映射:

    curl -XPUT "http://localhost:9200/test_index/users/_mapping" -d'
    {
      "users":
      {
        "_all" : {"enabled" : false},
        "properties":
        {
            "user": 
            {
               "type":"multi_field",
               "fields":
               {
                  "user":{"type":"string"},
                  "original":{"type":"string","index":"not_analyzed"}
               }
            },
            "school":{"type":"string","index": "not_analyzed"},
            "college":{"type":"string","index":"not_analyzed"},
            "uni":{"type":"string","index":"not_analyzed"}
        }
      }
    }'
    

    并检查以确保它有效:

    curl -XGET "http://localhost:9200/test_index/users/_mapping"
    ...
    {
       "users": {
          "_all": {
             "enabled": false
          },
          "properties": {
             "college": {
                "type": "string",
                "index": "not_analyzed",
                "omit_norms": true,
                "index_options": "docs"
             },
             "school": {
                "type": "string",
                "index": "not_analyzed",
                "omit_norms": true,
                "index_options": "docs"
             },
             "uni": {
                "type": "string",
                "index": "not_analyzed",
                "omit_norms": true,
                "index_options": "docs"
             },
             "user": {
                "type": "multi_field",
                "fields": {
                   "user": {
                      "type": "string"
                   },
                   "original": {
                      "type": "string",
                      "index": "not_analyzed",
                      "omit_norms": true,
                      "index_options": "docs",
                      "include_in_all": false
                   }
                }
             }
          }
       }
    }
    

    然后添加文档:

    curl -XPUT "http://localhost:9200/test_index/users/1" -d'
    {
      "user": "Abdul Jabbar",
      "school": "Aisha Bawany Academy",
      "college": "Pakistan Air Force",
      "uni": "Aptech Computer Education"
    }'
    curl -XPUT "http://localhost:9200/test_index/users/2" -d'
    {
      "user": "Abdul Jabbar WebBestow",
      "school": "Sadaya Academy",
      "college": "Pakistan Air Force",
      "uni": "WebBestow"
    }'
    curl -XPUT "http://localhost:9200/test_index/users/3" -d'
    {
      "user":"Abdul Jabbar Leopard",
      "school":"Innocent Public School",
      "college":"Lucene College of Science",
      "uni":"IBM"
    }'
    curl -XPUT "http://localhost:9200/test_index/users/4" -d'
    {
      "user":"Abdul Jabbar Loharwada",
      "school":"Aisha Bawany Academy",
      "college":"Behria College",
      "uni":"Karachi University"
    }'
    curl -XPUT "http://localhost:9200/test_index/users/5" -d'
    {
      "user":"Abdul Raheem Loharwada",
      "school":"Aisha Bawany Academy",
      "college":"Indus College",
      "uni":"Preston University"
    }'
    

    运行查询:

    curl -XPOST "http://localhost:9200/test_index/_search" -d'
    {
       "query": {
          "bool": {
             "must": [
                {
                   "prefix": {
                      "user": "jabb"
                   }
                }
             ],
             "should": [
                {
                   "multi_match": {
                      "query": "Aisha Bawany Academy",
                      "fields": ["school", "college", "uni"]
                   }
                },
                {
                   "multi_match": {
                      "query": "Pakistan Air Force",
                      "fields": ["school", "college", "uni"]
                   }
                },
                {
                   "multi_match": {
                      "query": "Aptech Computer Education",
                      "fields": ["school", "college", "uni"]
                   }
                }
             ]
          }
       }
    }'
    

    结果是:

    {
       "took": 27,
       "timed_out": false,
       "_shards": {
          "total": 2,
          "successful": 2,
          "failed": 0
       },
       "hits": {
          "total": 4,
          "max_score": 1.5784466,
          "hits": [
             {
                "_index": "test_index",
                "_type": "users",
                "_id": "1",
                "_score": 1.5784466,
                "_source": {
                   "user": "Abdul Jabbar",
                   "school": "Aisha Bawany Academy",
                   "college": "Pakistan Air Force",
                   "uni": "Aptech Computer Education"
                }
             },
             {
                "_index": "test_index",
                "_type": "users",
                "_id": "2",
                "_score": 0.32274455,
                "_source": {
                   "user": "Abdul Jabbar WebBestow",
                   "school": "Sadaya Academy",
                   "college": "Pakistan Air Force",
                   "uni": "WebBestow"
                }
             },
             {
                "_index": "test_index",
                "_type": "users",
                "_id": "4",
                "_score": 0.32274455,
                "_source": {
                   "user": "Abdul Jabbar Loharwada",
                   "school": "Aisha Bawany Academy",
                   "college": "Behria College",
                   "uni": "Karachi University"
                }
             },
             {
                "_index": "test_index",
                "_type": "users",
                "_id": "3",
                "_score": 0.06631388,
                "_source": {
                   "user": "Abdul Jabbar Leopard",
                   "school": "Innocent Public School",
                   "college": "Lucene College of Science",
                   "uni": "IBM"
                }
             }
          ]
       }
    

    }

    【讨论】:

    • 斯隆请修改查询,如果我们需要在 2 个字段上添加前缀怎么办?我们对 DSL Query 完全不了解,根本需要完成项目。所以,这就是打扰你的原因。但这是最后一个问题。
    • 我认为您可以在“must”子句中添加另一个前缀查询。
    • 随便什么人。你真是太棒了。感谢您的支持。
    • 好的,太好了。谢谢斯隆。多谢。愿你和你的 Stacksearch 长寿 longgggggggggggggg。阿明。非常感谢。
    • 不客气。如果您需要托管 Elasticsearch,请通过 qbox.io 与我们联系! :)
    猜你喜欢
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    相关资源
    最近更新 更多