Search code examples
mongodbnestedmongodb-querysubdocument

How to Search MongoDB Nested Subdocuments Within Different Deeps


I'm having some subdocument in MongoDB that occasionally include different types - string, another subdocument, another nested subdocument etc. I'm trying to build a query that will search within this subdocument content regardless of it's type.

Given the following documents:

{ name: "test1", content: "test contents"}
{ name: "test2", content: {family: "tests family content", last: "another test content"} }
{ name: "test3", content: {subdocument: {family: "super family contents", last: "last test content"} } }

I want to use a query that will search within all strings within all documents and subdocuments. Already tried the following query, but it returns only the most nested level of subdocument - content.subdocument.family:

{ $or: [
    {"content": {'$regex': '.*conten.*', '$options': 'i'}},
    {"content.family": {'$regex': '.*conten.*', '$options': 'i'}},
    {"content.last": {'$regex': '.*conten.*', '$options': 'i'}},
    {"content.subdocument.family": {'$regex': '.*conten.*', '$options': 'i'}},
    {"content.subdocument.last": {'$regex': '.*conten.*', '$options': 'i'}}
]}

Is it possible to create one query that will iterate over all nested strings\deeps at once?


Solution

  • Here you are missing syntax of $or in $regex. You should use $or like following:

    db.collection.find({
        $or: [{
        "content": {
            '$regex': '.*conten.*',
            '$options': 'i'
        }
        }, {
        "content.family": {
            '$regex': '.*conten.*',
            '$options': 'i'
        }
        }, {
        "content.last": {
            '$regex': '.*conten.*',
            '$options': 'i'
        }
        }, {
        "content.subdocument.family": {
            '$regex': '.*conten.*',
            '$options': 'i'
        }
        }, {
        "content.subdocument.last": {
            '$regex': '.*conten.*',
            '$options': 'i'
        }
        }]
    })
    

    Edit:

    Above query gives following result:

    [{
        "_id": ObjectId("55f41b6aef4766c946112a2d"),
        "name": "test1",
        "content": "test contents"
    }, {
        "_id": ObjectId("55f41b6aef4766c946112a2e"),
        "name": "test2",
        "content": {
        "family": "tests family content",
        "last": "another test content"
        }
    }, {
        "_id": ObjectId("55f41b6aef4766c946112a2f"),
        "name": "test3",
        "content": {
        "subdocument": {
            "family": "super family contents",
            "last": "last test content"
        }
        }
    }]