Elasticsearch : How to group documents by field when field is an array - arrays

My Elasticsearch index looks like that:
{
"team": ["Jane","Jason"],
"date": "2020/07/23 12:00:56",
"is_work_done": true
},
{
"team": ["Jane","Jason"],
"date": "2020/07/22 14:23:56",
"is_work_done": false
},
{
"team": ["Jane","Jason","Anna"],
"date": "2020/07/17 09:22:10",
"is_work_done": false
},
{
"team": ["Alex","George","Anna"],
"date": "2020/07/13 03:24:19",
"is_work_done": true
}
My mapping is:
{
"mappings": {
"type_name": {
"properties": {
"team": { "type": "keyword" },
"date": {"type": "date", "format": "yyyy/MM/dd HH:mm:ss"},
"is_work_done": { "type": "boolean" }
}
}
}
}
I would like to collect information on each team. How can I group my documents by team?
I created this index to solve this issue because in reality, I don't know how many members each team contain.
I tried to aggregate the documents but I don't find which type of aggregation would fit.
For example, with this query:
GET /testbench-test/_search
{
"aggs": {
"mybucket": {
"terms": { "field": "team" }
}
}
}
I get this result:
"aggregations" : {
"mybucket" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Jane",
"doc_count" : 3
},
{
"key" : "Jason",
"doc_count" : 3
},
{
"key" : "Anna",
"doc_count" : 2
},
{
"key" : "Alex",
"doc_count" : 1
},
{
"key" : "George",
"doc_count" : 1
}
]
}
}
Thanks for helping!
Edit:
With the query on my real index which contains 64,030 indexations:
POST _search
{
"aggs": {
"teams": {
"terms": {
"script": "doc['team'].join(' & ')",
"size": 10
}
}
}
}
I get this result:
{
"took" : 52,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 64031,
"max_score" : 1.0,
"hits" : [
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "98",
"_score" : 1.0,
"_source" : {
"uuid" : "9827af",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f930813",
"date" : "2019/04/25 11:40:19",
"duration" : 0.9953742847,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00013A9D00002"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "b0c9a8aa4",
"_score" : 1.0,
"_source" : {
"uuid" : "b0c9a1be0a8aa4",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf385a1562d78813",
"date" : "2019/04/29 08:08:37",
"duration" : 0.4976871423,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00149"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "bb1d525e2a368f6d4",
"_score" : 1.0,
"_source" : {
"uuid" : "bb1da368f6d4",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f85a1562d78813",
"date" : "2019/04/29 08:09:51",
"duration" : 0.5208305083,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00179"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "87bec43ce2553c590b",
"_score" : 1.0,
"_source" : {
"uuid" : "87bec43c-e2553c590b",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f9302bcdf8c26e1f85a1562d78813",
"date" : "2019/04/29 08:10:10",
"duration" : 0.4629604518,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00181"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "3499224bdac4fa39",
"_score" : 1.0,
"_source" : {
"uuid" : "349922444bdac4fa39",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6e1f85a1562d78813",
"date" : "2019/04/29 08:10:49",
"duration" : 0.5092588253,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"uut" : [
"MCANT00009A9D00171"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "f8236de0-dd6a97b7a81",
"_score" : 1.0,
"_source" : {
"uuid" : "f8236de0-add6a97b7a81",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f93085a1562d78813",
"date" : "2019/04/29 09:51:47",
"duration" : 0.6134272553,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00221"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "339fa5a2e-cf9f1f4738bf",
"_score" : 1.0,
"_source" : {
"uuid" : "339fa5a9f1f4738bf",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f932d78813",
"date" : "2019/04/29 09:51:57",
"duration" : 0.6249989383,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00185"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "dbd45ec4-f53b-4bda-9eeb-dadf2e3ab366",
"_score" : 1.0,
"_source" : {
"uuid" : "dbd45ec4-f53b-4bda-9eeb-dadf2e3ab366",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f9302bcdfd78813",
"date" : "2019/04/29 09:52:19",
"duration" : 0.5787005648,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00184"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "bc0d3548bed68",
"_score" : 1.0,
"_source" : {
"uuid" : "bc0d354348bed68",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf3801562d78813",
"date" : "2019/04/29 08:08:12",
"duration" : 0.5208305083,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00160"
]
}
},
{
"_index" : "test-logs",
"_type" : "log",
"_id" : "d591b9e7-683a-4d78-be31-1b137b8a3b2b",
"_score" : 1.0,
"_source" : {
"uuid" : "d591b9e7-683a-4d78-be31-1b137b8a3b2b",
"benchId" : "m",
"benchGroup" : "e",
"machine" : "CH",
"sha1" : "ddf380fd6a2f93013",
"date" : "2019/04/29 08:08:05",
"duration" : 0.6828689948,
"isCss" : false,
"isPassed" : true,
"finalStatus" : "OK_VNA_TEST",
"team" : [
"MCANT00009A9D00146"
]
}
}
]
},
"aggregations" : {
"teams" : {
"doc_count_error_upper_bound" : 25,
"sum_other_doc_count" : 63658,
"buckets" : [
{
"key" : "SI050010AA8C00001",
"doc_count" : 86
},
{
"key" : "00845D9E0137 & 00851F9E0095 & CPPCB00608C9F00060 & MCSAS00676A9F00141_-27.8_B & MCSAS00677A9F00146_23.0_B & SI050012AG9F00060",
"doc_count" : 56
},
{
"key" : "00845D9E0275 & 00851F9G0056 & CPPCB00608C9F00127 & MCSAS00676B9G00012 & MCSAS00676B9G00012_-21.2_C & MCSAS00677B9G00005 & MCSAS00677B9G00005_32.5_C & SI050012AG9F00127",
"doc_count" : 43
},
{
"key" : "00844G9D0041 & 00847D9G0020 & MCANT00009A9G00048 & MCSAS00652F9E00091 & S20-17272 & SI050001AG9G00055 & SI050004AA9F00059",
"doc_count" : 39
},
{
"key" : "00845D9E0035 & 00851F9E0062 & CPPCB00608C9E00034 & MCSAS00676A9E00090_-35.0_B & MCSAS00677A9E00089_31.0_B & SI050012AG9E00034",
"doc_count" : 34
},
{
"key" : "IX & IX-c2-67063 & IX-x2-00511 & SI050010AA9A00002 & droneProduction",
"doc_count" : 27
},
{
"key" : "IX & IX-12-10251 & IX-x2-00484 & SI050001AF9A00020 & SI050010AA8J00154 & SI050012AG9D00082 & droneClient",
"doc_count" : 25
},
{
"key" : "MCANT00009A9G00048 & MCSAS00652F9E00091 & S20-17272 & SI050001AG9G00055",
"doc_count" : 24
},
{
"key" : "00883C0F0000",
"doc_count" : 20
},
{
"key" : "00844C8B0029 & 00847C8E0018 & 00849A8B0015 & MCANT00009A8E00017 & N/A & S20-00533 & SI050002AA8E000001 & SI050004AA8E000514",
"doc_count" : 19
}
]
}
}
}
Why not all the different 'teams' have their own bucket?

What you can do is to use a script in your terms aggregation like this:
POST teams/_search
{
"size": 0,
"aggs": {
"teams": {
"terms": {
"script": "doc['team'].join('-')",
"size": 10
}
}
}
}
And the result you're going to get is something like this:
"buckets" : [
{
"key" : "Jane-Jason",
"doc_count" : 2
},
{
"key" : "Alex-Anna-George",
"doc_count" : 1
},
{
"key" : "Anna-Jane-Jason",
"doc_count" : 1
}
]

Related

Sorting nested Array in MongoDB using aggregate

I am trying to sort the nested array "subCategoryList on top of sorting by _id on the parent document. Newbie to mongo. Any help will be appreciated
Here is sample documents:
[
{
"_id": 1000,
"name": "Automobiles",
"parentId": "",
"helpText": "Year, Brand, Model, Color, Size"
},
{
"_id": 1004,
"name": "RV / Campers",
"parentId": 1000,
"helpText": ""
},
{
"_id": 1001,
"name": "Car / SUV / Truck",
"parentId": 1000,
"helpText": ""
}
]
Here is what I tried:
db.Category.aggregate([
{
"$match": {
"parentId": ""
}
},
{
"$lookup": {
"from": "Category", "localField": "_id", "foreignField": "parentId", "as": "subCategoryList"
}
},
{
$sort: {
_id: 1
}
}
]).pretty()
But I get:
{
"_id" : 17000,
"name" : "Music",
"parentId" : "",
"helpText" : "Help Text - Brand, Model, Title",
"subCategoryList" : [
{
"_id" : 17001,
"name" : "DVD / Blu-ray",
"parentId" : 17000,
"helpText" : ""
},
{
"_id" : 17002,
"name" : "Player",
"parentId" : 17000,
"helpText" : ""
}
]
}
{
"_id" : 20000,
"name" : "Sports Gear",
"parentId" : "",
"helpText" : "Help Text - Brand, Model, Gear Type, Size, Color,",
"subCategoryList" : [
{
"_id" : 20002,
"name" : "Football",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20007,
"name" : "Tennis",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20008,
"name" : "Cricket",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20004,
"name" : "Hockey",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20003,
"name" : "Golf",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20006,
"name" : "Basketball",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20005,
"name" : "Soccer",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20010,
"name" : "Camping / Hiking",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20009,
"name" : "Cycling",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20001,
"name" : "Baseball",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20012,
"name" : "Skiing",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20011,
"name" : "Swimming",
"parentId" : 20000,
"helpText" : ""
},
{
"_id" : 20099,
"name" : "Other",
"parentId" : 20000,
"helpText" : ""
}
]
}
db.hardwares.aggregate([
{$unwind: "$subCategoryList"},
{$sort: {"subCategoryList._id": 1}},
{$group: {_id:"$_id", subCategoryList: {$push:"$subCategoryList"}}}
]);
It could be helps you, try like this...
May be it didn't work but it gives an idea
Mongo doesn't have a built in function to sort an inner array, However Mongo v4.4 introduces the $function aggregation operator. this allows us to use custom javascript functions within a pipeline.
You could use it like so:
db.Category.aggregate([
{
$addFields: {
"subCategoryList":
{
$function: {
body: function (categories) {
return categories.sort((a, b) => a._id - b._id);
},
args: ["$subCategoryList"],
lang: "js"
}
}
}
}
])
For lesser Mongo versions you will have to first $unwind the array. then $sort it and finally constructing the original structure or in your case because you are $lookuping the inner array you could use the other $lookup syntax introduced at v3.6 to $sort within the $lookup:
db.Category.aggregate([
{
"$match": {
"parentId": ""
}
},
{
"$lookup": {
"from": "Category",
let: {id: "$_id"},
pipeline: [
{
$match: {
$expr: {
$eq: ["$$id", "$parentId"]
}
}
},
{
$sort: {
_id: 1
}
}
],
"as": "subCategoryList"
}
},
{
$sort: {
_id: 1
}
}
]);

Checking $gt on a structure element in MongoDB [duplicate]

This question already has answers here:
How to query nested objects?
(3 answers)
Closed 2 years ago.
> db.inventory.find()
{ "_id" : ObjectId("5eb67598bee5213484d45087"), "item" : "journal", "qty" : 25, "status" : "A", "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "tags" : [ "blank", "red" ] }
{ "_id" : ObjectId("5eb67598bee5213484d45088"), "item" : "notebook", "qty" : 50, "status" : "A", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "tags" : [ "red", "blank" ] }
{ "_id" : ObjectId("5eb67598bee5213484d45089"), "item" : "paper", "qty" : 10, "status" : "D", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "tags" : [ "red", "blank", "plain" ] }
{ "_id" : ObjectId("5eb67598bee5213484d4508a"), "item" : "planner", "qty" : 0, "status" : "D", "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "tags" : [ "blank", "red" ] }
{ "_id" : ObjectId("5eb67598bee5213484d4508b"), "item" : "postcard", "qty" : 45, "status" : "A", "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "tags" : [ "blue" ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be04608"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be04609"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be0460a"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be0460b"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be0460c"), "item" : "postcard", "qty" : 45, "tags" : [ "blue" ], "dim_cm" : [ 10, 15.25 ] }
Both of the following queries are resulting in nothing:
> db.inventory.find( { size: { h: { $gt: 14 } } } )
>
> db.inventory.find( { size: { $elemMatch: { h: { $gt: 14 } } } } )
Whereas there is a document greater than 14:
{ "_id" : ObjectId("5eb67598bee5213484d4508a"), "item" : "planner", "qty" : 0, "status" : "D", "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "tags" : [ "blank", "red" ] }
Following syntax doesn't work:
> db.inventory.find( { size.h: { $gt: 14 } } )
2020-05-24T15:08:44.306+0530 E QUERY [js] uncaught exception: SyntaxError: missing : after property id :#(shell):1:25
`
Please explain why.
You need to add dot notation while querying nested documents. Can you try this
db.inventory.find( { 'size.h': { $gt: 14 } } )

Unable to find a match in MongoDB query

> db.inventory.find( )
{ "_id" : ObjectId("5eb67598bee5213484d45087"), "item" : "journal", "qty" : 25, "status" : "A", "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "tags" : [ "blank", "red" ] }
{ "_id" : ObjectId("5eb67598bee5213484d45088"), "item" : "notebook", "qty" : 50, "status" : "A", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "tags" : [ "red", "blank" ] }
{ "_id" : ObjectId("5eb67598bee5213484d45089"), "item" : "paper", "qty" : 10, "status" : "D", "size" : { "h" : 8.5, "w" : 11, "uom" : "in" }, "tags" : [ "red", "blank", "plain" ] }
{ "_id" : ObjectId("5eb67598bee5213484d4508a"), "item" : "planner", "qty" : 0, "status" : "D", "size" : { "h" : 22.85, "w" : 30, "uom" : "cm" }, "tags" : [ "blank", "red" ] }
{ "_id" : ObjectId("5eb67598bee5213484d4508b"), "item" : "postcard", "qty" : 45, "status" : "A", "size" : { "h" : 10, "w" : 15.25, "uom" : "cm" }, "tags" : [ "blue" ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be04608"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be04609"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be0460a"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be0460b"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }
{ "_id" : ObjectId("5ebfd02b3a3b38a52be0460c"), "item" : "postcard", "qty" : 45, "tags" : [ "blue" ], "dim_cm" : [ 10, 15.25 ] }
>
> db.inventory.find( { item: 'journal', qty: '25' } )
>
item: 'journal' with qty '25' is the first item. Why isn't it being shown?
Here is a similar query which is working as per them: https://www.w3resource.com/mongodb-exercises/mongodb-exercise-22.php
db.restaurants.find(
{
"grades.date": ISODate("2014-08-11T00:00:00Z"),
"grades.grade":"A" ,
"grades.score" : 11
},
{"restaurant_id" : 1,"name":1,"grades":1}
);
qty is a number and you're trying to find a string, try:
db.inventory.find( { item: 'journal', qty: 25 } )
(docs)
For most data types, however, comparison operators only perform comparisons on documents where the BSON type of the target field matches the type of the query operand.

Swift Mullti level Filtering

{
"productId" : "prod830028",
"deviceFeatures" : [
"SIM Type:Nano",
"Battery:3,174mAh",
"Front Camera:7MP",
"Rear Camera:12MP + 12MP",
"OS:iOS 12",
"Processor:A12 Bionic chip with next-generation Neural Engine",
"Display:6.5 inches, OLED"
],
"productOverView": "Meet the iPhone X - the device that’s so smart that it responds to a tap, your voice, and even a glance. Elegantly designed with a large 14.73 cm (5.8) Super Retina screen and a durable front-and-back glass.",
"specifications":[
{
"key": "Color",
"value": "Space Grey"
},
{
"key": "Internal Memory",
"value": "64 GB"
},
{
"key": "Operating System",
"value": "iOS 11.1.1"
},
{
"key": "Primary Camera",
"value": "12 MP"
},
{
"key": "RAM",
"value": "5.8 inch"
},
{
"key": "Screen Size",
"value": "15"
},
{
"key": "Expandable Memory",
"value": "No"
},
{
"key": "Camera Feature",
"value": "Geo-tagging, simultaneous 4K video and 8MP image recording, touch focus, face/smile detection, HDR (photo/panorama)"
}
],
"preorderable" : false,
"responseMsg" : "SUCCESS",
"skuDetails" : [
{
"oldPriceWithVat" : "4461.45",
"pointsWithVat" : "393900",
"pointsWithoutVat" : "375143",
"ratePlanCode" : "RPDLAPAPPEQ000000G9F",
"priceWithouthVat" : "3751.43",
"priceWithVat" : "3939.0015",
"devicePaymentOptions" : [
{
"price" : "362.0",
"duration" : "12",
"demandId" : "3052451"
},
{
"price" : "185.0",
"duration" : "24",
"demandId" : "3052468"
},
{
"price" : "244.0",
"duration" : "18",
"demandId" : "3052593"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202391",
"vatPercentage" : "5",
"sicCode" : "3820202391",
"oldPriceWithoutVat" : "4249.0",
"oldPricePointsWithoutVat" : "424900",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-SpaceGray-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#8C8C8C",
"value" : "Space Gray",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "64GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "446145",
"demandId" : "3060416"
},
{
"oldPriceWithVat" : "4461.45",
"pointsWithVat" : "316575",
"pointsWithoutVat" : "301500",
"ratePlanCode" : "RPDLAPAPPEQ000000G9I",
"priceWithouthVat" : "3015.0",
"priceWithVat" : "3165.75",
"devicePaymentOptions" : [
{
"price" : "362.0",
"duration" : "12",
"demandId" : "3052402"
},
{
"price" : "185.0",
"duration" : "24",
"demandId" : "3052634"
},
{
"price" : "244.0",
"duration" : "18",
"demandId" : "3052559"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202404",
"vatPercentage" : "5",
"sicCode" : "3820202404",
"oldPriceWithoutVat" : "4249.0",
"oldPricePointsWithoutVat" : "424900",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-Silver-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#C0C0C0",
"value" : "Silver",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "64GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "446145",
"demandId" : "3060419"
},
{
"oldPriceWithVat" : "4461.45",
"pointsWithVat" : "393900",
"pointsWithoutVat" : "375143",
"ratePlanCode" : "RPDLAPAPPEQ000000GAL",
"priceWithouthVat" : "3751.43",
"priceWithVat" : "3939.0015",
"devicePaymentOptions" : [
{
"price" : "185.0",
"duration" : "24",
"demandId" : "3052605"
},
{
"price" : "362.0",
"duration" : "12",
"demandId" : "3052640"
},
{
"price" : "244.0",
"duration" : "18",
"demandId" : "3052646"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202419",
"vatPercentage" : "5",
"sicCode" : "3820202419",
"oldPriceWithoutVat" : "4249.0",
"oldPricePointsWithoutVat" : "424900",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-Gold-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#D4AF37",
"value" : "Gold",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "64GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "446145",
"demandId" : "3060494"
},
{
"oldPriceWithVat" : "5065.2",
"pointsWithVat" : "445500",
"pointsWithoutVat" : "424286",
"ratePlanCode" : "RPDLAPAPPEQ000000G9E",
"priceWithouthVat" : "4242.86",
"priceWithVat" : "4455.003",
"devicePaymentOptions" : [
{
"price" : "210.0",
"duration" : "24",
"demandId" : "3052406"
},
{
"price" : "277.0",
"duration" : "18",
"demandId" : "3052372"
},
{
"price" : "411.0",
"duration" : "12",
"demandId" : "3052571"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202438",
"vatPercentage" : "5",
"sicCode" : "3820202438",
"oldPriceWithoutVat" : "4824.0",
"oldPricePointsWithoutVat" : "482400",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-SpaceGray-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#8C8C8C",
"value" : "Space Gray",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "256GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "506520",
"demandId" : "3060415"
},
{
"oldPriceWithVat" : "5065.2",
"pointsWithVat" : "445500",
"pointsWithoutVat" : "424286",
"ratePlanCode" : "RPDLAPAPPEQ000000G9Y",
"priceWithouthVat" : "4242.86",
"priceWithVat" : "4455.003",
"devicePaymentOptions" : [
{
"price" : "210.0",
"duration" : "24",
"demandId" : "3052650"
},
{
"price" : "411.0",
"duration" : "12",
"demandId" : "3052353"
},
{
"price" : "277.0",
"duration" : "18",
"demandId" : "3052520"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202453",
"vatPercentage" : "5",
"sicCode" : "3820202453",
"oldPriceWithoutVat" : "4824.0",
"oldPricePointsWithoutVat" : "482400",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-Silver-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#C0C0C0",
"value" : "Silver",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "256GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "506520",
"demandId" : "3060445"
},
{
"oldPriceWithVat" : "5065.2",
"pointsWithVat" : "445500",
"pointsWithoutVat" : "424286",
"ratePlanCode" : "RPDLAPAPPEQ000000G9B",
"priceWithouthVat" : "4242.86",
"priceWithVat" : "4455.003",
"devicePaymentOptions" : [
{
"price" : "411.0",
"duration" : "12",
"demandId" : "3052561"
},
{
"price" : "277.0",
"duration" : "18",
"demandId" : "3052510"
},
{
"price" : "210.0",
"duration" : "24",
"demandId" : "3052448"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202469",
"vatPercentage" : "5",
"sicCode" : "3820202469",
"oldPriceWithoutVat" : "4824.0",
"oldPricePointsWithoutVat" : "482400",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-Gold-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#D4AF37",
"value" : "Gold",
"key" : "Colour",
"displayText" : "Colour"
}
],
"oldPricePointsWithVat" : "506520",
"demandId" : "3060412"
},
{
"oldPriceWithVat" : "5884.2",
"pointsWithVat" : "525500",
"pointsWithoutVat" : "500476",
"ratePlanCode" : "RPDLAPAPPEQ000000GA0",
"priceWithouthVat" : "5004.76",
"priceWithVat" : "5254.9980000000005",
"devicePaymentOptions" : [
{
"price" : "336.0",
"duration" : "18",
"demandId" : "3052601"
},
{
"price" : "499.0",
"duration" : "12",
"demandId" : "3052569"
},
{
"price" : "255.0",
"duration" : "24",
"demandId" : "3052361"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202486",
"vatPercentage" : "5",
"sicCode" : "3820202486",
"oldPriceWithoutVat" : "5604.0",
"oldPricePointsWithoutVat" : "560400",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-SpaceGray-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#8C8C8C",
"value" : "Space Gray",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "512GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "588420",
"demandId" : "3060451"
},
{
"oldPriceWithVat" : "5884.2",
"pointsWithVat" : "525500",
"pointsWithoutVat" : "500476",
"ratePlanCode" : "RPDLAPAPPEQ000000G9O",
"priceWithouthVat" : "5004.76",
"priceWithVat" : "5254.9980000000005",
"devicePaymentOptions" : [
{
"price" : "255.0",
"duration" : "24",
"demandId" : "3052466"
},
{
"price" : "499.0",
"duration" : "12",
"demandId" : "3052319"
},
{
"price" : "336.0",
"duration" : "18",
"demandId" : "3052334"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202505",
"vatPercentage" : "5",
"sicCode" : "3820202505",
"oldPriceWithoutVat" : "5604.0",
"oldPricePointsWithoutVat" : "560400",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-Silver-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#C0C0C0",
"value" : "Silver",
"key" : "Colour",
"displayText" : "Colour"
},
{
"key" : "Storage",
"value" : "512GB",
"displayText" : "Storage"
},
{
"key" : "Memory",
"value" : "4GB RAM",
"displayText" : "Memory"
}
],
"oldPricePointsWithVat" : "588420",
"demandId" : "3060427"
},
{
"oldPriceWithVat" : "5884.2",
"pointsWithVat" : "525500",
"pointsWithoutVat" : "500476",
"ratePlanCode" : "RPDLAPAPPEQ000000G9S",
"priceWithouthVat" : "5004.76",
"priceWithVat" : "5254.9980000000005",
"devicePaymentOptions" : [
{
"price" : "499.0",
"duration" : "12",
"demandId" : "3052340"
},
{
"price" : "336.0",
"duration" : "18",
"demandId" : "3052613"
},
{
"price" : "255.0",
"duration" : "24",
"demandId" : "3052324"
}
],
"payWithPointAvailable" : false,
"skuId" : "bgSku3820202524",
"vatPercentage" : "5",
"sicCode" : "3820202524",
"oldPriceWithoutVat" : "5604.0",
"oldPricePointsWithoutVat" : "560400",
"cashOnDeliveryAvailable" : true,
"images" : [
"https:\/\/www.etisalat.ae\/en\/system\/wst\/assets\/img\/devices\/AP-iPhoneXSMax\/AP-iPhoneXsMax-Gold-PureAngles-500.jpg"
],
"skuCoreProperties" : [
{
"colorCode" : "#D4AF37",
"value" : "Gold",
"key" : "Colour",
"displayText" : "Colour"
}
],
"oldPricePointsWithVat" : "588420",
"demandId" : "3060430"
}
],
"brand" : "Apple",
"responseCode" : "0000000",
"name" : "iPhone XS Max"
}
I have above json. what i want is to use filter to get skudetails of object for only those whose color is gold and storage is 64 gb. can it be achievable through filter? As for first level filtering its working fine for me like this :
if let skuDetailArray = self.deviceSKUsAndDetailsResponse?.skuDetails
let demandId = skuDetailArray.first(where: { $0.demandId == "3060416" })
but i could not able to parse data for above conditions, and if its not possible through than can it be possible through predicate, or any other method than please let me know.
**
UPDATE: showing class for these models
**
class SWGetDeviceSKUsAndDetailsResponseModel : SWBaseResponseModel {
let brand : String?
let deviceFeatures : [String]?
let name : String?
let preorderable : Bool?
let productId : String?
let productOverView : String?
let skuDetails : [SWSkuDetail]?
let specifications : [SWSpecification]?
}
class SWSkuDetail : Codable {
let cashOnDeliveryAvailable : Bool?
let demandId : String?
let devicePaymentOptions : [SWDevicePaymentOption]?
let images : [String]?
let oldPricePointsWithVat : String?
let oldPricePointsWithoutVat : String?
let oldPriceWithVat : String?
let oldPriceWithoutVat : String?
let payWithPointAvailable : Bool?
let pointsWithVat : String?
let pointsWithoutVat : String?
let priceWithVat : String?
let priceWithouthVat : String?
let ratePlanCode : String?
let sicCode : String?
let skuCoreProperties : [SWSkuCoreProperty]?
let skuId : String?
let vatPercentage : String?
}
class SWSkuCoreProperty : Codable {
let colorCode : String?
let displayText : String?
let key : String?
let value : String?
}
The following code will return any SWSkuDetail that has the Color = Gold and Storage = 64 GB.
The filter function first filters out the elements with the given keys and then check that it has gotten 2 hits and that both values exists in those two.
let keyColor = "Colour"
let keyStorage = "Storage"
let filtered = skuDetailArray.filter { detail in
guard let props = detail.skuCoreProperties else { return false }
let array = props.filter { $0.key == keyColor || $0.key == keyStorage }.map {$0.value}
return array.count == 2 && array.contains("Gold") && array.contains("64GB")
}

$match inside $in not working in aggregate

I'm trying to get all orders which is match in collection of serviceLocationId id field.
order collection :
{
"_id" : ObjectId("598b0560f514e531713b24b0"),
"orderId" : ObjectId("598b055ff514e531713b24af"),
"orderNo" : "AQ144O1701011",
"serviceLocationId" : "5976e2cce05d17132a343975",
"jobPriority" : "8",
"description" : "Spinneys Mercato",
"serviceType" : "pickup",
"orderSource" : "import",
"takenBy" : "Rany",
"plannedDeliveryDate" : ISODate("2017-08-13T00:00:00Z"),
"actualDeliveryDate" : ISODate("2017-10-13T00:00:00Z"),
"deliveredBy" : "Hamid",
"lineItems" : [
{
"itemId" : "Item09",
"orderQty" : 154,
"deliveredQty" : 154,
"status" : "UNASSIGNED",
"size1" : "100",
"size2" : "200",
"size3" : "300",
"_id" : ObjectId("598b0560f514e531713b24b1")
}
],
"actualDeliveryTime" : {
"from" : "10PM",
"to" : "7PM"
},
"plannedDeliveryTime" : {
"from" : "12PM",
"to" : "11PM"
},
"orderDate" : ISODate("2017-08-09T12:51:44Z"),
"__v" : 0
}
servicelocations collection:
{
"_id" : ObjectId("5976e2cce05d17132a343976"),
"regionId" : ObjectId("5975e82dd857e0444013f426"),
"zoneId" : ObjectId("5975eba0a392a045d77d1b12"),
"description" : "Spinneys Mercato",
"locationPriority" : 1,
"accountType" : "CHAIN CUSTOMER",
"locationType" : "Service Location",
"address1" : "Spinneys Mercato",
"address2" : "Marcatto Centre, Beach Road",
"phone" : "123456",
"city" : "Jumeirah",
"county" : null,
"zipcode" : null,
"state" : null,
"country" : "United Arab Emirates",
"imageUrl" : "",
"deliveryDays" : "1",
"status" : "Delivered",
"createdBy" : "Hitesh",
"updatedBy" : null,
"serviceLocationId" : ObjectId("5976e2cce05d17132a343975"),
"updateDate" : null,
"createdDate" : ISODate("2017-07-25T06:18:52.007Z"),
"location" : {
"makani" : null,
"geo" : {
"latitude" : "25.216547",
"longitude" : "55.253636"
}
},
"contact" : {
"name" : "shiv",
"phone" : "1111111111",
"email" : "test1#gmail.com"
},
"serviceTime" : {
"serviceTimeType" : "598ad8718db899b9d4ff2bc1",
"nonhelper" : {
"fixedTime" : "10",
"variableTime" : "25"
},
"helper" : {
"fixedTime" : "10",
"variableTime" : "15"
}
},
"timeWindow" : [
{
"timeWindowType" : "598ad7578db899b9d4ff2bb9",
"start" : "",
"close" : "",
"_id" : ObjectId("5976e2cce05d17132a343977")
}
],
"__v" : 0
}
query:
db.collection.aggregate([
{ $match: { 'serviceLocationId' : { $in: [ObjectId("5976e2cce05d17132a343975")]} } } ,
{
$lookup:
{
from:'orders',
localField:'serviceLocationId',
foreignField:'serviceLocationId',
as:'orders'
}
}
])
response:
{
"_id" : ObjectId("598592dc8db31d6625a412aa"),
"regionId" : ObjectId("5975e82dd857e0444013f426"),
"zoneId" : ObjectId("5975eb8ba392a045d77d1b10"),
"description" : "ASWAAQ- AL BADAA",
"locationPriority" : 7,
"locationType" : "Service Location",
"address1" : "ASWAAQ- AL BADAA",
"address2" : "AL BADAA, AL WASL ROAD.DUBAI",
"phone" : "123456",
"city" : null,
"county" : null,
"zipcode" : null,
"state" : null,
"country" : "United Arab Emirates",
"imageUrl" : "",
"deliveryDays" : "1",
"status" : "Delivered",
"createdBy" : "Hitesh",
"updatedBy" : null,
"serviceLocationId" : ObjectId("598592dc8db31d6625a41290"),
"accountType" : "CREDIT GROCERY",
"updateDate" : null,
"createdDate" : ISODate("2017-07-25T06:20:15.519Z"),
"location" : {
"makani" : null,
"geo" : {
"latitude" : "25.2037594",
"longitude" : "55.2752419"
}
},
"contact" : {
"name" : "krishna",
"phone" : "1111111119",
"email" : "test9#gmail.hypermarketsm"
},
"serviceTime" : {
"serviceTimeType" : "598ad89e8db899b9d4ff2bc5",
"nonhelper" : {
"fixedTime" : "10",
"variableTime" : "25"
},
"helper" : {
"fixedTime" : "10",
"variableTime" : "15"
}
},
"timeWindow" : [
{
"timeWindowType" : "598ad76d8db899b9d4ff2bbd",
"start" : "",
"close" : "",
"_id" : ObjectId("5976e31fe05d17132a34397d")
}
],
"__v" : 0,
"orders" : [ ]
}
i changed servicelocationId as string in servicelocation collection now it's working fine.
"serviceLocationId" : ObjectId("598592dc8db31d6625a41290") to "serviceLocationId" : "598592dc8db31d6625a41290"
query:
db.getCollection('servicelocations').aggregate([
{ $match: { 'serviceLocationId' : { $in: ["5976e2cce05d17132a343975"]}}} ,
{
$lookup:
{
from:'orders',
localField:'serviceLocationId',
foreignField:'serviceLocationId',
as:'orders'
}
}
])
solution:
/* 1 */
{
"_id" : ObjectId("5976e2cce05d17132a343976"),
"regionId" : ObjectId("5975e82dd857e0444013f426"),
"zoneId" : ObjectId("5975eba0a392a045d77d1b12"),
"description" : "Spinneys Mercato",
"locationPriority" : 1,
"accountType" : "CHAIN CUSTOMER",
"locationType" : "Service Location",
"address1" : "Spinneys Mercato",
"address2" : "Marcatto Centre, Beach Road",
"phone" : "123456",
"city" : "Jumeirah",
"county" : null,
"zipcode" : null,
"state" : null,
"country" : "United Arab Emirates",
"imageUrl" : "",
"imageUrl" : "",
"deliveryDays" : "1",
"status" : "Delivered",
"createdBy" : "Hitesh",
"updatedBy" : null,
"serviceLocationId" : "5976e2cce05d17132a343975",
"updateDate" : null,
"createdDate" : ISODate("2017-07-25T06:18:52.007Z"),
"location" : {
"makani" : null,
"geo" : {
"latitude" : "25.216547",
"longitude" : "55.253636"
}
},
"contact" : {
"name" : "shiv",
"phone" : "1111111111",
"email" : "test1#gmail.com"
},
"serviceTime" : {
"serviceTimeType" : "598ad8718db899b9d4ff2bc1",
"nonhelper" : {
"fixedTime" : "10",
"variableTime" : "25"
},
"helper" : {
"fixedTime" : "10",
"variableTime" : "15"
}
},
"timeWindow" : [
{
"timeWindowType" : "598ad7578db899b9d4ff2bb9",
"start" : "",
"close" : "",
"_id" : ObjectId("5976e2cce05d17132a343977")
}
],
"__v" : 0,
"orders" : [
{
"_id" : ObjectId("598b0560f514e531713b24b0"),
"orderId" : ObjectId("598b055ff514e531713b24af"),
"orderNo" : "AQ144O1701011",
"serviceLocationId" : "5976e2cce05d17132a343975",
"jobPriority" : "8",
"description" : "Spinneys Mercato",
"serviceType" : "pickup",
"orderSource" : "import",
"takenBy" : "Rany",
"plannedDeliveryDate" : ISODate("2017-08-13T00:00:00.000Z"),
"actualDeliveryDate" : ISODate("2017-10-13T00:00:00.000Z"),
"deliveredBy" : "Hamid",
"lineItems" : [
{
"itemId" : "Item09",
"orderQty" : 154,
"deliveredQty" : 154,
"status" : "UNASSIGNED",
"size1" : "100",
"size2" : "200",
"size3" : "300",
"_id" : ObjectId("598b0560f514e531713b24b1")
}
],
"actualDeliveryTime" : {
"from" : "10PM",
"to" : "7PM"
},
"plannedDeliveryTime" : {
"from" : "12PM",
"to" : "11PM"
},
"orderDate" : ISODate("2017-08-09T12:51:44.000Z"),
"__v" : 0
},
{
"_id" : ObjectId("598c3d9880c4d4366cf3e35d"),
"orderId" : ObjectId("598c3d9880c4d4366cf3e35c"),
"orderNo" : "AQ144O1701011",
"serviceLocationId" : "5976e2cce05d17132a343975",
"jobPriority" : "1",
"description" : "Spinneys Mercato",
"serviceType" : "pickup",
"orderSource" : "import",
"takenBy" : "Adam",
"plannedDeliveryDate" : ISODate("2017-09-06T18:30:00.000Z"),
"actualDeliveryDate" : ISODate("2017-10-11T00:00:00.000Z"),
"deliveredBy" : "Adam",
"lineItems" : [
{
"itemId" : "Item09",
"orderQty" : 15,
"deliveredQty" : 15,
"status" : "ASSIGNED",
"_id" : ObjectId("598c3d9880c4d4366cf3e35e")
}
],
"actualDeliveryTime" : {
"from" : "11PM",
"to" : "12PM"
},
"plannedDeliveryTime" : {
"from" : "10PM",
"to" : "10PM"
},
"orderDate" : ISODate("2017-08-10T11:03:52.170Z"),
"__v" : 0
}
]
}

Resources