问题
When adding a term to my query instead of a filter I am getting 0 facets. FYI I am using the tire gem with Ruby.
Here is my model code with its mapping:
class Property < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
has_and_belongs_to_many :tags
mapping do
indexes :id, type: 'integer'
indexes :status
indexes :refno, type: 'integer'
indexes :name, :analyzer => 'snowball', :boost => 100
indexes :description
indexes :tags, type: 'object',
properties: {
name: { type: 'multi_field',
fields: {
name: { type: 'string', analyzer: 'snowball' },
exact: { type: 'string', index: 'not_analyzed' }
}
}
}
end
def to_indexed_json
to_json( include: {
tags: { only: [:name] },
})
end
Then here is the search method
def self.search(params={})
tire.search(page: params[:page], per_page: 2, load: true) do
query do
boolean do
must { string params[:name], default_operator: "AND" } if params[:name].present?
must { term :status, 'live' }
must { term :refno, params[:refno]} if params[:refno].present?
# must { term :tag, params[:tag]} if params[:tag].present? ## does not work either
must { term 'tags.name.exact', params[:tag]} if params[:tag].present?
end
end
facet "tags" do
terms 'tags.name.exact'
end
raise to_json
# raise to_curl
end
end
I get 0 Facets. But if I move facets to a filter ie below I get full facets.
def self.search(params={})
tire.search(page: params[:page], per_page: 2, load: true) do
query do
boolean do
must { string params[:name], default_operator: "AND" } if params[:name].present?
must { term :status, 'live' }
must { term :refno, params[:refno]} if params[:refno].present?
end
end
filter :term, 'tags.name.exact' => params[:tag] if params[:tag].present?
facet "tags" do
terms 'tags.name.exact'
end
raise to_json
# raise to_curl
end
end
While this is ok it's not want, When a facet filter is clicked I want to remove non available tags from my facet filter and update the new facet count.
If it helps here is the json for the query which works and does not.
## No Factes
{
"query":{
"bool":{
"must":[
{
"query_string":{
"query":"England",
"default_operator":"AND"
}
},
{
"term":{
"status":"live"
}
},
{
"term":{
"tags.name.exact":[
"Pet Friendly"
]
}
}
]
}
},
"facets":{
"tags":{
"terms":{
"field":"tags.name.exact",
"size":10,
"all_terms":false
}
}
},
"size":2
}
## Facets working
{
"query":{
"bool":{
"must":[
{
"query_string":{
"query":"England",
"default_operator":"AND"
}
},
{
"term":{
"status":"live"
}
}
]
}
},
"facets":{
"tags":{
"terms":{
"field":"tags.name.exact",
"size":10,
"all_terms":false
}
}
},
"filter":{
"term":{
"tags.name.exact":[
"Pet Friendly"
]
}
},
"size":2
}
Really hope someone can advise. Starting to pull my hair out on this one.
回答1:
You should use filtered query for facet seach to get exact result:
query do
filtered do
query { <search keywords> }
filter <your filter> (pass in facet values)
end
end
<facet>
...
<facet>
回答2:
I was actually very close. As my tags can have multiple I needed to use terms not term ie,
def self.search(params={})
tire.search(page: params[:page], per_page: 2, load: true) do
query do
boolean do
must { string params[:name], default_operator: "AND" } if
must { term :status, 'live' }
must { term :refno, params[:refno]} if params[:refno].present?
must { terms 'tags.name.exact', params[:tag]} if params[:tag].present?
end
end
facet "tags" do
terms 'tags.name.exact'
end
# raise to_json
# raise to_curl
end
end
Thank you for your advise though imotov, Hoang.
回答3:
A search request usually consists of two parts: a query and a filter. If a search request contains only a query part, facets are calculated based on the complete search result. In other words if a search result contains 10 records with the tag "Pet Friendly" and 5 records with the tag "No Pets Allowed", the facet response will contain two facets: "Pet Friendly" and "No Pets Allowed". Now let's assume a user limits results by selecting the "Pet Friendly" tag. If the "Pet Friendly" clause is added to the query part of the request, the search result will be limited to 10 records with the "Pet Friendly" tag, and only one facet will be returned: "Pet Friendly". However, if the "Pet Friendly" clause is added as a filter, the search result will be still limited to 10 records, but two facets will be returned. It happens because facets are calculated based only on the query portion of the search request and query portion didn't change - it still produces search results with 15 records with two different facets.
To answer your question, if a query returns no results (for example, user selected both "Pet Friendly" and "No Pets Allowed" tags) then results have no facets in them, so no facets are returned.
来源:https://stackoverflow.com/questions/9895941/facet-troubles-with-elasticsearch-on-query