简体   繁体   中英

Having trouble with mixed complex boolean with Tire (and ElasticSearch)

I've been trying to figure out how to do mixed boolean searches that use nested objects using Tire. All the simple examples I've found don't include a more complex query (when searching on other attributes).

My search involves finding a Team that 'needs' a specific type of person. When trying to build a football team, the team needs to fill the roster with certain types of players of a given weight class, with the option of excluding one term or the other.

Other parameters such as 'region' or 'kind' have to do with where the team plays, and what kind of team (casual, competitive, etc) it is.

My current setup:

mapping do
  indexes :region, index: :not_analyzed
  indexes :kind, index: :not_analyzed

  indexes :role_requirements do
    indexes :need, type: 'boolean'
    indexes :weight_class_id, type: 'integer'
    indexes :role_id, type: 'integer'
  end

  .
  .
  .

end

def self.search(params)
  team_params = params[:team_search]
  tire.search(page: params[:page], per_page: 10) do
    query do
      boolean do
        must { string team_params[:query], default_operator: "AND" } if team_params[:query].present?
        must { term :kind, team_params[:kind] } if team_params[:kind].present?
        must { term :region, team_params[:region] } if team_params[:region].present?

        if team_params[:weight_class_id].present? || team_params[:role_id].present?
          must { term 'role_requirements.need', true }
        end

        must { term 'role_requirements.weight_class_id', team_params[:job_id].to_i } if team_params[:weight_class_id].present?
        must { term 'role_requirements.role_id', team_params[:role_id].to_i } if team_params[:role_id].present?

        .
        .
        .

      end
    end
  end
end

I've tried a number of ways, but there usually seems to be a problem either with ElasticSearch not able to parse things or Tire not having the method within the scope:

With this implementation, here is the generated to_json: https://gist.github.com/8a615e701eb31ff2e250

Which are currently not giving me any results.

All the different ways I've tried: https://gist.github.com/907c9571caa0e87bad27

None are really able to give me full results.

You seem to be missing the nested type in the mapping:

mapping do
  indexes :region, index: :not_analyzed
  indexes :kind,   index: :not_analyzed

  indexes :role_requirements, type: 'nested' do
    indexes :need,            type: 'boolean'
    indexes :weight_class_id, type: 'integer'
    indexes :role_id,         type: 'integer'
  end

  # ..more mappings..

end

Then you can build your query like this:

tire.search(page: params[:page], per_page: 10) do
  query do
    boolean do
      must { string team_params[:query], default_operator: "AND" } if team_params[:query].present?
      must { term :kind, team_params[:kind] } if team_params[:kind].present?
      must { term :region, team_params[:region] } if team_params[:region].present?

      must do
        nested path: 'role_requirements' do
          query do
            boolean do
              if team_params[:weight_class_id].present? || team_params[:role_id].present?
                must { term 'role_requirements.need', true }
              end
              must { term 'role_requirements.weight_class_id', team_params[:job_id].to_i } if team_params[:weight_class_id].present?
              must { term 'role_requirements.role_id', team_params[:role_id].to_i } if team_params[:role_id].present?
            end
          end
        end
      end
    end
  end
end

Here are some examples in Tire's integration tests .

Hope this helps :)

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