Search code examples
mongodbmongodb-querymongodb-indexes

MongoDB: How to index unknown fields


We're storing documents with a undefined structure. I mean, it has a basic structure (id, user and creationTimestamp), but is also there a Map<String, Object> values fields, where we are able to store whichever structure:

public class Metadata {
    private String id;
    private String user;
    private Date creationTimestamp;
    private Map<String, Object> values;
}

Example:

> db.metadata.find();
{
    "_id" : "Doc2Ref2Mdt1",
    "user" : "user1",
    "creationTimestamp" : ISODate("2018-09-24T12:20:56.958Z"),
    "values" : {
        "ambit" : "ctti",
        "departament" : "economia"
    }
},
{
    "_id" : "Doc1Ref2Mdt1",
    "user" : "user2",
    "creationTimestamp" : ISODate("2018-09-24T12:20:56.169Z"),
    "values" : {
        "date" : ISODate("2018-09-24T12:20:56.171Z"),
        "number" : 16,
        "address" : {
        "street" : "Av. Diagonal",
        "location" : "barcelona",
        "credentials" : [
        {
            "password" : "pwd",
            "login" : "main"
        },
        {
            "password" : "pwd",
            "login" : "other",
            "creation" : ISODate("2018-09-24T12:20:56.171Z")
        }],
        "contact" : "contact name",
        "tags" : ["tag1", "tag2"}]
    }
}

So, you can see values can store any structure.

I need to know if mongodb is able to automatically index all of them.

I mean, when a new field is "added" into values, for example, values.newfield it is indexed automatically.

Any ideas?


Solution

  • From version 4.2 MongoDB now supports so-called wildcard indices.

    Assume you collect objects with the following structure

    { "userMetadata" : { "likes" : [ "dogs", "cats" ] } }
    { "userMetadata" : { "dislikes" : "pickles" } }
    { "userMetadata" : { "age" : 45 } }
    { "userMetadata" : "inactive" }
    

    You can add this index:

    db.userData.createIndex( { "userMetadata.$**" : 1 } )
    

    This index will support queries like these:

    db.userData.find({ "userMetadata.likes" : "dogs" })
    db.userData.find({ "userMetadata.dislikes" : "pickles" })
    db.userData.find({ "userMetadata.age" : { $gt : 30 } })
    db.userData.find({ "userMetadata" : "inactive" })
    

    You can check the documentation as well. https://docs.mongodb.com/manual/core/index-wildcard/