【问题标题】:PHP Elastic Search Filtered Query String SearchPHP Elastic Search 过滤查询字符串搜索
【发布时间】:2016-06-23 12:05:43
【问题描述】:

所有人都希望使用过滤后的查询,其中结果应包含来自“query_string”以及应用的“term - filter”的数据。

GET blog/_search
{
    "query": {
        "filtered": {
            "query": {
                "query_string": {
                    "fields": [ "description" ],
                    "query": "a"                 // or just ""
                }
            },
            "filter": {
                "terms": {
                    "topic_id": [
                        10
                    ]
                }
            }
        }
    }
}

预期结果是:

  1. 所有包含字母“a”或“”且 topic_id 为 10 的博客记录。
  2. 还有 topic_id 为 10 的其余记录,即使描述为空白/空。

所以最终结果应该是 - 得分较高的匹配记录应该排在最前面,然后是与过滤器中的“topic_id”匹配的记录。

【问题讨论】:

  • 当用“a”搜索时,我只得到描述中包含字母“a”的数据,但我也需要topic_id为10的空(“”)描述的数据。同样当用空白(“”)搜索时,没有得到任何数据。但我希望数据的描述为空,topic_id 为 10。
  • 问题中提到了我正在尝试的查询。
  • 这可能是helpful
  • @keety,您提供的链接无济于事,因为我希望根据 query 添加的两个匹配项以及空搜索但使用 topic_id 值的过滤器。我在问题中提到的条件 1。
  • @KunalDethe 检查我的答案。我认为这就是你要找的。希望对你有帮助

标签: php elasticsearch


【解决方案1】:

实现此目的的一种方法是对description 字段使用muti_fields 映射。多字段中的一个字段应该是非分析的。 重新索引数据后,您可以使用简单的bool query 来实现您想要的:

示例

创建索引:

put test
{
    "mappings": {
        "data" : {
            "properties": {
                "description" : {
                    "type": "string",
                     "fields": {
                        "raw" : {"type": "string","index": "not_analyzed"}
                     }
                }
            }   
        }
    }
}

索引数据:

put test/data/1 
{
    "description" : "a",
    "test_id" : 10
}
put test/data/2
{
    "description" : "",
    "test_id" : 10
}

put test/data/3
{
    "description" : "hello",
    "test_id" : 10
}


put test/data/4
{
    "description": "a",
    "test_id" : 20
}

查询:

post test/data/_search
{
   "query": {
      "filtered": {
         "query": {
            "bool": {
               "disable_coord": "true",
               "should": [
                  {
                     "query_string": {
                        "fields": [
                           "description"
                        ],
                        "query": "a"
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "term": {
                              "description.raw": ""
                           }
                        },
                        "boost": 0.2
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "exists": {
                              "field": "description"
                           }
                        },
                        "boost": 0.1
                     }
                  }
               ]
            }
         },
         "filter": {
            "terms": {
               "test_id": [
                  10
               ]
            }
         }
      }
   }
}

结果:

 "hits": [
         {
            "_index": "test",
            "_type": "data",
            "_id": "1",
            "_score": 0.5113713,
            "_source": {
               "description": "a",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "2",
            "_score": 0.29277003,
            "_source": {
               "description": "",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "3",
            "_score": 0.097590014,
            "_source": {
               "description": "hello",
               "test_id": 10
            }
         }
      ]

查询空字符串:

{
   "query": {
      "filtered": {
         "query": {
            "bool": {
               "disable_coord": "true",
               "should": [
                  {
                     "query_string": {
                        "fields": [
                           "description"
                        ],
                        "query": ""
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "term": {
                              "description.raw": ""
                           }
                        },
                        "boost": 0.2
                     }
                  },
                  {
                     "constant_score": {
                        "filter": {
                           "exists": {
                              "field": "description"
                           }
                        },
                        "boost": 0.1
                     }
                  }
               ]
            }
         },
         "filter": {
            "terms": {
               "test_id": [
                  10
               ]
            }
         }
      }
   }
} 

结果:

  "hits": [
         {
            "_index": "test",
            "_type": "data",
            "_id": "2",
            "_score": 1.3416407,
            "_source": {
               "description": "",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "1",
            "_score": 0.44721356,
            "_source": {
               "description": "a",
               "test_id": 10
            }
         },
         {
            "_index": "test",
            "_type": "data",
            "_id": "3",
            "_score": 0.44721356,
            "_source": {
              "description": "hello",
               "test_id": 10
            }
         }
      ]

【讨论】:

  • 让我试试看。
  • @KunalDethe 好奇上面的方法没有按预期工作吗?
  • 当搜索文本为空(“”)时我得到的结果,然后只返回具有空描述的数据。但我也希望返回非空但稍后在结果中。空描述应优先于非空。
  • 只是为了验证,如果您正在搜索“a”,您希望“a”结果后跟空字符串,然后是其余非空和非“a”的文档。同样,如果你在结果中搜索你喜欢的空,然后是非空,那准确吗?
  • 是的,需要完全相同。
【解决方案2】:

您是否考虑过使用wildcard 查询?检查这个查询它会为你工作。

所有包含字母“a”且 topic_id 为 10 的博客记录。

{
  "filter": {
    "and": [
      {
        "in": {
          "topic_id": [
            "10"
          ]
        }
      },
      {
        "query": {
          "filtered": {
            "filter": {
              "bool": {
                "should": [
                  {
                    "query": {
                      "wildcard": {
                        "description": {
                          "value": "*a*"
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ]
  }
}

即使描述为空白/空,topic_id 为 10 的其余记录也是如此。这将返回与通配符不匹配的所有其他记录。

{
  "filter": {
    "and": [
      {
        "in": {
          "topic_id": [
            "10"
          ]
        }
      },
      {
        "not": {
          "query": {
            "filtered": {
              "filter": {
                "bool": {
                  "should": [
                    {
                      "query": {
                        "wildcard": {
                          "description": {
                            "value": "*a*"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    ]
  }
}

仅查找 topic_id 为 10 的空“”描述字段。试试这个,

{
  "filter": {
    "and": [
      {
        "in": {
          "topic_id": [
            "10"
          ]
        }
      },
      {
        "query": {
          "filtered": {
            "filter": {
              "script": {
                "script": "_source.description.length() == 0"
              }
            }
          }
        }
      }
    ]
  }
}

【讨论】:

    【解决方案3】:

    对于 ES 2.x

    使用bool 查询应该可以解决问题。

    这是我将使用的查询:

    GET blog/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "query_string": {
                "fields": [ "description" ],
                  "query": "a"
              }
            }
          ],
          "must": [
            {
              "terms": {
                "topic_id": [
                  10
                ]
              }
            }
          ]
        }
      }
    }
    

    这里,布尔查询的 should 子句将告诉 Elassticsearch 应该返回与 query_string 匹配的文档。在query_string 中,如果要匹配包含a 的任何文档,请考虑使用通配符。 例如"query_string": { "query": "*a*" }

    另一方面,must 子句表明,为了将文档视为有效匹配,它必须在 topic_id 字段中包含 10should 子句是否可以匹配。

    Bool filter

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-17
      • 2021-03-22
      • 2020-08-21
      • 2014-12-03
      • 2015-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多