简体   繁体   中英

Custom facets using Elastic Search

I have a search page that uses facets. When a user enters terms in the search bar or selects a facet checkbox on the left hand column, this triggers a new search in our Elastic Search index. 在此处输入图片说明

Here is how the facets work. Our query includes an aggregation on each of the facet categories. For example, the aggregation response for the firstname category includes all first names from the result set and the number of times each name appears in the result set. As this is a Vuejs app and the facet data is a responsive variable, the facet then updates with the new list of keys and document counts in parenthesis.

在此处输入图片说明

This is problematic, because a user can only select a single checkbox in each facet. As soon as the user selects a checkbox, the other options disappear because the new result set and aggregation response now are restricted to documents that satisfy the selected checkbox.

I think what I need to do is customize my aggregation, but I can be wrong and there is a simpler or smarter approach. Let me know if that is the case.

I imagine I need to refactor so that when a user selects a checkbox in category foo, the aggregation operates on a different result set that takes into account the search bar term and the checked values in all other categories, but ignores the user's selections in the foo category. How can this be done in Elastic?

A requirement is that selecting a checkbox immediately triggers a new search to update the table and the content of the other facet categories.

Ultimately, I need to implement this with Elastic's high level REST client for JAVA, but even just cURL examples would be helpful.

Here is my current aggregation query...

        for (String colName : colNames) {
        sourceBuilder.aggregation(AggregationBuilders.terms(colName)
                .field(colName + ".keyword"));
    }

If I am understanding your question right, you want your terms aggregation to be independent of search query.

You can use global aggregation for it.

Defines a single bucket of all the documents within the search execution context. This context is defined by the indices and the document types you're searching on, but is not influenced by the search query itself

Example

Mapping:

{
  "index50" : {
    "mappings" : {
      "properties" : {
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }

Data:

 "hits" : [
      {
        "_index" : "index50",
        "_type" : "_doc",
        "_id" : "v8MR3XABAqtoal9HOsoo",
        "_score" : 1.0,
        "_source" : {
          "name" : "john"
        }
      },
      {
        "_index" : "index50",
        "_type" : "_doc",
        "_id" : "wMMR3XABAqtoal9HU8rs",
        "_score" : 1.0,
        "_source" : {
          "name" : "doe"
        }
      }
    ]

Query:

{
  "query": {
    "match": {
      "name": "john"
    }
  },
  "aggs": {
    "name_global_faucet": {
      "global": {},--> will return terms from all documents
      "aggs": {
        "first_name": {
          "terms": {
            "field": "name.keyword",
            "size": 10
          }
        }
      }
    },
    "name_faucet": {
      "terms": {--> will return terms from documents returned in query
        "field": "name.keyword",
        "size": 10
      }
    }
  }
}

Result:

  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.6931472,
    "hits" : [
      {
        "_index" : "index50",
        "_type" : "_doc",
        "_id" : "v8MR3XABAqtoal9HOsoo",
        "_score" : 0.6931472,
        "_source" : {
          "name" : "john"
        }
      }
    ]
  },
  "aggregations" : {
    "name_faucet" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "john",
          "doc_count" : 1
        }
      ]
    },
    "name_global_faucet" : {
      "doc_count" : 2,
      "first_name" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 0,
        "buckets" : [
          {
            "key" : "doe",
            "doc_count" : 1
          },
          {
            "key" : "john",
            "doc_count" : 1
          }
        ]
      }
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM