Skip to content
This repository has been archived by the owner on Jun 30, 2018. It is now read-only.

Nested documents boolean query doubt/problem #749

Closed
miguelm opened this issue Jun 6, 2013 · 6 comments
Closed

Nested documents boolean query doubt/problem #749

miguelm opened this issue Jun 6, 2013 · 6 comments
Labels

Comments

@miguelm
Copy link

miguelm commented Jun 6, 2013

Hi,

Sorry if this is the wrong place to post this, but i have searched for a while in other issues and documentation and didn't find the answer to my problem.

I'm using mongoid and i have a base class Venue:

class Venue
  include Mongoid::Document
  include Mongoid::Timestamps
  include Tire::Model::Search
  include Tire::Model::Callbacks

  # alot of fields
  field :name, type: String

  embeds_many :weekdays, :cascade_callbacks => true
  accepts_nested_attributes_for :weekdays, :allow_destroy => true

   mapping do
     indexes :weekdays do
       indexes :type, :type => "string"
       indexes :hours, :type => "string", :analyzer => 'keyword'
     end
   end

And my embedded document Weekday:

class Weekday
  include Mongoid::Document
  include Mongoid::Timestamps

  embedded_in :venue

  field :type
  field :hours, type: Array
end

In the hours field of my Weekday embedded documents i have an array with data like this:

["10:00", "11:00,"12:00", "12:30","14:30"]

What i'm trying to accomplish here is obtaining Venue documents given a specific type of weekday and between a range of hours.

I.e. I want documents with weekdays.type = 1 and an hours between 11:00 and 12:00.

For that i'v built this query:

tire.search do
  query do
   boolean do
       must { string "weekdays.type:1 AND weekdays.hours:[11\:00 TO 12\:00]" }
   end
  end
end

Unfortunately every-time all documents are returned, perhaps because there is weekdays with other type where the array has the 11:00 to 12:00 or even because since i'm trying to do a lexicographical comparison something might get borked (also used the \ to try to escape the : special character but also tested without it and same problem, even tried to change my model to have an integer 1100 instead of a string "11:00" but had the same problem).

So my question is, in this scenario what would be the best way to accomplish a query similar to this? and what am i doing wrong?

Thank you for your attention!

@karmi
Copy link
Owner

karmi commented Jun 6, 2013

Hi, for solving this "cross matching" issue, you need to use the special nested type in Elasticsearch.

See:

Ping me back with more questions if you need.

(Also, better use the match query instead of the error-prone query_string query...)

@miguelm
Copy link
Author

miguelm commented Jun 6, 2013

You are awesome!

After i did your links i did another mapping structure like this:

mapping do
  indexes :weekdays, :type => "nested" do 
    indexes :type, :type => "string"
    indexes :hours, :type => "string", :analyzer => 'keyword'
  end
end

and a query construction like in your nested query test:

    s = Tire.search @index.name do
      query do
        boolean do
          must do
            match 'name', 'Duck'
          end
          must do
            nested path: 'weekdays' do
              query do
                boolean do
                  must { match 'weekdays.type',  '0' }
                  must { range 'weekdays.hours', { gt: "12:00" }}
                end
              end
            end
          end
        end
      end
    end

It all worked out.

Another last question if i may, since i will be returning an array a set of Venue results something similar to this:

<Item (Venue) _id: "xxxid", name: "xxx", weekdays: [<Item _id: "anotherid", type: 0, hours: ["14:30", "15:00"]>,<Item _id: "anotherid", type: 1, hours: ["14:30", "15:00"]>]>

With this result i only want to retrieve the items of weekdays that match my boolean query (type = 0) is that possible?

Since it's a nested document ideally i could do something like this:

 s.results.first.weekdays 

Where the only weekdays items are there are the ones who match type = 0
Is it possible without having to write the code to iterate over all the weekdays?

Let me know if i didn't explain myself properly.

Once again awesome tips and love your work!

@karmi
Copy link
Owner

karmi commented Jun 6, 2013

Hi, thanks, you're very welcome :)

I know what you're after -- but Elasticsearch will return the whole document _source , so unfortunately you have to iterate over the venue.weekdays yourself to display just the matching ones...

@karmi
Copy link
Owner

karmi commented Jun 6, 2013

@miguelm It's on the Elasticsearch roadmap though to return matching nested documents, elastic/elasticsearch#3022

@miguelm
Copy link
Author

miguelm commented Jun 6, 2013

Nice catch, will follow up that issue elastic/elasticsearch#3022

For now i will do a venue.weekdays.select{...} over it and extract the values.

The most difficult part is solved, do you want to keep this issue as it links to the elastic search issue or should i close it so it doesn't take up more space on your backlog?

Once again thank you very much and hope i can repay it sometime in the future :)

@karmi
Copy link
Owner

karmi commented Jun 7, 2013

@miguelm I think we can close it here. Thanks!

@karmi karmi closed this as completed Jun 7, 2013
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants