Elasticsearch:全文搜索

时间:2019-11-14 13:57:49

标签: elasticsearch full-text-search

我正在尝试在多个字段上使用以下文本“ Gold Cartier watchs”构建Elasticsearch全文搜索查询。

我必须遵循以下规则:首先找到所有“金”文件。从检索“金”文件中,找到所有“卡地亚”文件,并从中找到所有“手表”文件。

这是我的multi_match查询:

{
  "query": {
    "multi_match": {
      "query": "Fred or rose",
      "fields": [
        "name",
        "status",
        "categories.name",
        "brand.name",
        "reference"
      ]
    }
  }
}

有我的地图

{
  "product": {
    "mappings": {
      "product": {
        "dynamic_date_formats": [],
        "properties": {
          "available": {
            "type": "text"
          },
          "brand": {
            "properties": {
              "available": {
                "type": "text"
              },
              "name": {
                "type": "keyword"
              },
              "shopProductBrands": {
                "properties": {
                  "available": {
                    "type": "text"
                  },
                  "priority": {
                    "type": "integer"
                  },
                  "slug": {
                    "type": "keyword"
                  }
                }
              },
              "slug": {
                "type": "keyword"
              }
            }
          },
          "categories": {
            "type": "nested",
            "properties": {
              "available": {
                "type": "text"
              },
              "brand": {
                "properties": {
                  "available": {
                    "type": "text"
                  },
                  "name": {
                    "type": "keyword"
                  },
                  "slug": {
                    "type": "keyword"
                  }
                }
              },
              "name": {
                "type": "keyword"
              },
              "parent": {
                "type": "keyword"
              },
              "slug": {
                "type": "keyword"
              }
            }
          },
          "createdAt": {
            "type": "date",
            "format": "date_time_no_millis"
          },
          "longDescription": {
            "type": "text",
            "analyzer": "french_search"
          },
          "name": {
            "type": "text",
            "boost": 15,
            "fields": {
              "raw": {
                "type": "keyword"
              }
            },
            "analyzer": "french_search"
          },
          "purchasePrice": {
            "type": "double"
          },
          "rawPrice": {
            "type": "double"
          },
          "reference": {
            "type": "keyword",
            "boost": 10
          },
          "shortDescription": {
            "type": "text",
            "boost": 3,
            "analyzer": "french_search"
          },
          "slug": {
            "type": "keyword"
          },
          "status": {
            "type": "text"
          },
          "updatedAt": {
            "type": "date",
            "format": "date_time_no_millis"
          }
        }
      }
    }
  }
}

我的搜索将检索所有组合的“金”,“卡地亚”和“手表”文档。

如何建立符合我的规则的查询?

谢谢

2 个答案:

答案 0 :(得分:0)

我不确定是否有简单的解决方案。我认为最接近的方法是将cross_fields"operator": "and"一起使用,并且仅搜索具有相同分析器的字段。您可以为每个字段添加“ french_search”版本吗?

  

cross_fields将查询字符串分析为各个术语,然后   寻找任何领域中的每一项,好像它们是一个大词   字段。

但是:

  

cross_field类型只能在以术语为中心的模式下用于   具有相同的分析仪。 ...如果有多个组,它们是   结合布尔查询。

所以这个查询:

{
  "query": {
    "multi_match": {
      "type": "cross_fields",
      "query": "gold Cartier watches",
      "fields": [
        "name",
        "status",
        "categories.name",
        "brand.name",
        "reference"
      ]
    }
  }
}

会变成这样:

"query": {
    "bool": {
      "should": [
        {
          "multi_match": {
            "query": "gold Cartier watches",
            "fields": ["name"]
          }
        },
        {
          "multi_match": {
            "query": "gold Cartier watches",
            "fields": ["status"]
          }
        },
        {
          "multi_match": {
            "query": "gold Cartier watches",
            "fields": [
              "categories.name",
              "brand.name",
              "reference"
            ]
          }
        }
      ]
    }
  }

该查询过于宽松,但是添加"operator": "and""minimum_should_match": "100%"太严格了。

这不是很有效,但是您可以执行应用程序端术语解析并构建布尔查询。像这样:

"query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "gold",
            "fields": [
              "name",
              "status",
              ...
              "reference"
            ]
          }
        },
        {
          "multi_match": {
            "query": "Cartier",
            "fields": [
              "name",
              "status",
              ...
              "reference"
            ]
          }
        }
        ...
      ]
    }
  }

答案 1 :(得分:0)

您可以使用此方法 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#_boolean_operators

首选运算符为+(必须存在此术语)和-(不得存在此术语)。所有其他术语都是可选的。例如,此查询:

  

快速棕色+ fox-新闻

声明:

mapAtOriginal :: (a -> a) -> [Int] -> [a] -> [a]
mapAtOriginal fn indices xs =
    let  booleans = booleansFromIndices indices
    in   zipWith  (\x b -> if b  then  (fn x)  else  x)  xs  booleans

还支持熟悉的布尔运算符AND,OR和NOT(也写为&&,||和!),但要注意它们不遵守通常的优先级规则,因此,每当多个运算符一起使用时,都应使用括号。例如,上一个查询可以重写为:

fox must be present
news must not be present
quick and brown are optional — their presence increases the relevance

U还可以对特定术语https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#_boosting

使用提升来权衡结果