question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Finding credentials by tenant-id, auth-id and type does not use MongoDb index

See original GitHub issue

The MongoDbDocumentBuilder class uses MongoDb’s $elemMatch operator for filtering credentials by tenant-id, auth-id and type. For this purpose an index on those fields was created. When using MongoDb’s explain it turned out that this index is in fact not used:

db.getCollection('device-credentials').find({
    "tenant-id": "foobar",
    "credentials": {
      "$elemMatch": {
        "auth-id": "spamegg",
        "type": "hashed-password"
      }
    }
  }).explain()
  
# RETURNS
{
    "queryPlanner" : {
        ...
        },
        "winningPlan" : {
            ...
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "tenant-id" : 1,
                    "device-id" : 1
                },
                "indexName" : "tenant-id_1_device-id_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "tenant-id" : [],
                    "device-id" : []
                },
                "isUnique" : true,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "tenant-id" : [ 
                        "[\"foobar\", \"foobar\"]"
                    ],
                    "device-id" : [ 
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans" : []
    },
    ...
}

Actually an index on tenant-id and device-id is used and a scan is done for all device ids (see the “[MinKey, MaxKey]” value for “device-id”.

As far as I can see there is no need to the $elemMatch operator for this query as it is only a simple match of two values and not more complicated match resorting to other MongoDb funtions ($gt, $and, $or,…).

If the query is done without the $elemMatch operator the index is used as expected:

db.getCollection('device-credentials').find({
    "tenant-id": "foobar",
    "credentials.auth-id": "spamegg",
    "credentials.type": "hashed-password"
  }).explain()
  
# RETURNS
{
    "queryPlanner" : {
        ...
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "credentials.type" : {
                    "$eq" : "hashed-password"
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "tenant-id" : 1,
                    "credentials.auth-id" : 1,
                    "credentials.type" : 1
                },
                "indexName" : "tenant-id_1_credentials.auth-id_1_credentials.type_1",
                "isMultiKey" : true,
                "multiKeyPaths" : {
                    "tenant-id" : [],
                    "credentials.auth-id" : [ 
                        "credentials"
                    ],
                    "credentials.type" : [ 
                        "credentials"
                    ]
                },
                "isUnique" : true,
                "isSparse" : false,
                "isPartial" : true,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "tenant-id" : [ 
                        "[\"foobar\", \"foobar\"]"
                    ],
                    "credentials.auth-id" : [ 
                        "[\"spamegg\", \"spamegg\"]"
                    ],
                    "credentials.type" : [ 
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ 
            ...
        ]
    },
    ...
}

From https://github.com/eclipse/hono/commit/d75a28e7276a055fd5dc72264f8016355cb80223 I understand that the $elemMatch operator was used since the credentials to be returned should not contain sensitive information. Hence MongoDb’s projection operator was used. This did not work with a “plain” filter which is why the $elemMatch operator was introduced.

Since the result set returned by the query should usually be only one credential (consequently there’s no big advantage using the projection so that traffic is reduced), I think that commit could be reverted and the sensitive fields could be removed “in code”.

WDYT?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:19 (19 by maintainers)

github_iconTop GitHub Comments

1reaction
sophokles73commented, Jul 27, 2021

Ok, it is not a partial index. So, we need the unique index on (tenant-id,auth-id,type) in order to enforce the existing constraints when adding credentials and we can use your new index to speed up querying 😃

1reaction
sophokles73commented, Jul 27, 2021

Nice idea. Execution time will mostly depend on the number of tenants that contain credentials with the same (auth-id,type) tuple then. But IMHO we can assume that to be not that many.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Indexes — MongoDB Manual
In sharded clusters, if you do not use the _id field as the shard key, ... MongoDB provides a text index type that...
Read more >
How to connect using user id and password - MongoDB
Hi, We do have environment in mongoDB 4.2 ,redhad 7 . As per the user request as a admin we have created the...
Read more >
db.auth() — MongoDB Manual
Starting in MongoDB 4.4, if you use the db.auth(<username>, <password>) syntax and omit the password, the user is prompted to enter a password....
Read more >
Authentication Mechanisms — Go - MongoDB
The Go Driver establishes a connection with an authentication mechanism through a Client type. The Client type specifies the mechanism and credentials to...
Read more >
MongoDB Authentication
How to Enable Authentication in MongoDB ; Locate the following code in the mongod configuration file ( /etc/mongod.conf ). security: authorization: "disabled".
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found