Elasticsearch filter selection date

This is how my data looks like

{
  "name": "thename",
  "openingTimes": {
    "monday": [
      {
        "start": "10:00",
        "end": "14:00"
      },
      {
        "start": "19:00",
        "end": "02:30"
      }
    ]
  }
}

      

I want to request this document by saying opened on monday between 13:00 and 14:00

.
I tried this filter but it doesn't return my document:

{
  "filter": {
    "range": {
      "openingTimes.monday.start": {
        "lte": "13:00"
      },
      "openingTimes.monday.end": {
        "gte": "14:00"
      }
    }
  }
}

      

If I just say opened on monday at 13:00

it works:

{
  "filter": {
    "range": {
      "openingTimes.monday.start": {
        "lte": "13:00"
      }
    }
  }
}

      

Or even closing on monday from 14:00

, it works too:

{
  "filter": {
    "range": {
      "openingTimes.monday.start": {
        "gte": "14:00"
      }
    }
  }
}

      

but combining both of them gives me nothing. How can I create a filter that means opened on monday between 13:00 and 14:00

?

EDIT

This is how I mapped the field openingTime

{
  "properties": {
    "monday": {
      "type": "nested",
      "properties": {
        "start": {"type": "date","format": "hour_minute"},
        "end": {"type": "date","format": "hour_minute"}
      }
    }
  }
}

      

SOLUTION (@DanTuffery)

Building on @ DanTuffery's answer, I changed my filter to his (which works great) and added a type definition for my attribute openingTime

.

For the record, I am using elasticsearch as my main db via Ruby-on-Rails using the following stones:

gem 'elasticsearch-rails', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
gem 'elasticsearch-model', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
gem 'elasticsearch-persistence', git: 'git://github.com/elasticsearch/elasticsearch-rails.git', require: 'elasticsearch/persistence/model'

      

This is what the openTime attribute mapping looks like:

attribute :openingTimes, Hash,    mapping: {
                                    type: :object,
                                    properties: {
                                      monday:     {
                                        type: :nested,
                                        properties: {
                                          start:{type: :date, format: 'hour_minute'},
                                          end:  {type: :date, format: 'hour_minute'}
                                        }
                                      },
                                      tuesday:     {
                                        type: :nested,
                                        properties: {
                                          start:{type: :date, format: 'hour_minute'},
                                          end:  {type: :date, format: 'hour_minute'}
                                        }
                                      },
                                      ...
                                      ...
                                    }
                                  }

      

And this is how I applied its filter:

def self.openedBetween startTime, endTime, day
  self.search filter: {
                nested: {
                  path: "openingTimes.#{day}",
                  filter: {
                    bool: {
                      must: [
                        {range: {"openingTimes.#{day}.start"=> {lte: startTime}}},
                        {range: {"openingTimes.#{day}.end"  => {gte: endTime}}}
                      ]
                    }
                  }
                }
              }
end

      

+3


source to share


1 answer


First, create a mapping openingTimes

to the top-level object .

/PUT http://localhost:9200/demo/test/_mapping
{
  "test": {
    "properties": {
      "openingTimes": {
        "type": "object",
        "properties": {
          "monday": {
            "type": "nested",
            "properties": {
              "start": {
                "type": "date",
                "format": "hour_minute"
              },
              "end": {
                "type": "date",
                "format": "hour_minute"
              }
            }
          }
        }
      }
    }
  }
}

      

Index of your document



/POST http://localhost:9200/demo/test/1
{
  "name": "thename",
  "openingTimes": {
    "monday": [
      {
        "start": "10:00",
        "end": "14:00"
      },
      {
        "start": "19:00",
        "end": "02:30"
      }
    ]
  }
}

      

With a nested filter query, you can search for a document with fields start

and end

in boolean range queries:

/POST http://localhost:9200/demo/test/_search
{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "nested": {
          "path": "openingTimes.monday",
          "filter": {
            "bool": {
              "must": [
                {
                  "range": {
                    "openingTimes.monday.start": {
                      "lte": "13:00"
                    }
                  }
                },
                {
                  "range": {
                    "openingTimes.monday.end": {
                      "gte": "14:00"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

      

+5


source







All Articles