ruby-on-railsrubyelasticsearchsearchkick

Searching postgresql arrays with searchkick


I have a search functionality that I would like to search by various fields. I am already using multi_search to look for different records from different models.

    @entries_result = Post.search(params[:q].presence || '*',
      fields: ['title^10', 'content', 'rating', 'parent_id', 'tags'],
      ...
      where: { parent_id: @parent.id },
      limit: 3)

    @categories_result = Category.search(params[:q].presence || '*', ...)

    @tags_result = Post.search(params[:q].presence || '*',
      fields: ['tags'],
      match: :word_start,
      highlight: true,
      misspellings: { below: 3 },
      where: { parent_id: @parent.id, tags: params[:q] })

    Searchkick.multi_search([@categories_result, @entries_result, @tags_result])

    @tags_result.map(:&tags)

As you can see I am searching through Post model twice, as I need

  1. Posts with specific name(shown on top of the search results)
  2. Tags which are an Array in psql, that I will be showing on the side of the search results
#  tags :text default([]), is an Array, indexed

I can't figure out how to find these tags that are a result of searching by params[:q]. I know that Elasticsearch can search these arrays in documents, but I couldn't find any info on how to do this with searchkick gem. For example when params[:q] is dog I'd like to search for Posts that start with the keyword dog and also tags that start with keyword dog.

Rails 7, gems opensearch (2.0.0), searchkick (5.0.3)


Solution

  • I ended up building an advanced query as it's also possible to just use elasticsearch/opensearch queries in searchkick, and below code works fine for me.

        @tags_result = Post.search(body:
          { query: {
            bool: {
              should: [
                prefix: {
                  tags: params[:q].presence || '*',
                },
              ],
              filter: {
                term: {
                  parent_id: @parent.id,
                },
              },
            },
          } })