We have an index of Users e.g.
{
"name": "Eli",
"cars": [
{ "model": "Honda", "color": "Red" },
{ "model": "Honda", "color": "Blue" },
{ "model": "Toyota", "color": "Red" }
]
}
{
"name": "Don",
"cars": [
{ "model": "Honda", "color": "Blue" },
{ "model": "Honda", "color": "Black" },
{ "model": "Toyota", "color": "Red" }
]
}
We are trying to retrieve all the users with a Red Honda, but we couldn't find a way to do it in ElasticSearch
Since i dont know which elasticsearch version you are using, i'm referencing to the current.
What you are looking at is the following:
https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-objects.html
and
https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-mapping.html
and
https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-query.html
with the nested mapping you can create a query like the following:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "cars",
"query": {
"bool": {
"must": [
{
"term": {
"cars.model": "honda"
}
},
{
"term": {
"cars.color": "red"
}
}
]
}
}
}
}
]
}
}
}
link to example: https://www.found.no/play/gist/91c5a6c8c9fe81928b1cc497f8740a3f
(click run)
Be aware, this is only working when you are working with nested objects! The mapping must know this.
Related
I have 2 collections in mongodb
Clothes and Colors
Clothes:
[
{ "name": "t-shirt" },
{ "name": "pants" }
]
Colors:
[
{ "color": "yellow" },
{ "color": "red" }
]
I want to have multiply of 2 collections in result
[
{ "name": "t-shirt", "color": "red" },
{ "name": "t-shirt", "color": "yellow" },
{ "name": "pants", "color": "red" },
{ "name": "pants", "color": "yellow" }
]
How can I do this? Thx!
Query
lookup without any criteria (all with all)
unwind
project to fix the structure to get the expected output
Playmongo
clothes.aggregate(
[{"$lookup": {"from": "Colors", "pipeline": [], "as": "results"}},
{"$unwind": "$results"},
{"$project": {"_id": 0, "name": 1, "color": "$results.color"}}])
I want to find duplicate values and if there are duplicate values then I sort based on the last update, so what I take is the newest one, how do I do aggregations? I've tried this aggregation.
I've tried adding sort to sources but it still doesn't work, I've tried several ways but it still fails sometimes it comes out 1 but only old data, sometimes the order is correct from the newest but appears 2 data
{
"size": 0,
"query": {
"bool": {
"must": [
{
"match": {
"BILLING_TYPE_CD": "Service Bundle"
}
},
{
"match": {
"ID": "xxxx"
}
},
{
"exists": {
"field": "LI_MILESTONE"
}
},
{
"exists": {
"field": "LI_SID"
}
},
{
"query_string": {
"default_field": "LI_SID",
"query": "*xxxx*"
}
}
],
"must_not": {
"bool": {
"must": [
{
"query_string": {
"default_field": "LI_PRODUCT_NAME",
"query": "*Network*"
}
},
{
"terms": {
"LI_MILESTONE.keyword": [
"Abandoned",
"Cancelled"
]
}
},
{
"terms": {
"ORDER_STATUS.keyword": [
"Abandoned",
"Cancelled",
"Drop In Progress"
]
}
},
{
"term": {
"STATUS.keyword": ""
}
}
]
}
}
}
},
"sort": [
{
"TGL_CREATED": {
"order": "desc"
}
}
],
"aggs": {
"list_products": {
"composite": {
"size": 50000,
"sources": [
{
"LI_SID": {
"terms": {
"field": "LI_SID.keyword",
"order": "desc"
}
}
}
]
},
"aggs": {
"totalService": {
"terms": {
"field": "LI_SID.keyword",
"size": 50000,
"order": {
"_term": "asc"
}
}
},
"bucket_sort": {
"bucket_sort": {
"from": 0,
"size": 10
}
},
"includes_source": {
"top_hits": {
"size": 1,
"_source": {
"includes": [
"LAST_UPDATE",
"xxxxx",
"xxxxx",
"xxxxx",
"xxx"
]
}
}
}
}
},
"term_product": {
"terms": {
"field": "LI_SID.keyword",
"size": 50000
}
}
}
}
Like this ?
{
"aggs": {
"LI_SID": {
"terms": {
"field": "LI_SID.keyword",
"size": 10
},
"aggs": {
"hit": {
"top_hits": {
"size": 1,
"sort": [
{
"LAST_UPDATE": "desc"
}
]
}
}
}
}
},
"size": 0
}
You need to use aggregations response not hits
I was implementing fuzzy search in my existing elasticsearch where I can't change mappings, I was hoping if there is any way I can convert the following query in fuzzy one i.e add fuzzy search on fields lower_name and album
{
"query": {
"bool": {
"must": [
{
"term": {
"user": "userId"
}
},
{
"bool": {
"should": [
{
"terms": {
"lower_name": ["search", "Text"]
}
},
{
"terms": {
"album": ["search","Text"]
}
}
]
}
}
]
}
}
}
I tried this :
{
"query": {
"bool": {
"must": [
{
"term": {
"user": "userId"
}
},
{
"bool": {
"should": [
{
"fuzzy": {
"lower_name": ["search","Text"]
}
},
{
"fuzzy": {
"album": ["search","Text"]
}
}
]
}
}
]
}
}
}
But this is giving error: [fuzzy] query doesn't support multiple fields
Please help!
Using Elasticsearch 6.3
You can use a multi_match query with fuzziness. Try out the below query
Index Data:
{
"user": "ben",
"lower_name": "def",
"album": "Brenda"
}
{
"user": "ben",
"lower_name": "abc",
"album": "Brenda"
},
{
"user": "ben",
"lower_name": "fgh",
"album": "honda"
}
Search Query:
{
"query": {
"bool": {
"must": [
{
"term": {
"user": "ben"
}
},
{
"bool": {
"should": [
{
"multi_match": {
"query": "abc dey",
"fields": [
"lower_name"
],
"fuzziness": "auto"
}
},
{
"multi_match": {
"query": "brenda",
"fields": [
"album"
],
"fuzziness": "auto"
}
}
]
}
}
]
}
}
}
Search Result:
"hits": [
{
"_index": "66311552",
"_type": "_doc",
"_id": "2",
"_score": 0.7497801,
"_source": {
"user": "ben",
"lower_name": "def",
"album": "Brenda"
}
},
{
"_index": "66311552",
"_type": "_doc",
"_id": "1",
"_score": 0.7497801,
"_source": {
"user": "ben",
"lower_name": "abc",
"album": "Brenda"
}
}
]
You can easily use the "fuzziness": "AUTO". param in your search query. Refer fuzziness in match query official example
Desired Behavior:
Delete a property from each object in an array of objects in all documents in a collection.
What I've Tried:
The docs show $unset is used for deleting object properties:
db.products.update(
{ sku: "unknown" },
{ $unset: { quantity: "", instock: "" } }
)
Another post gives an example of how to delete a nested property in multiple documents:
db.collectionName.update(
{ },
{ "$unset": { "values.727920": "" } },
{ "multi":true }
)
Source: https://stackoverflow.com/a/31384375
I had a look at:
https://docs.mongodb.com/manual/reference/operator/update/positional-all/
https://docs.mongodb.com/manual/reference/operator/update/positional-all/#positional-update-all
which gave the example:
db.students.update(
{ },
{ $inc: { "grades.$[]": 10 } },
{ multi: true }
)
So I tried the following and it seems to work:
db.my_collection.update(
{ },
{ "$unset" : { "array_of_objects.$[].weight": "" } },
{ "multi" : true }
)
Question:
Is this the correct way to:
delete each weight property in each object in array_of_objects in
all documents
Schema:
{
"_id": ObjectId("5d1d85aa00341124bc90d158"),
"title": "hello 01",
"array_of_objects": [
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
},
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
},
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
}]
},
{
"_id": ObjectId("5d1d85aa11341124bc90d158"),
"title": "hello 02",
"array_of_objects": [
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
},
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
},
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
}]
},
{
"_id": ObjectId("5d1d85aa22341124bc90d158"),
"title": "hello 03",
"array_of_objects": [
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
},
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
},
{
"color": "blue",
"weight": "100",
"date": "2019-07-04T11:12:59.356Z"
}]
}
We have an index of Users with Cars e.g.
{
"name": "Eli",
"cars": {
"Honda": { "color": "Red", "Price": 120 },
"Toyota":{ "color": "Blue", "Price": 110 }
"Mazda": { "color": "White", "Price": 100 }
}
}
{
"name": "Eli",
"cars": {
"Honda": { "color": "Blue", "Price": 110 },
"BMW": { "color": "Red", "Price": 200 }
}
}
We are trying to retrieve all the users with a Red Car.
cars.*.color = "Red"
But we couldn't find a way to do it in ElasticSearch.
You can do it with a query_string query like this:
POST index/_search
{
"query": {
"query_string": {
"query": "cars.\\*.color:Red"
}
}
}