Why is MongoDB not using the compound index for the query? - database

Here are the compound index and single index I have for this Collection:
///db.Collection.getIndexes()
/* 1 */
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "service.Collection"
},
/* 2 */
{
"v" : 2,
"key" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"name" : "FirstIdSecondIdCreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"ns" : "service.Collection"
},
/* 3 */
{
"v" : 2,
"key" : {
"CreationTime" : 1
},
"name" : "CreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"ns" : "service.Collection"
}
The expected result is an IXSCAN using the FirstIdSecondIdCreationTime index:
///service.Collection.find({ FirstId: "771367b7-4bef-49ab-bda1-6230254c6349", ///SecondId: "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f" })
/// .projection({})
/// .sort({_id:-1}).hint("FirstIdSecondIdCreationTime").explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "service.Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"_id" : -1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"indexName" : "FirstIdSecondIdCreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : false,
"multiKeyPaths" : {
"FirstId" : [ ],
"SecondId" : [ ],
"CreationTime" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"FirstId" : [
"[MinKey, MaxKey]"
],
"SecondId" : [
"[MinKey, MaxKey]"
],
"CreationTime" : [
"[MaxKey, MinKey]"
]
}
}
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 5491,
"totalKeysExamined" : 856730,
"totalDocsExamined" : 856730,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 1,
"executionTimeMillisEstimate" : 5261,
"works" : 856734,
"advanced" : 1,
"needTime" : 856732,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"_id" : -1
},
"memUsage" : 432,
"memLimit" : 33554432,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"nReturned" : 1,
"executionTimeMillisEstimate" : 5201,
"works" : 856732,
"advanced" : 1,
"needTime" : 856730,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 5131,
"works" : 856731,
"advanced" : 1,
"needTime" : 856729,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 856730,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 856730,
"executionTimeMillisEstimate" : 820,
"works" : 856731,
"advanced" : 856730,
"needTime" : 0,
"needYield" : 0,
"saveState" : 6697,
"restoreState" : 6697,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"indexName" : "FirstIdSecondIdCreationTime",
"collation" : {
"locale" : "en",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 1,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : false,
"multiKeyPaths" : {
"FirstId" : [ ],
"SecondId" : [ ],
"CreationTime" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"FirstId" : [
"[MinKey, MaxKey]"
],
"SecondId" : [
"[MinKey, MaxKey]"
],
"CreationTime" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 856730,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"indexDef" : {
"indexName" : "FirstIdSecondIdCreationTime",
"isMultiKey" : false,
"multiKeyPaths" : {
"FirstId" : [ ],
"SecondId" : [ ],
"CreationTime" : [ ]
},
"keyPattern" : {
"FirstId" : 1,
"SecondId" : 1,
"CreationTime" : -1
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"direction" : "forward"
}
}
}
}
}
but the actual result is a COLLSCAN that takes over 8000ms:
"event": {
"dataset": "mongodb.log",
"module": "mongodb"
},
"service": {
"type": "mongodb"
},
"message": "command service.Collection command: find { find: \"Collection\",
filter: { FirstId: \"771367b7-4bef-49ab-bda1-6230254c6349\", SecondId: \"3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f\" }, sort: { CreationTime: -1 }, limit: 1,
planSummary: COLLSCAN keysExamined:0 docsExamined:784787 hasSortStage:1 cursorExhausted:1 numYields:6175 nreturned:1 reslen:677
locks:{ Global: { acquireCount: { r: 12352 } }, Database: { acquireCount: { r: 6176 } }, Collection: { acquireCount: { r: 6176 } } } protocol:op_msg 8441ms",
"mongodb.docsExamined": 784787,
"fileset": {
"name": "log"
},
Why am I COLLSCANing instead of IXSCANing with the FirstIdSecondIDCreationTime compound index? Is there a way to change my index/ my query to speed up the query?
Per a suggestion in the comments, I've run explain("allPlansExecution").
///db.Collection.find({ FirstId: "771367b7-4bef-49ab-bda1-6230254c6349", ///SecondId: "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f" })
/// .projection({})
/// .sort({_id:-1}).explain('allPlansExecution')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "service.Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 5408,
"totalKeysExamined" : 856748,
"totalDocsExamined" : 856748,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"FirstId" : {
"$eq" : "771367b7-4bef-49ab-bda1-6230254c6349"
}
},
{
"SecondId" : {
"$eq" : "3bffb3cd-fb5e-43e5-abd1-e0b48c97f78f"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 4862,
"works" : 856749,
"advanced" : 1,
"needTime" : 856747,
"needYield" : 0,
"saveState" : 6694,
"restoreState" : 6694,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 856748,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 856748,
"executionTimeMillisEstimate" : 1220,
"works" : 856749,
"advanced" : 856748,
"needTime" : 0,
"needYield" : 0,
"saveState" : 6694,
"restoreState" : 6694,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 856748,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
},
"allPlansExecution" : [ ]
}
}

The "FirstIdSecondIdCreationTime" index was not automatically considered because it was created with a collation, and the query is being run without a collation.
Use the .collation() cursor method to specify the same collation for the query that was used for the index.
The 5.5 second run time using that index is pretty slow as well.
You may see some improvement in that query if you create an index on {FirstId: 1, SecondId: 1, _id: 1} so that they query executor can use the index to meet the sort instead of an in-memory sort.

Can you please sort by leading indexes i.e firstId, secondId and creationTime in the same sequence and see index is used. it will give an idea whether leading indexes fields should be there in sort as well.

Related

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

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
}
]

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
}
}
]);

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")
}

Working with Mongodb References inside array next to other content

I want to use the mongodb aggregation framework on 3 Collections that have to "come together" to one Query. The problem is, when I'm referencing to another collection with $lookup it deletes the other content of the array the reference is in.
Heres the collection my aggregation starts in (users):
{
"_id" : ObjectId("5c9bea89f4fe8c37175ade58"),
"kundennummer" : "000001",
"passwort" : "xxx",
"status" : "1",
"onlinestatus" : true,
"kontakt" : {
"email" : "test#test.net"
},
"thing" : [
{
"thing_id" : 2,
"onlinestatus" : false,
"status" : true,
"site" : [
{
"site_id" : 3,
"status": true
},
{
"site_id" : 4,
"status": true
}
],
"refs" : [
{
"thing_id" : 11,
"status" : true
},
{
"thing_id" : 22,
"status" : true
}
]
}
]
}
when I know want site to be extended by the content given in site collection like this:
{
"_id": 11,
"name": "test"
},
{
"_id": 22,
"name": "test2"
}
I tried to use $lookup and the status: true disappeared.
db.users.aggregate([{
$lookup:
{
from: "sites",
localField: "things.site.site_id",
foreignField: "_id",
as: "things.site"
}
}])
edit:
What I want to achieve is the following:
{
"_id" : ObjectId("5c9bea89f4fe8c37175ade58"),
"kundennummer" : "000001",
"passwort" : "xxx",
"status" : "1",
"onlinestatus" : true,
"kontakt" : {
"email" : "test#test.net"
},
"thing" : [
{
"thing_id" : 2,
"onlinestatus" : false,
"status" : true,
"site" : [
{
"site_id" : 11,
"status": true,
"name": "test"
},
{
"site_id" : 12,
"status": true,
"name": "test2"
}
],
"refs" : [
{
"thing_id" : 11,
"status" : true,
"name": "test"
},
{
"thing_id" : 12,
"status" : true,
"name": "test2"
}
]
}
]
}
To use $lookup on the embedded document in MongoDB aggregation you need to use $unwind. It will output a document for each element and then you can use $lookup. You will get results from sites as well with the help of the below query:
db.user.aggregate([
{
$unwind: "$thing"
},
{
$unwind: "$thing.site"
},
{
$unwind: "$thing.refs"
},
{
$lookup: {
from: 'sites',
let: { 'siteId': '$thing.site.site_id' },
pipeline: [
{
$match: {
$expr: {
$eq: ['$_id', '$$siteId']
}
}
},
],
as: 'siteObject'
}
},
{
$lookup: {
from: 'things',
let: { 'thingId': '$thing.refs.thing_id' },
pipeline: [
{
$match: {
$expr: {
$eq: ['$_id', '$$thingId']
}
}
},
],
as: 'thingObject'
}
},
{
$unwind: "$siteObject"
},
{
$unwind: "$thingObject"
},
{
$project: {
"_id" : 1,
"kundennummer" : 1,
"passwort" : 1,
"status" : 1,
"onlinestatus" : 1,
"kontakt" : 1,
"thing": [{
"thing_id" : "$thing.thing_id",
"onlinestatus" : "$thing.onlinestatus",
"status" : "$thing.status",
"site" : {
"site_id":"$thing.site.site_id",
"status":"$thing.site.status",
"siteName":"$siteObject.siteName",
},
"refs" : {
"thing_id":"$thing.refs.thing_id",
"status":"$thing.refs.status",
"siteName":"$thingObject.thingName",
},
}]
}
},
{
$unwind: "$thing"
},
{
$group: {
_id: {
"_id": "$_id",
"kundennummer": "$kundennummer",
"passwort": "$passwort",
"status":"$status",
"onlinestatus":"$onlinestatus",
"kontakt":"$kontakt"
},
thing: { $push: { thing_id: "$thing.thing_id", onlinestatus: "$thing.onlinestatus", status: "$thing.status",site:"$thing.site",refs: "$thing.refs" } }
}
}
])
This will result as below:
{
"_id" : {
"_id" : ObjectId("5c9bea89f4fe8c37175ade58"),
"kundennummer" : "000001",
"passwort" : "xxx",
"status" : "1",
"onlinestatus" : true,
"kontakt" : {
"email" : "test#test.net"
}
},
"thing" : [
{
"thing_id" : 2,
"onlinestatus" : false,
"status" : true,
"site" : {
"site_id" : ObjectId("5caf395e512ab5123bb4b0af"),
"status" : true,
"siteName" : "Moto"
},
"refs" : {
"thing_id" : ObjectId("5cb042ea512ab5123bb4b0b0"),
"status" : true,
"siteName" : "hi"
}
},
{
"thing_id" : 2,
"onlinestatus" : false,
"status" : true,
"site" : {
"site_id" : ObjectId("5caf395e512ab5123bb4b0af"),
"status" : true,
"siteName" : "Moto"
},
"refs" : {
"thing_id" : ObjectId("5cb042ea512ab5123bb4b0b1"),
"status" : true,
"siteName" : "world"
}
},
{
"thing_id" : 2,
"onlinestatus" : false,
"status" : true,
"site" : {
"site_id" : ObjectId("5caf395e512ab5123bb4b0ae"),
"status" : true,
"siteName" : "hello"
},
"refs" : {
"thing_id" : ObjectId("5cb042ea512ab5123bb4b0b0"),
"status" : true,
"siteName" : "hi"
}
},
{
"thing_id" : 2,
"onlinestatus" : false,
"status" : true,
"site" : {
"site_id" : ObjectId("5caf395e512ab5123bb4b0ae"),
"status" : true,
"siteName" : "hello"
},
"refs" : {
"thing_id" : ObjectId("5cb042ea512ab5123bb4b0b1"),
"status" : true,
"siteName" : "world"
}
}
]
}
Result is near by your desired result and i think you should not follow such schema it will make your every query more complex.

mongodb 2.6.3 use wrong index

I have a query like below.Obviously the better index is "platform_1_keyuserAccountID_1_weiboAccountID_1_postTime_1",but mongodb choose "weiboAccountID_1",am i make something wrong?
db.inbox_weibo.find({platform: "sina", keyuserAccountID:"1665337047", weiboAccountID: "2271338624"}).explain(true);
{
"cursor" : "BtreeCursor weiboAccountID_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 24,
"nscannedAllPlans" : 634425,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 2912,
"indexBounds" : {
"weiboAccountID" : [
[
"2271338624",
"2271338624"
]
]
},
"allPlans" : [
{
"cursor" : "BtreeCursor weiboAccountID_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"weiboAccountID" : [
[
"2271338624",
"2271338624"
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_dealed_1_operatorID_1_weiboAccountID_1_postTIme_-1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 62,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"operatorID" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"weiboAccountID" : [
[
"2271338624",
"2271338624"
]
],
"postTIme" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_weiboAccountID_1_postTime_-1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"weiboAccountID" : [
[
"2271338624",
"2271338624"
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor platform_keyuserAccountID_dealed_postTime_weiboAccountID",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 634331,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"weiboAccountID" : [
[
"2271338624",
"2271338624"
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_mid_1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"mid" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_dealerID_1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealerID" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor distinctAccountAgg",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"operatorID" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor fansCountUndealed",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"fromType" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"fansCount" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"usePicture" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor retweetCountUndealed",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"fromType" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"sourceRetweetCount" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"usePicture" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor interactUndealed",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"fromType" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"userInteractionCount" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"usePicture" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_dealed_1_dealTime_-1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"dealTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_dealerID_1_postTime_-1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealerID" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor platform_1_keyuserAccountID_1_postTime_-1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"platform" : [
[
"sina",
"sina"
]
],
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"postTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor keyuserAccountID_dealed_createTime_-1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 2,
"nscanned" : 3,
"scanAndOrder" : false,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"keyuserAccountID" : [
[
"1665337047",
"1665337047"
]
],
"dealed" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"createTime" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
}
}
I don't think the other index is "better". It seems that both indexes (the one you would suggest and the one mongodb uses) return the queried object with "nscanned:1", so they are equally perfect for this query. I say that since "weiboAccountID" in your test dataset defines exactly the one record you are looking for, there is no need for other indexes in this case - mongodb will choose the first good fit. Try adding more records with this same exact weiboAccountID (if duplicated Ids are at all valid in your dataset) and re-run the query, see how it changes the execution.

Resources