0

Ich muss ein Ergebnis mit der Anzahl der Warnungen für jeden Level für jeden Benutzer generieren.Verschachtelte Gruppe mit Spring MongoDB

Eine Struktur ähnlich der folgenden:

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

    } 
    ] 

} 

Der Alarm entitity hat die folgende Struktur:

@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; 

} 

ich die folgende Methode implementiert haben versucht, das Ergebnis in einer verschachtelten Art und Weise zu projizieren. Aber das Feld "Identity" ist immer null und das Feld "Alerts" ist eine leere Sammlung.

@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; 
    } 

Das Ergebnis, das ich bekommen ist folgende:

{ 
    "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 
} 

Das Ergebnis DTO ist wie folgt:

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; 
    } 
} 

Was getan werden muss, um das Ergebnis in einer verschachtelten Art und Weise zu projizieren?

Vielen Dank im Voraus

Antwort

1

In Aggregations Rahmen gibt es einen $unwind Operator, der im Grunde Ihre ein Element Sammlung mit verschachtelten Array aus zwei Elementen zu zwei separaten Dokumenten mit einem Elemente aus diesem Array verwandeln. So erhalten Sie:

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

}

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

Und das ist, wo Sie Ihre Gruppe mit Zählung beginnen kann. Sollte gut funktionieren.