Search by results of previous search in elasticsearch - elasticsearch

It is possible to make a search by the results of another search?. For example:
// index: A
{ "ID": 1, "status": "done" }
{ "ID": 2, "status": "processing" }
{ "ID": 3, "status": "done" }
{ "ID": 4, "status": "done" }
// index: B
{ "ID": 1, "user": 1, "value": 10 }
{ "ID": 1, "user": 2, "value": 3 }
{ "ID": 2, "user": 1,"value": 1 }
{ "ID": 3, "user": 1, "value": 3 }
{ "ID": 4, "user": 1, "value": 7 }
Q1: Search in index "A" status == "done" and return the ID
RES: 1,3,4
Q2: From the results in Q1 search value > 5 and return the ID
RES: 1,4
My current solution is use two queries and download the results of "Q1" and make a second search in "Q2" but is very complicated because have 30k of results.

the problem to me seems to be more of a traditional union of filters in 2 indexes sort of a join , what we have in relational databases , not sure of the exact solution but recently had used a plug-in for the joins -> https://siren.io/siren-federate-20-0-introducing-a-scalable-inner-join-for-elasticsearch/ this might help

Related

Jooq order by not in jsonArrayArg

The query statement which need to be executed is
dslContext.select(
jsonObject(
key("id").value(ENTITY.ID),
key("name").value(ENTITY.NAME),
key("attributes").value(
coalesce(
select(
jsonArrayAgg(
jsonObject(
key("id").value(ATTRIBUTE.ID),
key("name").value(ATTRIBUTE.NAME),
key("indexValue").value(ATTRIBUTE.INDEX_VALUE)
)
)
).from(ATTRIBUTE)
.where(ATTRIBUTE.ENTITY_ID.eq(ENTITY.ID))
.orderBy(ATTRIBUTE.INDEX_VALUE.asc()),
jsonArray()
)
)
)
).from(ENTITY).fetchInto(EntityDto.class)
Response for the above query:
[
{
"id": 2,
"name": "Address",
"attributes": [
{
"id": 3,
"name": "Pincode",
"indexValue": 4
},
{
"id": 4,
"name": "Country",
"indexValue": 3
},
{
"id": 5,
"name": "City",
"indexValue": 2
},
{
"id": 6,
"name": "Address",
"indexValue": 1
}
]
}
]
The attributes are not sorting in ascending order with respect to indexValue.
How to make the attributes sort in the ascending order?
Use the ORDER BY clause on JSON_ARRAYAGG:
jsonArrayAgg(...).orderBy(...)

ReferenceManyFields (One to Many Relationship)

I am working on a project where I have to create one to many relationships which will get all the list of records referenced by id in another table and I have to display all the selected data in the multi-select field (selectArrayInput). Please help me out in this, if you help with an example that would be great.
Thanks in advance.
Example:
district
id name
1 A
2 B
3 C
block
id district_id name
1 1 ABC
2 1 XYZ
3 2 DEF
I am using https://github.com/Steams/ra-data-hasura-graphql hasura-graphql dataprovider for my application.
You're likely looking for "nested object queries" (see: https://hasura.io/docs/1.0/graphql/manual/queries/nested-object-queries.html#nested-object-queries)
An example...
query MyQuery {
district(where: {id: {_eq: 1}}) {
id
name
blocks {
id
name
}
}
}
result:
{
"data": {
"district": [
{
"id": 1,
"name": "A",
"blocks": [
{
"id": 1,
"name": "ABC"
},
{
"id": 2,
"name": "XYZ"
}
]
}
]
}
}
Or...
query MyQuery2 {
block(where: {district: {name: {_eq: "A"}}}) {
id
name
district {
id
name
}
}
}
result:
{
"data": {
"block": [
{
"id": 1,
"name": "ABC",
"district": {
"id": 1,
"name": "A"
}
},
{
"id": 2,
"name": "XYZ",
"district": {
"id": 1,
"name": "A"
}
}
]
}
}
Setting up the tables this way...
blocks:
districts:
Aside: I recommend using plural table names as they are more standard, "districts" and "blocks"

Elasticsearch Sorting Tiebreakers

Say I am creating a search engine for a photo sharing social network and the documents of the site have the following schema
{
"id": 123456
"name": "Foo",
"num_followers": 123456,
"num_photos": 123456
}
I would like my search results to satisfy the following requirements:
Only have results where the search query strings matches the "name" field in the document
Rank the search results by number of followers descending
In the case where multiple customers have the same number of followers, rank by number of photos descending
For example, say I have the following documents in my index:
{
"id": 1,
"name": "Customer",
"num_followers": 3,
"num_photos": 27
}
{
"id": 2,
"name": "Customer",
"num_followers": 25,
"num_photos": 1
}
{
"id": 3,
"name": "Customer",
"num_followers": 8,
"num_photos": 2
}
{
"id": 4,
"name": "Customer",
"num_followers": 8,
"num_photos": 5
}
{
"id": 5,
"name": "FooBar",
"num_followers": 10000,
"num_photos": 20000
}
If I search "Customer" in the search bar of the site, the ES hits should be in the following order:
{
"id": 2,
"name": "Customer",
"num_followers": 25,
"num_photos": 1
}
{
"id": 4,
"name": "Customer",
"num_followers": 8,
"num_photos": 5
}
{
"id": 3,
"name": "Customer",
"num_followers": 8,
"num_photos": 2
}
{
"id": 1,
"name": "Customer",
"num_followers": 3,
"num_photos": 27
}
I'm assuming I will need to perform some sort of compact query to create this "tiebreaker" logic. What clauses should I be using? If anyone had an example of something similar that would be amazing. Thanks in advance.
This sounds like a pretty standard sorting use case. Elasticsearch can sort on multiple fields in a predefined priority order. See documentation here.
GET /my_index/_search
{
"sort" : [
{ "num_followers" : {"order" : "desc"}},
{ "num_photos" : "desc" }
],
"query" : {
"term" : { "name" : "Customer" }
}
}
Obviously this is just a simple term query -- you may want that to be a keyword search instead based on the wording of your question.

Elasticsearch to return documents based on 2 criteria where one is based on the other

I have documents in the following format:
{
"id": number
"chefId: number
"name": String,
"ingredients": List<String>,
"isSpecial": boolean
}
Here is a list of 5 documents:
{
"id": 1,
"chefId": 1,
"name": "Roasted Potatoes",
"ingredients": ["Potato", "Onion", "Oil", "Salt"],
"isSpecial": false
},
{
"id": 2,
"chefId": 1,
"name": "Dauphinoise potatoes",
"ingredients": ["Potato", "Garlic", "Cream", "Salt"],
"isSpecial": true
},
{
"id": 3,
"chefId": 2,
"name": "Boiled Potatoes",
"ingredients": ["Potato", "Salt"],
"isSpecial": true
},
{
"id": 4,
"chefId": 3
"name": "Mashed Potatoes",
"ingredients": ["Potato", "Butter", "Milk"],
"isSpecial": false
},
{
"id": 5,
"chefId": 4
"name": "Hash Browns",
"ingredients": ["Potato", "Onion", "Egg"],
"isSpecial": false
}
I will be doing a search where "Potatoes" is contained in the name field. Like this:
{
"query": {
"wildcard": {
"status": {
"value": "*Potatoes*"
}
}
}
}
But I also want to add some extra criteria when returning documents:
If the ingredients contain onion or milk, then return the documents. So documents with the id 1 and 4 will be returned. Note that this means that we have documents returned where chef ids are 1 and 3.
Then, for the documents where we haven't already got another document with the same chef id, return where the isSpecial flag is set to true. So only document 3 will be returned. 2 wouldn't be returned as we already have a document where the chef id is equal to one.
Is it possible to do this kind of chaining in Elasticsearch? I would like to be able to do this in a single query so that I can avoid adding logic to my (Java) code.
You can't have that sort of logic in one elasticsearch query. You could have a tricky query with aggregations / post_filter and so to have all the data you need in one query and then transform it in your Java application.
But the best approach (and the more maintainable) is to have two queries.

Partial Update in Eleastic Search Document

I just started exploring the elastic search and I stuck with a requirement in my project. I tried multiple thing but nothing worked for me. I have saved a sample document in elastic search index
"orderData": {
"lines": [
{
"lineNbr": 1,
"quantity": {
"amount": 1,
"uom": "EACH"
},
"weight": null,
"Qty": null
},
{
"lineNbr": 2,
"quantity": {
"amount": 1,
"uom": "EACH"
},
"weight": null,
"Qty": null
}
]
}
Next time I want to update only some of the data in line nbr one but here the problem is I dont want to do fields wise update. I get full Line Nbr 1 json again something like
{
"lineNbr": 1,
"quantity": {
"amount": 10,
"uom": "EACH"
},
"weight": 5,
"Qty": 5
}
But if I am performing update line nbr 2 tag is removed and only line nbr 1 tag is left with the updated data but I never wanted to touch line nbr 2
How can I achieve this? Any help will be appreciated. Thanks In Advance.

Resources