PHP - MongoDB:使用数组中的字段名称从子文档中检索字段

Consider an Array

$lettersArray = [A,C,E,G]

and my MongoDB Collection has the following structure.

{
    Collection : {
        letters:{
            A:{...},
            B:{...},
            ...
            Z:{...}
        }

    }
}

Consider that the Letter Sub document is a part of a larger collection. Hence I am using Aggregation. Right Now I have tried to project -

['$Collection.letters' => ['$elemMatch' => ['$in' => $lettersArray]]

and also tried

['Letters' => ['$in' => [$lettersArray,'$Collection.letters']]

But it didn't work.

In the End, I want result like the following:

 [
     Collection => [
        letters => [
            A => [...],
            C => [...],
            E => [...],
            G => [...]
        ]
    ]
]

Is there any way to do this?

In PHP you can use array_combine with array_fill to create the empty arrays.

$lettersArray = ['A','C','E','G'];

$letters = array_combine($lettersArray, array_fill(0,count($lettersArray), []));

Array_fill creates an array from index 0, to the count of items in $lettersArray with the contents []

Output:

array(4) {
  ["A"]=>
  array(0) {
  }
  ["C"]=>
  array(0) {
  }
  ["E"]=>
  array(0) {
  }
  ["G"]=>
  array(0) {
  }
}

https://3v4l.org/TeoFv

I think you are mistaken in the way you are trying to access the documents' information.

If you take a look at your MongoDB document, you will see that it is in fact not an array, so you should not use $elemMatch to project these fields, but simple projections. In your case, you should project in this way:

[
    '$project' => [
        'Collection.letters.A' => 1,
        'Collection.letters.C' => 1,
        'Collection.letters.E' => 1,
        'Collection.letters.G' => 1
    ]
]

By the way, you don't need to use the aggregation framework to compute such a projection. You could just use find(), and use the projection in the options, which are the functions' second argument:

myCollection->find(query, [
    'projection' => [
        'Collection.letters.A' => 1,
        'Collection.letters.C' => 1,
        'Collection.letters.E' => 1,
        'Collection.letters.G' => 1
    ]
]);

Cheers,

Charles