Sachin Sachin - 21 days ago 6
Java Question

Spring Aggregate representation of mongodb query

Can some one show me the Spring representation of below query.

db.groupsDocument.aggregate(
{$unwind:"$groups"},
{$match:{"groups.students":"8b8a7464-4dff-4136-ab0f-ec2bfe1ec48e"}},
{$group:{ _id:"$_id",groups:{$push:"$groups"},createdDate:{$first:"$createdDate"},editedDate:{$first:"$editedDate"},editedBy:{$first:"$editedBy"}}})


Above query is working file.

I tried below code but it is not working. It is throwing error "No property _id found for type GroupsDocument!"

GroupOperation groupOperation=Aggregation.group("$_id").push("$groups").as("groups").first("$createdDate").as("createdDate")
.first("$editedDate").as("editedDate")
.first("$editedBy").as("editedBy");

Aggregation aggregation = Aggregation.newAggregation(
Aggregation.unwind("$groups"),
Aggregation.match(where("_id.teacherId").is("5").and("groups.students").in("11")),
groupOperation);

AggregationResults<BasicDBObject> groupResults = groupsMongoTemplate.aggregate(aggregation,
GroupsDocument.class, BasicDBObject.class);


My id in the document contains two fields as shown below

"_id" : { "teacherId" : "1", "Year" : "2016" }


Document structure

{
"_id" : { "teacherId" : "1", "Year" : "2016" },
"groups" : [ {
"groupId" : "123",
"groupName" : "Test1",
"groupNameLowerCase" : "test1",
"description" : "sample document",
"students" : ["11", "22"]
},
{
"groupId" : "234",
"groupName" : "Test2",
"groupNameLowerCase" : "test2",
"description" : "sample document",
"students" : ["11", "22"]
},
{
"groupId" : "345",
"groupName" : "Test3",
"groupNameLowerCase" : "test3",
"description" : "sample document",
"students" : ["21", "32"]
}
],
"editedBy" : "sachin",
"createdDate":"11/11/2016"
"editedDate":" 11/14/2016"

}


CLASS:

@Document
public class GroupsDocument extends AbstractDocument {

/**
* document _id and shard key
*
* composite key: Teacherid, Year
*/
@Id
@Field(FieldDefinition.DOCUMENT_ID)
private final GroupsDocumentId GroupsDocumentId;

@Field(FieldDefinition.GROUPS)
private final Collection<Group> groups;

@Field(GroupsDocument.FieldDefinition.CREATED_DATE)
private final Date createdDate;

@Field(GroupsDocument.FieldDefinition.EDITED_DATE)
private Date editedDate;

@Field(GroupsDocument.FieldDefinition.EDITED_BY)
private String editedBy;

/**
* empty constructor
*/
@SuppressWarnings("unused")
public GroupsDocument() {
this(null, null, Collections.emptyList(), null, null);
}


public GroupsDocument(String teacherId, String year, Collection<Group> groups, String editedBy) {
this(teacherId, year, groups, new Date(), editedBy);
}

public GroupsDocument(
String teacherId, String year, Collection<Group> groups, Date createdDate, String editedBy) {
this.GroupsDocumentId = new GroupsDocumentId(teacherId, year);
this.groups = groups;
this.createdDate = createdDate;
this.editedDate = this.createdDate;
this.editedBy = editedBy;
}

public GroupsDocumentId getGroupsDocumentId() {
return GroupsDocumentId;
}

public Collection<Group> getGroups() {
return groups;
}

public Date getEditedDate() {
return editedDate;
}

public Date getCreatedDate() {
return createdDate;
}

public void setEditedDate(Date editedDate) {
this.editedDate = editedDate;
}

public String getEditedBy() {
return editedBy;
}

public void setEditedBy(String editedBy) {
this.editedBy = editedBy;
}


Id class:

public class GroupsDocumentId extends AbstractDocument {

@Field(GroupsDocument.FieldDefinition.teacherId)
private final String teacherId;

@Field(GroupsDocument.FieldDefinition.year)
private final String year;

/**
* empty constructor
*/
@SuppressWarnings("unused")
public GroupsDocumentId() {
this(null, null);
}

public GroupsDocumentId(String teacherId, String year) {
this.teacherId = teacherId;
this.year = year;
}

public String getteacherId() {
return teacherId;
}

public String getyear() {
return year;
}

Answer

Change private final GroupsDocumentId GroupsDocumentId to private final GroupsDocumentId _id for spring mapping context to bind the id variable to the GroupDocumentId type in GroupsDocument class.

Alternatively, you can use this aggregate variant to bypass type checking.

 AggregationResults<BasicDBObject> groupResults = mongoTemplate.aggregate(aggregation,
            "groupsDocument, BasicDBObject.class);