关注我的Mongo查询
{$project:{
id:"$_id",
login:"$login",
firstName: "$firstName",
lastName:"$lastName",
email:"$email",
deactivateFlag:"$deactivateFlag",
lastActivity:"$lastActivity",
company :"$organization.name",
RoleName :"$organization.roles.roleName",
isMatchingRoles: { $eq: [ "$organization.roles.orgRoleId","$userOrgMap.roleId" ] }
}
},
{ $match: {isMatchingRoles:true},
这完全没问题。特别是最后一场$ match完美地减少了重复。但是当我试图将上面的代码转换为Spring数据等价时,我面临着以下问题。
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.rangeCheck(ArrayList.java:653) at java.util.ArrayList.get(ArrayList.java:429) at java.util.Collections$UnmodifiableList.get(Collections.java:1309)
以下是我的Spring数据代码。我打印了原始输出,碰巧得到了isMatchingRoles的布尔值,这是我的bean类的一部分,它在聚合期间被映射。但是当使用getMappedResult对布尔值进行映射时,我遇到了这个问题。
aggregation = newAggregation(
match(getUsersCriteria(searchTxt)),
unwind("userOrgMap"),
lookup("organizations", "userOrgMap.orgId", "_id", "organization"),
unwind("organization"),
unwind("organization.roles"),
project("userId", "login", "firstName", "lastName", "email", "deactivateFlag", "lastActivity")
.and("organization.name").as("companyName")
.and("organization.roles.roleName").as("roleName")
.and(when(where("organization.roles.orgRoleId").is("userOrgMap.roleId")).then(true).otherwise(false)).as("isMatchingRoles"),
match(Criteria.where("isMatchingRoles").is(true))
AggregationResults<UserDTO> groupResults groupResults = mongoOperation.aggregate(aggregation, UserDTO.class, UserDTO.class);
System.out.println(" Raw result "+groupResults.getMappedResults().get(0));
// The above result is getting data properly for isMatchingRoles
List<UserDTO> result = groupResults.getMappedResults();
// I am getting the exception in the above code
System.out.println(" actual mapped Reesult "+result.size());
以下是我的输入类
@Document(collection = "users")
public class UserDTO {
@Id
private String userId;
private String login;
private String firstName;
private String lastName;
private String lastActivity;
private String email;
private boolean deactivateFlag;
private String companyName;
private String roleName;
private boolean isMatchingRoles;
public UserDTO(String userId, String login, String firstName, String lastName, String lastActivity, String email,
boolean deactivateFlag, String companyName, String roleName, boolean isMatchingRoles) {
super();
this.userId = userId;
this.login = login;
this.firstName = firstName;
this.lastName = lastName;
this.lastActivity = lastActivity;
this.email = email;
this.deactivateFlag = deactivateFlag;
this.companyName = companyName;
this.roleName = roleName;
this.isMatchingRoles = isMatchingRoles;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastActivity() {
return lastActivity;
}
public void setLastActivity(String lastActivity) {
this.lastActivity = lastActivity;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isDeactivateFlag() {
return deactivateFlag;
}
public void setDeactivateFlag(boolean deactivateFlag) {
this.deactivateFlag = deactivateFlag;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public boolean isMatchingRoles() {
return isMatchingRoles;
}
public void setMatchingRoles(boolean isMatchingRoles) {
this.isMatchingRoles = isMatchingRoles;
}
}
以下是我的样本集
user collection
{
"_id" : "123",
"login" : "abc@abc.com",
"firstName" : "xxx",
"lastName" : "yyy",
"email" : "abc@abc.com",
"deactivateFlag" : false,
"userOrgMap" : [
{
"orgId" : "999",
"roleId" : "888"
}
]
}
Organization collection
{
"_id" : "999",
"name" : "orgName",
"roles" : [
{
"orgRoleId" : "888",
"roleName" : "Standard User"
},
{
"orgRoleId" : "777",
"roleName" : "Company Administrator"
}
]
}
答案 0 :(得分:0)
你正在使用(CriteriaDefinition)
api(不确定为什么在投影中暴露这个,可能是因为聚合运算符确实与查询运算符共享它的一些函数)来生成条件表达式,应该用于常规查询表达式(用于$match
阶段和常规查找查询)。
标准定义api生成以下查询。
"isMatchingRoles": {
"$cond": {
"if": {
"$eq": ["$organization.roles.orgRoleId", "userOrgMap.roleId"]
},
"then": true,
"else": false
}
}
注意$eq
的第二个参数是字符串值而不是字段引用。
您可以通过以下两种方式完成此操作。
使用ConditonalOperator
api。
.and(when(ComparisonOperators.Eq.valueOf("organization.roles.orgRoleId").equalTo("userOrgMap.roleId")).then(true).otherwise(false)).as("isMatchingRoles")
使用AggregationExpression
生成条件表达式。
and(new AggregationExpression() {
@Override
public DBObject toDbObject(AggregationOperationContext context) {
return new BasicDBObject("$cond",
Arrays.<Object>asList(
new BasicDBObject("$eq",
Arrays.asList("$organization.roles.orgRoleId", "$userOrgMap.roleId")),
true,
false));
}
}).as("isMatchingRoles");