Elastic search query scenario - elasticsearch

I am building an application which requires a location based search of hotels.
I have three Main classes
class Hotel {
String name
String latitude
String longitude
}
class HotelResource {
Hotel hotel
String name
}
class HotelResourceAvailability{
HotelResource resource
}
HotelResourceAvailability - holds the availability data of a hotel resource.
The query scenario,
As a user I want to search for all the hotels in a particular location which have at least one hotel resource available
and get the count of available resources for each of the hotels
Note - The hotels matching the location criteria but without any available resource should be filtered out.
I am new to elastic search and finding it difficult to decide on the approach any pointers would be really appreciated.

Three points to get you started:
I would keep your data model as flat as possible - Elasticsearch isn't relational so you can't easily join from one object to another.
Latitude and Longitude can be stored in the geo_point type - you can then use queries to find the nearest matching hotels.
Is Hotel availability based on date? if so I would use nesting or a parent child relationship.

Related

FHIR Appointment search filtered by location and all its partOf locations

FHIR Location resources can have a .partOf property that points to another Location.
Let's say we have locations nested like this. Where each location is partOf the parent Location.
hospital
building
clinic
exam room
Let's say that an Appoinment has an actor that is a Location.
How do I query for appointments at these various levels, if I just have a Location Id.
For example: How do I query for all appointments at the hospital? Or for all appointments at the building, etc.
Also, it could be that the actor Location is an ID at any one of these levels and we don't know which, at the time of the search.
I'd like to be able to query Appointments filtered by whatever the current location hierarchy level it is, and everything below.
I know I can do /Appointment?location=LOCATION_ID and /Appointment?location.partOf=LOCATION_ID
But, is there any way to do both and everything below in the same search request?
If the server you are using supports it, you should be able to use the :below modifier on the location search:
/Appointment?location:below=LOCATION_ID
See http://hl7.org/fhir/search.html#recursive for the documentation.

GraphQL batching with logic

I have the following situation in GraphQL schema:
type User {
id: Float
name: String
cityId: Float
}
type City {
id: Float
country: String
}
On client I need information about User and City. But in order to load City I have to know its id, so I can't just batch these requests. Is it possible to make batch request with logic, so from client I make one request with two queries and maybe add some addition info that when the first request is done take id from it and then make another request.
After that both User and City go to client. It is so to say inner join, so I would like to have one request to load connected data.
I can't change the schema, but I can add libs and so on to client or server.
Thanks.
PS. sorry i have just noticed that you stated that you cannot change
the schema. I will leave it there for future reference, but it cannot
be applied on your problem probably.
i would suggest to rearrange your schema as follows. I do not have enough information if it would satisfy your needs. But i would suggest this.
type User {
id: Float
name: String
city: City
#for this city field there will be additional resolver binded to data loader
}
type City {
id: Float
country: String
}
This way the query will look like as follows
query getUsers {
users {
id
name
city {
id
country
}
}
}
There can be used UserConnection from Relay spec, but let's keep it simple for now.
On server side you will then need to implement two resolvers ... first is request for user list and then resolver for city field. Please note that resolvers have seperate context. In order to avoid N+1 requests problem and batch requests city requests to 1. It would be useful to implement data loader for cities to reduce the number of requests to database. The simple schema would be
User resolver, fetch users and return them in users resolver. CityId
is part of the payload for each use
Because city is second level of selection set you will receive each user in the first argument in the resolver function. You will use countryId to pass it to Countries data loader
Countries data loader will batch requests for each counry together. Data loader will transform the countryIds into country values and return them for each user.
GraphQL server will resolve the whole query and each city will be assigned to each user
This is the best approach that i know to deal with this and will also leads you to better architecture of your schema as you will leverage normalization of your appollo store and in my opinion it is easier to work with this format of the data on frontend as well. I hope that i did not miss something in your post and this information will be useful for you. The whole point is to just nest the country into the user, which leads to N+1 request problem and reduce the performance issue of N+1 problem with data loaders.

Recommended model design for large objects

I have a model structure that looked like this
Country
- City
- User
- Items
In my data I have about 50 countries.
Each country have about 100.000 cities.
Each city have about 10-100 users and each user have about 1-10 items.
I want to query cities and where country is X and return the hole city object with all child objects (user and the user items).
I want to query cities where user is X or users items is X
I want to query users where city is X or item is X
How would you index this data in elastic search?
First I thought that I could use parent child relationships (https://www.elastic.co/guide/en/elasticsearch/guide/2.x/parent-child.html) which lets me perform all the queries but it won't return the child objects right? This means that I would have to perform extra queries to return the children and the children children or I could use inner hits but that would need som manual mapping to the object model...
If I use nested objects I won't be able to query child objects without returning the parent? So I could not perform a query agains users and return a list of matching users? It would return the country and its cities and all the cities users?
How would you model this data? performance of search is much more important the performance of indexing the data.

Is Elasticsearch X-Pack able to return graph vertices across different types?

I have product type data loaded into Elasticsearch containing catalogue_number and name. I also have customer data loaded into Elasticsearch containing name and purchases (where purchases is an array of product numbers).
For example:
CATALOGUE_NUMBER, NAME
518, "Toilet Paper"
388, "Candy Bar"
263, "Carrots"
And, for customers:
NAME, PURCHASES
"Jack", [518, 388]
"John", [263]
"Bill", [263, 518]
Considering the relationship is many to one (i.e. customers purchase many items), am I able to use Kibana to view a graph linking purchases to specific customers, or is this out of scope?
My end goal is to have a graph showing product and customer as vertices and edges showing which products each customer purchases. I am very confused as to whether Elasticsearch is capable, or if I should move to a pure graph database such as Neo4J and Elasticsearch for searching only.
The Graph feature can draw out these connections if they share a common field name - the unique identity of a node is a field name and a term. Terms can be in different indices but as long as they share a common field name they are seen as the same node.
I'm not sure which business problem you are trying to solve (recommendations? Fraud?) but depending on what you are trying to achieve you may want to model things differently.
If you're interested in recommendations and people who-bought-X-also-bought-Y style suggestions then the people are unlikely to be interesting nodes to plot and you can just examine the "purchases" field which will draw out which products significantly co-occur.
For more detailed "forensic" type applications you may want to just have person->product links and not have product->product links in which case you would be forced to create more classical "edge-like" documents with only 2 nodes - a person ID and a product ID.

Elasticsearch custom score function

Lets say I have a the following tables:
products: id, name, latitude and longitude
users: id, name, latitude, longitude
interests: id, name
user_interests: user_id, interest_id
These gets inserted/updated into elasticsearch whenever they are created/edited using model observers.
Now I want to make a custom script/scoring function in elastic search which will return me a matching score when a user is searching for a product. The scoring will be based on distance between users location and product, user interests and product name match etc etc.
Being new to elastic search, whats the right approach of implementing this? Any tutorial, online resources or examples are highly appreciated.
PS: I am using PostgreSQL as a database. I can create a function there called get_match(product_id, user_id) which returns a number (0-100) based on matching criteria and do something like:
//psuedo sql
select p.name, get_match(p.id, u.id) as match
from products p, users u
order by match desc
I want to achieve a similar functionality in elasticsearch if possible.

Resources