Related
I need to update a document with an object, but my approach looks like don't apply the changes on DB, can someone explain me what I'm doing wrong, please?
let dishes = await this.dishesModel.find({});
let dishesPromise = dishes.map((dish, i) => {
dish.ingredients.forEach((item) => {
if (item?.item) {
if (item['item']['unit']['_id'].toString() === payload._id) {
item['item']['unit'] = unit;
}
}
});
return dish.save();
});
await Promise.all(dishesPromise)
In the above code I get unit previously and the objective is to use this unit in: item['item']['unit']
A dish document looks like:
{
"_id": { "$oid": "62cc00bfad995c0e7d8bbb7d" },
"name": "Bologne pasta",
"price": 6.99,
"ingredients": [
{
"quantity": 3,
"item": {
"_id": { "$oid": "62cbe92821464145f0eb280e" },
"name": "Cow beef",
"code": "meat-01",
"price": 9.99,
"value": 100,
"internal": true,
"categories": [
{
"_id": { "$oid": "62cbe83221464145f0eb27ea" },
"name": "Meat",
"disabled": false
}
],
"unit": {
"name": "GRAMASO 2",
"abbr": "gr.",
"_id": { "$oid": "62befe5ff6f95cf46a4cfe5b" }
},
"disabled": false,
"__v": 0,
"translation": { "es": { "name": "Carne de vaca" } }
}
},
{
"quantity": 2,
"item": {
"_id": { "$oid": "62cbea3121464145f0eb283a" },
"name": "Tomato",
"code": "vegetable-02",
"price": 1.5,
"value": 20,
"internal": true,
"categories": [
{
"_id": { "$oid": "62cbe82921464145f0eb27e6" },
"name": "Vegetables",
"disabled": false
}
],
"unit": {
"name": "GRAMASO 2",
"abbr": "gr.",
"_id": { "$oid": "62befe5ff6f95cf46a4cfe5b" }
},
"disabled": false,
"__v": 0,
"translation": { "es": { "name": "Tomate" } }
}
},
{
"quantity": 1,
"item": {
"_id": { "$oid": "62cbee5621464145f0eb2865" },
"name": "Spagetti",
"code": "pasta-01",
"price": 1.5,
"value": 100,
"internal": true,
"categories": [
{
"_id": { "$oid": "62cbee3e21464145f0eb285f" },
"name": "Pasta",
"disabled": false
}
],
"unit": {
"name": "GRAMASO 2",
"abbr": "gr.",
"_id": { "$oid": "62befe5ff6f95cf46a4cfe5b" }
},
"disabled": false,
"__v": 0,
"translation": { "es": { "name": "Espaguetti" } }
}
}
],
"categories": [
{
"_id": { "$oid": "62cbe84721464145f0eb27f6" },
"name": "Italian",
"disabled": false,
"translation": { "en": { "name": "Italiana" } }
}
],
"__v": 0,
"translation": { "es": { "name": "Pasta con salsa boloƱesa" } }
}
At last, the changes are not reflecting on DB, but I don't figure out what's wrong.
I am creating a filters application for products, and i am using nodejs and elasticsearch for filtering products. I have stuck on price range filter, it shows wrong options values.
Here is mapping.
{
"elasticsearch": {
"default_mapping": {
"properties": {
"variants.option_values": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"variants.price": {
"type": "float",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
}
}
}
}
}
My Query
{
"_source": [
"variants.option_values",
"variants.price"
],
"query": {
"bool": {
"filter": {
"range": {
"variants.price": {
"gte": 25000,
"lte": 30000
}
}
}
}
},
"aggs": {
"sizes": {
"terms": {
"field": "variants.option_values.keyword",
"order": {
"_count": "desc"
},
"size": 750
}
}
}
}
And Elasticsearch's Result
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 4.8374715,
"hits": [
{
"_index": "my-products",
"_type": "products",
"_id": "4680333656118",
"_score": 4.8374715,
"_ignored": [
"product_type.completion"
],
"_source": {
"variants": [
{
"price": "30000.00",
"option_values": [
"Small"
]
},
{
"price": "20000.00",
"option_values": [
"Medium"
]
},
{
"price": "25000.00",
"option_values": [
"Large"
]
}
]
}
}
]
},
"aggregations": {
"sizes": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Large",
"doc_count": 1
},
{
"key": "Medium",
"doc_count": 1
},
{
"key": "Small",
"doc_count": 1
}
]
}
}
}
I am expecting an aggregations's buckets must have Size Large and Small. And must not include Medium. Because Size Medium's price in less than the filtered price.(In other words size medium is not available in filtered price).
Here is my mapping
"elasticsearch": {
"default_mapping": {
"properties": {
"placement": {
"type": "nested"
},
"collects": {
"properties": {
"collection_id": {
"type": "long",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
},
"id": {
"type": "long",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
},
"product_id": {
"type": "long",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
}
}
},
"variants.percent_sale": {
"type": "float",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
},
"variants.option_values": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"variants.price": {
"type": "float",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
},
"variants.compare_at_price": {
"type": "float",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
},
"variants.weight": {
"type": "float",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"text": {
"type": "text"
}
}
},
"variants.sku": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"tags": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"vendor": {
"type": "text",
"analyzer": "keyword",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"product_type": {
"type": "text",
"analyzer": "keyword",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"options.values": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"articles.title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
},
"articles.tags": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"completion": {
"type": "completion",
"analyzer": "standard"
}
}
}
}
}
}
Mapping issue: Resolved when i set variants as nested type
inner_hits done the great job!
Here is results
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0,
"hits": [
{
"_index": "my-products",
"_type": "products",
"_id": "5012966080571",
"_score": 0,
"_source": {
"variants": [
{
"price": "30000.00"
},
{
"price": "20000.00"
},
{
"price": "25000.00"
}
]
},
"inner_hits": {
"variants": {
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "my-products",
"_type": "products",
"_id": "5012966080571",
"_nested": {
"field": "variants",
"offset": 0
},
"_score": null,
"_source": {
"id": 34120727560251,
"product_id": 5012966080571,
"title": "Small",
"price": "30000.00",
"sku": "super-1101",
"position": 1,
"inventory_policy": "deny",
"compare_at_price": "30500.00",
"fulfillment_service": "manual",
"inventory_management": "shopify",
"option1": "Small",
"option2": null,
"option3": null,
"created_at": "2020-08-11T11:09:29-04:00",
"updated_at": "2020-08-11T11:09:49-04:00",
"taxable": true,
"barcode": "",
"grams": 144,
"image_id": null,
"weight": 144,
"weight_unit": "g",
"inventory_item_id": 35675740274747,
"inventory_quantity": 2,
"old_inventory_quantity": 2,
"requires_shipping": true,
"admin_graphql_api_id": "gid://shopify/ProductVariant/34120727560251",
"option_values": [
"Small"
],
"percent_sale": 1
},
"sort": [
30000
]
},
{
"_index": "my-products",
"_type": "products",
"_id": "5012966080571",
"_nested": {
"field": "variants",
"offset": 2
},
"_score": null,
"_source": {
"id": 34120727625787,
"product_id": 5012966080571,
"title": "Large",
"price": "25000.00",
"sku": "super-1103",
"position": 3,
"inventory_policy": "deny",
"compare_at_price": "25500.00",
"fulfillment_service": "manual",
"inventory_management": "shopify",
"option1": "Large",
"option2": null,
"option3": null,
"created_at": "2020-08-11T11:09:29-04:00",
"updated_at": "2020-08-11T11:10:03-04:00",
"taxable": true,
"barcode": "",
"grams": 144,
"image_id": null,
"weight": 144,
"weight_unit": "g",
"inventory_item_id": 35675740340283,
"inventory_quantity": 4,
"old_inventory_quantity": 4,
"requires_shipping": true,
"admin_graphql_api_id": "gid://shopify/ProductVariant/34120727625787",
"option_values": [
"Large"
],
"percent_sale": 1
},
"sort": [
25000
]
}
]
}
}
}
}
]
},
"aggregations": {
"variants_options": {
"doc_count": 3,
"inner": {
"doc_count": 2,
"sizes": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Large",
"doc_count": 1
},
{
"key": "Small",
"doc_count": 1
}
]
}
}
}
}
}
Thanks Gibbs
I want to aggregate on the brand field and is give me two results instead of one
The brands_aggs give me from this text
{name : "Brand 1"}
2 results
Brand and 1
But Why I need only Brand 1
is separate the word brand and 1 from (Brand 1)
and is give me 2 results in the aggrecation
my mappings where I want to aggregate
mapping = {
"mappings": {
"product": {
"properties": {
"categories": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"fielddata": True
}
"brand": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"fielddata": True
}
}
}
}
}
my post request
{
"query" : {
"bool": {
"must": [
{"match": { "categories": "AV8KW5Wi31qHZdVeXG4G" }}
]
}
},
"size" : 0,
"aggs" : {
"brand_aggs" : {
"terms" : { "field" : "brand" }
},
"categories_aggs" : {
"terms" : { "field" : "categories" }
}
}
}
response from the server
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0,
"hits": []
},
"aggregations": {
"categories_aggs": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "av8kw5wi31qhzdvexg4g",
"doc_count": 1
},
{
"key": "av8kw61c31qhzdvexg4h",
"doc_count": 1
},
{
"key": "av8kxtch31qhzdvexg4a",
"doc_count": 1
}
]
},
"brand_aggs": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "1", <==== I dont need this , why is give me that ??
"doc_count": 1
},
{
"key": "brand",
"doc_count": 1
}
]
},
}
}
Your mapping has property fields which is used when you want to have multiple analyzers for the same field. In your case valid name of your field is 'brand.keyword'. When you call your aggregate for just 'brand' it use default mapping defined for string.
So your query should be:
{
"query" : {
"bool": {
"must": [
{"match": { "categories": "AV8KW5Wi31qHZdVeXG4G" }}
]
}
},
"size" : 0,
"aggs" : {
"brand_aggs" : {
"terms" : { "field" : "brand.keyword" }
},
"categories_aggs" : {
"terms" : { "field" : "categories.keyword" }
}
}
}
Property field is useful when you want for example search the same property which multiple analyzers, for example:
"full_name": {
"type": "text",
"analyzer": "standard",
"boost": 1,
"fields": {
"autocomplete": {
"type": "text",
"analyzer": "ngram_analyzer"
},
"standard":{
"type": "text",
"analyzer": "standard"
}
}
},
You need to map your string as not_analyzed string, for that run the below query
PUT your_index/_mapping/your_type
{
"your_type": {
"properties": {
"brand": {
"type": "string",
"index": "analyzed",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
Don't forget to replace the your_type and your_index with your type and index values.
I have a nested object as follows
{"stats": {"abc": {"NumSources": 6, "Size": 12754890006, "Sources": {"NodeA": {"NumFiles": 246, "Size": 509071269}, "NodeB": {"NumFiles": 104, "Size": 823385346}, "NodeC": {"NumFiles": 466, "Size": 1259819487}, "NodeD": {"NumFiles": 178, "Size": 1712383515}, "NodeE-daemon": {"NumFiles": 79, "Size": 7338}, "NodeF": {"NumFiles": 244, "Size": 8450223051}}}}}
and here is the mapping i create
put statsview
{
"mappings":{
"test2":{
"properties":{
"stats":{
"type":"nested",
"properties":{
"abc":{
"type":"nested",
"include_in_parent": true,
"properties": {
"NumSources": {
"type": "long"
},
"Size": {
"type": "long"
},
"Sources": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NodeA": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NumFiles": {
"type": "long"
},
"Size": {
"type": "long"
}
}
},
"NodeB": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NumFiles": {
"type": "long"
},
"Size": {
"type": "long"
}
}
},
"NodeC": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NumFiles": {
"type": "long"
},
"Size": {
"type": "long"
}
}
},
"NodeD": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NumFiles": {
"type": "long"
},
"Size": {
"type": "long"
}
}
},
"NodeE": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NumFiles": {
"type": "long"
},
"Size": {
"type": "long"
}
}
},
"NodeF": {
"type":"nested",
"include_in_parent": true,
"properties": {
"NumFiles": {
"type": "long"
},
"Size": {
"type": "long"
}
}
}
}
}
}
}
}
}
}
}
}
}
Note that, at each level i am including the spec "include_in_parent": true,
now, in my Kibana Discover view, i see just one record, which makes sense.
GET statsview/_search
{
"query": {
"match_all": {}
}
}
which gives me
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "statsview",
"_type": "test2",
"_id": "1",
"_score": 1,
"_source": {
"logs": {
"abc": {
"NumSources": 6,
"Size": 12754890006,
"Sources": {
"NodeA": {
"NumFiles": 246,
"Size": 509071269
},
"NodeB": {
"NumFiles": 104,
"Size": 823385346
},
"NodeC": {
"NumFiles": 466,
"Size": 1259819487
},
"NodeD": {
"NumFiles": 178,
"Size": 1712383515
},
"NodeE-daemon": {
"NumFiles": 79,
"Size": 7338
},
"NodeF": {
"NumFiles": 244,
"Size": 8450223051
}
}
}
}
}
}
]
}
}
So i see this record in Kibana's Discover view. But i cant run queries like
logs.abc.Sources
so i want to see all of the sources i.e NodeA to NodeF. I even tried
logs.abc.Sources:[NodeA To NodeF]
but i still get status 200.
Is there support in Kibana for running such queries for nested objects?
How can i visualize these nested objects?
Is my mapping correct?
I got a problem with a search I just can't figure out how to do it. My docs are of the following form:
{
"timestamp":"2015-03-17T15:05:04.563Z",
"session_id":"1",
"user_id":"jan"
}
Let's say the first timestamp of a session id is the "Login" and the last timestamp is the "Logout". I want to have all "login" and "logout" docs for all sessions (if possible sorted by user_id). I managed to get the right timestamps with aggregations:
{
"aggs" : {
"group_by_uid" : {
"terms" : {
"field" : "user_id"
},
"aggs" : {
"group_by_sid" : {
"terms" : {
"field" : "session_id"
},
"aggs" : {
"max_date" : {
"max": { "field" : "timestamp" }
},
"min_date" : {
"min": { "field" : "timestamp" }
}
}
}
}
}
}
}
But how do I get the corresponding docs? I also don't mind if i have to do 2 searches (one for the logins and one for the logouts). I tried tome top hits aggregations and sorting stuff but I always get parse errors :/
I hope someone can give me a hint :)
Best regards,
Jan
Here's a solution in a single search based on the approach proposed by Sloan Ahrens. The advantage is that the start and end session entries are in the same bucket.
{
"aggs": {
"group_by_uid": {
"terms": {
"field": "user_id"
},
"aggs": {
"group_by_sid": {
"terms": {
"field": "session_id"
},
"aggs": {
"session_start": {
"top_hits": {
"size": 1,
"sort": [ { "timestamp": { "order": "asc" } } ]
}
},
"session_end": {
"top_hits": {
"size": 1,
"sort": [ { "timestamp": { "order": "desc" } } ]
}
}
}
}
}
}
}
}
Cheers,
Jan
You're already close. How about this. Use two searches, each aggregating the way you did, but then also get the first top_hit sorting on "timestamp".
I just set up a basic index and added some data that looks like what you posted:
PUT /test_index
{
"settings": {
"number_of_shards": 1
}
}
POST /test_index/_bulk
{"index":{"_index":"test_index","_type":"doc","_id":1}}
{"timestamp":"2015-03-17T15:05:04.563Z","session_id":"1","user_id":"jan"}
{"index":{"_index":"test_index","_type":"doc","_id":2}}
{"timestamp":"2015-03-17T15:10:04.563Z","session_id":"1","user_id":"jan"}
{"index":{"_index":"test_index","_type":"doc","_id":3}}
{"timestamp":"2015-03-17T15:15:04.563Z","session_id":"1","user_id":"jan"}
{"index":{"_index":"test_index","_type":"doc","_id":4}}
{"timestamp":"2015-03-17T18:05:04.563Z","session_id":"1","user_id":"bob"}
{"index":{"_index":"test_index","_type":"doc","_id":5}}
{"timestamp":"2015-03-17T18:10:04.563Z","session_id":"1","user_id":"bob"}
{"index":{"_index":"test_index","_type":"doc","_id":6}}
{"timestamp":"2015-03-17T18:15:04.563Z","session_id":"1","user_id":"bob"}
Then I can get each session's start time with:
POST /test_index/_search?search_type=count
{
"aggs": {
"group_by_uid": {
"terms": {
"field": "user_id"
},
"aggs": {
"group_by_sid": {
"terms": {
"field": "session_id"
},
"aggs": {
"session_start": {
"top_hits": {
"size": 1,
"sort": [ { "timestamp": { "order": "asc" } } ]
}
}
}
}
}
}
}
}
...
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_uid": {
"buckets": [
{
"key": "bob",
"doc_count": 3,
"group_by_sid": {
"buckets": [
{
"key": "1",
"doc_count": 3,
"session_start": {
"hits": {
"total": 3,
"max_score": null,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "4",
"_score": null,
"_source": {
"timestamp": "2015-03-17T18:05:04.563Z",
"session_id": "1",
"user_id": "bob"
},
"sort": [
1426615504563
]
}
]
}
}
}
]
}
},
{
"key": "jan",
"doc_count": 3,
"group_by_sid": {
"buckets": [
{
"key": "1",
"doc_count": 3,
"session_start": {
"hits": {
"total": 3,
"max_score": null,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "1",
"_score": null,
"_source": {
"timestamp": "2015-03-17T15:05:04.563Z",
"session_id": "1",
"user_id": "jan"
},
"sort": [
1426604704563
]
}
]
}
}
}
]
}
}
]
}
}
}
and end-time with:
POST /test_index/_search?search_type=count
{
"aggs": {
"group_by_uid": {
"terms": {
"field": "user_id"
},
"aggs": {
"group_by_sid": {
"terms": {
"field": "session_id"
},
"aggs": {
"session_end": {
"top_hits": {
"size": 1,
"sort": [ { "timestamp": { "order": "desc" } } ]
}
}
}
}
}
}
}
}
...
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_uid": {
"buckets": [
{
"key": "bob",
"doc_count": 3,
"group_by_sid": {
"buckets": [
{
"key": "1",
"doc_count": 3,
"session_end": {
"hits": {
"total": 3,
"max_score": null,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "6",
"_score": null,
"_source": {
"timestamp": "2015-03-17T18:15:04.563Z",
"session_id": "1",
"user_id": "bob"
},
"sort": [
1426616104563
]
}
]
}
}
}
]
}
},
{
"key": "jan",
"doc_count": 3,
"group_by_sid": {
"buckets": [
{
"key": "1",
"doc_count": 3,
"session_end": {
"hits": {
"total": 3,
"max_score": null,
"hits": [
{
"_index": "test_index",
"_type": "doc",
"_id": "3",
"_score": null,
"_source": {
"timestamp": "2015-03-17T15:15:04.563Z",
"session_id": "1",
"user_id": "jan"
},
"sort": [
1426605304563
]
}
]
}
}
}
]
}
}
]
}
}
}
Here's the code I used:
http://sense.qbox.io/gist/05edb48b840e6a992646643913db8ef0a3ccccb3