0

Je dois générer un résultat avec le nombre d'alertes de chaque niveau pour chaque utilisateur.Groupe imbriqué avec Spring MongoDB

Une structure similaire à ce qui suit:

{ 
    "identitity": "59e3b9dc5a3254691f327b67", 
    "alerts": [ 
    { 
     "level": "INFO", 
     "count": "3" 
    }, 
    { 
     "level": "ERROR", 
     "count": "10" 

    } 
    ] 

} 

Le entitity alerte a la structure suivante:

@Document(collection = AlertEntity.COLLECTION_NAME) 
public class AlertEntity { 

    public final static String COLLECTION_NAME = "alerts"; 

    @Id 
    private ObjectId id; 

    @Field 
    private AlertLevelEnum level = AlertLevelEnum.INFO; 

    @Field("title") 
    private String title; 

    @Field("payload") 
    private String payload; 

    @Field("create_at") 
    private Date createAt = new Date(); 

    @Field("delivered_at") 
    private Date deliveredAt; 

    @Field("delivery_mode") 
    private AlertDeliveryModeEnum deliveryMode = 
    AlertDeliveryModeEnum.PUSH_NOTIFICATION; 

    @Field("parent") 
    @DBRef 
    private ParentEntity parent; 

    @Field("son") 
    @DBRef 
    private SonEntity son; 

    private Boolean delivered = Boolean.FALSE; 

} 

J'ai mis en œuvre la méthode suivante a essayé de projeter le résultat d'une manière imbriquée. Mais le champ "Identity" est toujours nul et le champ "alerts" est une collection vide.

@Override 
    public List<AlertsBySonDTO> getAlertsBySon(List<String> sonIds) { 


     TypedAggregation<AlertEntity> alertsAggregation = 
       Aggregation.newAggregation(AlertEntity.class, 
        Aggregation.group("son.id", "level").count().as("count"), 
        Aggregation.project().and("son.id").as("id") 
         .and("alerts").nested(
           bind("level", "level").and("count"))); 

     // Aggregation.match(Criteria.where("_id").in(sonIds) 

      AggregationResults<AlertsBySonDTO> results = mongoTemplate. 
       aggregate(alertsAggregation, AlertsBySonDTO.class); 

      List<AlertsBySonDTO> alertsBySonResultsList = results.getMappedResults(); 

      return alertsBySonResultsList; 
    } 

Le résultat que je reçois est la suivante:

{ 
    "response_code_name": "ALERTS_BY_SON", 
    "response_status": "SUCCESS", 
    "response_http_status": "OK", 
    "response_info_url": "http://yourAppUrlToDocumentedApiCodes.com/api/support/710", 
    "response_data": [ 
    { 
     "identity": null, 
     "alerts": [] 
    }, 
    { 
     "identity": null, 
     "alerts": [] 
    } 
    ], 
    "response_code": 710 
} 

Le résultat DTO est la suivante:

public final class AlertsBySonDTO implements Serializable { 

    private static final long serialVersionUID = 1L; 


    @JsonProperty("identity") 
    private String id; 

    @JsonProperty("alerts") 
    private ArrayList<Map<String, String>> alerts; 


    public AlertsBySonDTO() { 
     super(); 
    } 

    public AlertsBySonDTO(String id, ArrayList<Map<String, String>> alerts) { 
     super(); 
     this.id = id; 
     this.alerts = alerts; 
    } 



    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public ArrayList<Map<String, String>> getAlerts() { 
     return alerts; 
    } 

    public void setAlerts(ArrayList<Map<String, String>> alerts) { 
     this.alerts = alerts; 
    } 
} 

Ce qui doit être fait pour projeter le résultat d'une manière imbriquée?

Merci à l'avance

Répondre

1

Dans le cadre d'agrégation il y a un $unwind opérateur qui transformera fondamentalement votre collection un élément avec tableau imbriqué de deux éléments à deux documents distincts avec un élément de ce tableau. Donc, vous obtiendrez:

{ 
"identitity": "59e3b9dc5a3254691f327b67", 
"alerts": { 
    "level": "INFO", 
    "count": "3" 
    } 

}

{ 
    "identitity": "59e3b9dc5a3254691f327b67", 
    "alerts": { 
     "level": "ERROR", 
     "count": "10" 
    } 
} 

Et c'est là, vous pouvez commencer votre groupe en avec le comte. Ça devrait bien fonctionner.