1

I have 2 indexes, one that stores data about an event and one that stores the availability of that event. I am trying to create a single query that gets events by a query but only returns ones that are available, and I am having difficulty doing so.

The events index stores

{
  "id" : "152ce52d-e975-4ebd-849a-0a12f535e644",
  "createdAt" : 1.5519999143126902E12,
  "description" : "A very not so concise description",
  "geoHash" : "dnh00x6x5",
  "name" : "a name",
  ...etc...
}

The availability index stores availability like so:

{
  "eventId" : "152ce52d-e975-4ebd-849a-0a12f535e644",
  "maxGuests" : 8,
  "availability" : {
    "lte" : "2019-10-18T22:15:00.000Z",
    "gte" : "2019-10-18T02:30:00.000Z"
  }
}

I am trying to create a query like below, but what I can't figure out is how to filter by listings that meet the criteria in the events index AND are available in the availability index.

GET events,availability/_search
{
  "size": 5,
  "from": 0,
  "_source": [
      "id"
  ],
  "query": {
    "bool": {
      "must": [
        {
          "geo_distance": {
            "distance": "25mi",
            "geoHash": {
              "lat": 34.0389,
              "lon": -84.3826
            }
          }
        }
      ],
      "should": [],
      "filter":[               
        {
          "range" : {
            "availability" : { 
              "gte" : "2019-10-31",
              "lte" : "2020-11-01",
              "relation" : "within" 
            }
          }
        }
      ]
    }
  }
}

--

The reason I want to only do one query is that the client is expecting a certain specified number of events. If I filter out the unavailable events after I get the event data then I am likely to be left with fewer events than the client expected and would need to do yet another search to fill the gap.

Also, of course, I could merge the two indices so that the event also stores the availability info, but I originally set them up this way because the availability info may have hundreds or thousands of entries per event.

1 Answer 1

1

What you want to accomplish is an equivalent of a foreign key of SQL (join). There is no way to have exactly what you want, meaning to filter documents from index A by querying an index B. Your options are:

  1. As you've mentioned solve it on application level (although this causes other problems for you, so it's not a solution).
  2. Merge the data in one index and have duplicated event informatin. Although it seems expensive, the duplication of data in a NoSQL database is to be expected. If you need a relational model then maybe you should use a SQL solution.
  3. Use parent/child (join datatype). The problem here is that you will need to have the data in the same index overall. Moreover, parent and child will be stored in the same shard as well.

One approach to this (a bit more complex though) that I believe would work for you is to use the nested datatype, which actually is a more compact approach for the solution number 2 (combine your data in one index, but save root information only once). Make events be at the root and availability appear as nested. When you want to add one availability you can use the update api, and when you query, you can search by the root fields and by the nested. If you need to retrieve specific availability entries for an event you can use inner hits

What you are trying to do (multi-index search) will not join your data automatically, it will not work. Elasticsearch doesn't work that way, and the relational model is not suited for this product.

One last thing, it's a good thing to plan ahead, but it's a bad thing to try to optimize early on.

The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.

An interesting read that summarizes the above

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.