2017-10-17 16 views
0

나는 각 사용자에 대한 각 유형의 경고의 수를 얻기 위해 MongoDB의 쉘에서 수행 다음 집계 한 : 나는 봄 데이터 MongoDB를로 번역 한Spring MongoDB 집계에서 프로젝트 DBRef는 어떻게됩니까?

db.getCollection('alerts').aggregate(

     { 
      $unwind:"$son" 
     }, 
     { 
      $group: 
      { 
       _id:{ 
        son: "$son", 
        level: "$level" 
       }, 
       count: { $sum: 1 } 
      } 
     }, 
     { 
      $group: 
       { 
        _id:{ 
         son: "$_id.son" 
        }, 
        alerts: { $addToSet: { 
         level: "$_id.level", 
         count: "$count" 
        }} 

       } 
     } 
     ) 

다음과 같이

TypedAggregation<AlertEntity> alertsAggregation = 
       Aggregation.newAggregation(AlertEntity.class, 
         unwind("$son"), 
         Aggregation.group("$son", "$level").count().as("count"), 
         Aggregation.group("$_id.son") 
          .addToSet(new BasicDBObject("level", "$_id.level").append("count", "$count")).as("alerts")); 

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

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

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

      return alertsBySonResultsList; 

내가 명확하지 않고 작동하도록 할 수없는 것은 식별자와 가능한 경우 사용자의 이름 (아들 변수)을 투사하는 것입니다.

The resulting DTO is as follows 


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; 

} 

그러나 id 속성에는 전체 내장 하위 엔티티가 포함됩니다.

이것은 경보 모음의 구조입니다.

{ 
    "_id" : ObjectId("59e6ff3d9ef9d46a91112890"), 
    "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
    "level" : "INFO", 
    "title" : "Alerta de Prueba", 
    "payload" : "Alerta de Prueba", 
    "create_at" : ISODate("2017-10-18T07:13:45.091Z"), 
    "delivery_mode" : "PUSH_NOTIFICATION", 
    "delivered" : false, 
    "parent" : { 
     "$ref" : "parents", 
     "$id" : ObjectId("59e6ff369ef9d46a91112878") 
    }, 
    "son" : { 
     "$ref" : "children", 
     "$id" : ObjectId("59e6ff389ef9d46a9111287b") 
    } 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("59e6ff6d9ef9d46a91112892"), 
    "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
    "level" : "WARNING", 
    "title" : "Token de acceso inv�lido.", 
    "payload" : "El token de acceso YOUTUBE no es v�lido", 
    "create_at" : ISODate("2017-10-18T07:14:53.449Z"), 
    "delivery_mode" : "PUSH_NOTIFICATION", 
    "delivered" : false, 
    "parent" : { 
     "$ref" : "parents", 
     "$id" : ObjectId("59e6ff369ef9d46a91112878") 
    }, 
    "son" : { 
     "$ref" : "children", 
     "$id" : ObjectId("59e6ff389ef9d46a9111287b") 
    } 
} 

/* 3 */ 
{ 
    "_id" : ObjectId("59e6ff6d9ef9d46a91112893"), 
    "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
    "level" : "WARNING", 
    "title" : "Token de acceso inv�lido.", 
    "payload" : "El token de acceso INSTAGRAM no es v�lido", 
    "create_at" : ISODate("2017-10-18T07:14:53.468Z"), 
    "delivery_mode" : "PUSH_NOTIFICATION", 
    "delivered" : false, 
    "parent" : { 
     "$ref" : "parents", 
     "$id" : ObjectId("59e6ff369ef9d46a91112878") 
    }, 
    "son" : { 
     "$ref" : "children", 
     "$id" : ObjectId("59e6ff389ef9d46a9111287c") 
    } 
} 

누구든지 내가이 접근 할 수있는 방법을 알고 :

enter image description here

JSON 포맷을 경고? MongoDB의 버전으로 미리

+0

경고 컬렉션의 json 예제를 붙여 넣을 수 있습니까? –

+0

붙여 넣은 이미지에서 아들이 배열 인 것을 볼 수 없습니다. 집계가 풀리기 때문에 배열입니다. 이미지 대신 json을 붙여 넣는 것이 좋습니다. –

+0

MongoDB에서 집계를 실제로 마스터하지는 않습니다. 원하는 결과를 얻는 유일한 방법입니다. 그러나 제 질문은 투사의 마지막 부분에 더 초점을 맞추고 있습니다. DBRef 필드의 ID를 가져올 수 없습니다. –

답변

2

1에서

덕분에 3.4

이 내가 사용 사례 재현하기 위해 만든 다음 모음 :

경고 컬렉션

{ 
    "_id" : ObjectId("59e6ff3d9ef9d46a91112890"), 
    "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
    "level" : "INFO", 
    "title" : "Alerta de Prueba", 
    "payload" : "Alerta de Prueba", 
    "create_at" : ISODate("2017-10-18T07:13:45.091+0000"), 
    "delivery_mode" : "PUSH_NOTIFICATION", 
    "delivered" : false, 
    "parent" : DBRef("parents", ObjectId("59e6ff369ef9d46a91112878")), 
    "son" : DBRef("children", ObjectId("59e72ff0572ae72d8c063666")) 
} 
{ 
    "_id" : ObjectId("59e6ff6d9ef9d46a91112892"), 
    "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
    "level" : "WARNING", 
    "title" : "Token de acceso inv�lido.", 
    "payload" : "El token de acceso YOUTUBE no es valido", 
    "create_at" : ISODate("2017-10-18T07:14:53.449+0000"), 
    "delivery_mode" : "PUSH_NOTIFICATION", 
    "delivered" : false, 
    "parent" : DBRef("parents", ObjectId("59e6ff369ef9d46a91112878")), 
    "son" : DBRef("children", ObjectId("59e72ff0572ae72d8c063666")) 
} 
{ 
    "_id" : ObjectId("59e6ff6d9ef9d46a91112893"), 
    "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
    "level" : "WARNING", 
    "title" : "Token de acceso inv�lido.", 
    "payload" : "El token de acceso INSTAGRAM no es v�lido", 
    "create_at" : ISODate("2017-10-18T07:14:53.468+0000"), 
    "delivery_mode" : "PUSH_NOTIFICATION", 
    "delivered" : false, 
    "parent" : DBRef("parents", ObjectId("59e6ff369ef9d46a91112878")), 
    "son" : DBRef("children", ObjectId("59e72ffb572ae72d8c063669")) 
} 

알림 아들 ref의 OBjectIds를 변경했습니다. 내가 만든 어린이 컬렉션과 일치시킬 수 있습니다.

어린이 수집

{ 
    "_id" : ObjectId("59e72ff0572ae72d8c063666"), 
    "name" : "Bob" 
} 
{ 
    "_id" : ObjectId("59e72ffb572ae72d8c063669"), 
    "name" : "Tim" 
} 

방금 ​​다른 모음에서 필드를 액세스 할 수 없습니다에 대한 참조를 사용하고 있기 때문에. 그래서 일부 집계 단계가 누락되었다고 생각합니다.

나는 다음과 같은 한 :

db.getCollection('alerts').aggregate(
{ 
      $unwind:"$son" 
     }, 
     { 
      $group: 
      { 
       _id:{ 
        son: "$son", 
        level: "$level" 
       }, 
       count: { $sum: 1 } 
      } 
     }, 
     { 
      $group: 
       { 
        _id:{ 
         son: "$_id.son" 
        }, 
        alerts: { $addToSet: { 
         level: "$_id.level", 
         count: "$count" 
        }} 

       } 
     }, 
     { $addFields: { sonsArray: { $objectToArray: "$_id.son" } } }, 
     { $match: { "sonsArray.k": "$id"} }, 
     { $lookup: { from: "children", localField: "sonsArray.v", foreignField: "_id", as: "name" } } 
) 

을 그리고 JSON으로 다음과 같은 결과를 얻었다 : 당신이 추가로 sonsArray 등 당신이 할 수처럼 만든 곳 필드를 제거하려면

{ 
    "_id" : { 
     "son" : DBRef("children", ObjectId("59e72ffb572ae72d8c063669")) 
    }, 
    "alerts" : [ 
     { 
      "level" : "WARNING", 
      "count" : NumberInt(1) 
     } 
    ], 
    "sonsArray" : [ 
     { 
      "k" : "$ref", 
      "v" : "children" 
     }, 
     { 
      "k" : "$id", 
      "v" : ObjectId("59e72ffb572ae72d8c063669") 
     } 
    ], 
    "name" : [ 
     { 
      "_id" : ObjectId("59e72ffb572ae72d8c063669"), 
      "name" : "Tim" 
     } 
    ] 
} 
{ 
    "_id" : { 
     "son" : DBRef("children", ObjectId("59e72ff0572ae72d8c063666")) 
    }, 
    "alerts" : [ 
     { 
      "level" : "INFO", 
      "count" : NumberInt(1) 
     }, 
     { 
      "level" : "WARNING", 
      "count" : NumberInt(1) 
     } 
    ], 
    "sonsArray" : [ 
     { 
      "k" : "$ref", 
      "v" : "children" 
     }, 
     { 
      "k" : "$id", 
      "v" : ObjectId("59e72ff0572ae72d8c063666") 
     } 
    ], 
    "name" : [ 
     { 
      "_id" : ObjectId("59e72ff0572ae72d8c063666"), 
      "name" : "Bob" 
     } 
    ] 
} 

을 결과를 clean$project 파이프 라인을 추가하십시오.


2. 당신은 MongoDB의 이전 버전을 가지고 있고 당신은 당신의 데이터 구조를 변경 할 수 있습니다.

경우, 대신에이 같은 참조 사용 :

"sonId" : [ 
     ObjectId("59e72ff0572ae72d8c063666") 
    ] 

은 당신이 당신의 집계를 수행 할 수 있습니다

"son" : DBRef("children", ObjectId("59e72ffb572ae72d8c063669")) 

는이 같은 배열로 아들/S의 OBJECTID를 추가 할 수 다음과 같습니다 :

db.getCollection('alerts').aggregate(
{ 
      $unwind:"$sonId" 
     }, 
     { 
      $group: 
      { 
       _id:{ 
        sonId: "$sonId", 
        level: "$level" 
       }, 
       count: { $sum: 1 } 
      } 
     }, 
     { 
      $group: 
       { 
        _id:{ 
         sonId: "$_id.sonId" 
        }, 
        alerts: { $addToSet: { 
         level: "$_id.level", 
         count: "$count" 
        }} 

       } 
     }, 
     { $lookup: { from: "children", localField: "_id.sonId", foreignField: "_id", as: "son" } } 
) 

그게 뭔가?

+0

완벽합니다. 문제는 최근의 mongodb 버전을 사용할 수 없다는 것입니다. 분명히이 단계 "$ addFields"가 버전 3.4에 추가되었습니다. 이전 버전에서 다르게 할 수 있습니까? –

+0

"$ addFields"(예 : 더 긴 "$ project"단계로 대체)에 대한 대안을 제공하더라도 다음 단계로 넘어갈 것이므로 두려워합니다. $ objectToArray "를 참조하십시오. 이 기능은 3.4에서만 사용할 수 있습니다. 아마도 최신 버전의 mongo로 업그레이드 할만한 이유 일 것입니다. 스키마를 변경할 때 융통성이 있다면 3.2에서만 작동합니다. –

+0

스키마 변경에 관심이 있다면 더 자세히 설명 할 수 있습니다. –