Skip to content

Projection of fields in nested lists #4428

@fkreis

Description

@fkreis

Dear spring-data-mongodb maintenance team,
I am having trouble with the projection of fields in nested lists with spring-data-mongodb.

Given the following minimal example mongoDB:

db.nestedList.insertOne(
    {
      "flat": 1,
      "flatDescription": "one",
      "list": [
        {
          "element": 11,
          "description": "eleven"
        },
        {
          "element": 12,
          "description": "twelve"
        }
      ]
    }
 );
 db.nestedList.insertOne(
    {
      "flat": 2,
      "flatDescription": "two",
      "list": [
        {
          "element": 21,
          "description": "twentyone"
        },
        {
          "element": 22,
          "description": "twentytwo"
        }
      ]
    }
 );

Let's assume I only want to know about the fields "flat" and all "list.element". In mongoDB I can simply execute

db.nestedList
    .find({})
   .projection({ flat: 1, "list.element" : 1})

with the result

{
	"_id" : ObjectId("649a8045da17a6faee05e306"),
	"flat" : 1,
	"list" : [
		{
			"element" : 11
		},
		{
			"element" : 12
		}
	]
},

{
	"_id" : ObjectId("649a80a9da17a6faee05e307"),
	"flat" : 2,
	"list" : [
		{
			"element" : 21
		},
		{
			"element" : 22
		}
	]
}

This is exactly my expected and desired behavior!

Now my question is: How can I achieve this exact behavior with Spring Data (Java)?

The intuitive approach

ProjectionOperation projection = Aggregation.project("flat", "list.element");

generates

{ "flat" : "$flat", "element" : "$list.element"}

which produces

{
	"_id" : ObjectId("649a8045da17a6faee05e306"),
	"flat" : 1,
	"element" : [ 11, 12 ]
},
{
	"_id" : ObjectId("649a80a9da17a6faee05e307"),
	"flat" : 2,
	"element" : [ 21, 22 ]
}

which is obviously not what I need, as element is now a property in the root object and also is an array.

Slightly better

ProjectionOperation projection = Aggregation.project("flat");
projection = projection.and("list.element").as("list.element");

generates

{ "flat" : "$flat", "list.element" : "$list.element"}

which produces

{
	"_id" : ObjectId("649a8045da17a6faee05e306"),
	"list" : [
		{
			"element" : [ 11, 12 ]
		},
		{
			"element" : [ 11, 12 ]
		}
	],
	"flat" : 1
},
{
	"_id" : ObjectId("649a80a9da17a6faee05e307"),
	"list" : [
		{
			"element" : [ 21, 22 ]
		},
		{
			"element" : [ 21, 22 ]
		}
	],
	"flat" : 2
}

which is still wrong. At list the structure is correct now but list.element are still arrays.

I even tried

ProjectionOperation projection = Aggregation.project("flat");
projection = projection.and("list").nested(Fields.fields("list.element"));

generates

{ "_id" : "$_id", "list" : { "element" : "$list.element"}}

which produces

{
	"list" : [
		{
			"element" : [ 11, 12 ]
		},
		{
			"element" : [ 11, 12 ]
		}
	],
	"_id" : ObjectId("649a8045da17a6faee05e306")
},
{
	"list" : [
		{
			"element" : [ 21, 22 ]
		},
		{
			"element" : [ 21, 22 ]
		}
	],
	"_id" : ObjectId("649a80a9da17a6faee05e307")
}

which is still wrong as list.element are arrays.

Is this a bug or am I just using it wrong? In the latter case, can you please explain the proper usage? :)
I am looking forward to you response!

Kind regards,
fkreis

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions