Search code examples
phpmongodblaraveljenssegers-mongodb

How do I extract subdocument in laravel mongodb


Hello Good Developers,

I am using jenssegers/laravel-mongodb package to query my MongoDB from Laravel.

Here's Fiddle for my query: https://mongoplayground.net/p/qzbNN8Siy-3

I have following JSON

[{
    "id": "GLOBAL_EDUCATION",
    "general_name": "GLOBAL_EDUCATION",
    "display_name": "GLOBAL_EDUCATION",
    "profile_section_id": 0,
    "translated": [
      {
        "con_lang": "US-EN",
        "country_code": "US",
        "language_code": "EN",
        "text": "What is the highest level of education you have completed?",
        "hint": null
      },
      {
        "con_lang": "US-ES",
        "country_code": "US",
        "language_code": "ES",
        "text": "\u00bfCu\u00e1l es su nivel de educaci\u00f3n?",
        "hint": null
      }...
    {
     ....
    }
]

I am trying to run following command

db.collection.find({ 'id': "GLOBAL_EDUCATION" },{_id:0, id:1, general_name:1, translated:{ $elemMatch: {con_lang: "US-EN"} }})

Expecting result like this

[
  {
    "general_name": "GLOBAL_EDUCATION",
    "id": "GLOBAL_EDUCATION",
    "translated": [
      {
        "con_lang": "US-EN",
        "country_code": "US",
        "hint": null,
        "language_code": "EN",
        "text": "What is the highest level of education you have completed?"
      }
    ]
  }
]

Everything is fine while query directly in MoDB but issue arise when I am trying this in Laravel. I've tried every possible known function from MongoDB package. but Not able to do this. here's my Array

$findArray = [
        [
            'id' => "GLOBAL_EDUCATION",
        ],
        [
            '_id' => 0,
            'id' => 1,
            'general_name' => 1,
            'translated' => [
                '$elemMatch' => ['con_lang' => "US-EN"]
            ],
        ]
];

$model = GlobalQuestions::raw()->find($findArray) //OR
$data = GlobalQuestions::raw(function($collection) use ($findArray){
        return $collection->find($findArray);
});

What I am doing wrong here, is this kind of Find() not possible here and I've to do this by aggregation?


Solution

  • Since no-one answered this, I am posting the solution if someone is having the same issue. Doing some more R&D on the same I was able to do this using where and Project as well by Aggregation Pipelines.

    ----- Using Where() and Project() ------

    $projectArray = [
        '_id' => 0,
        'id' => 1,
        'general_name' => 1,
        'translated' => [
            '$elemMatch' => ['con_lang' => "FR-FR"]
        ],
    ];
    
    $data = GlobalQuestions::where('id', '=', 'GLOBAL_EDUCATION')
        ->project($projectArray)
        ->get();
    

    --- Using Aggregation and $unwind ---

    $data = GlobalQuestions::raw(function($collection) {
        return $collection->aggregate([
            [
                '$match' => [
                    'id' => "GLOBAL_EDUCATION"
                ]
            ],
            [
                '$unwind' => '$translated',
            ],
            [
                '$match' => [
                    'translated.con_lang' => "US-EN"
                ]
            ],
            [
                '$project' => [
                    '_id'=> 0,
                    'id'=> 1,
                    'general_name' => 1,
                    'translated' => 1,
                ]
            ]
        ]);
    })->first();