복붙노트

[MONGODB] C #을 중첩 된 개체의 수를 계산

MONGODB

C #을 중첩 된 개체의 수를 계산

나는 ASP.Net 코어 2.0 웹 API를 사용하여 소프트웨어를 개발하고있다. 나는 내 컬렉션의 일부 필드의 계산 횟수에 필요합니다. 나는 아래로 MongoDB의 내 컬렉션의 데이터를 가지고있다. 나는 내 컬렉션에해야 할 얼마나 많은 태그 얼마나 많은 센서를 찾아야합니다. 특정 엔드 포인트는 멀티 태그가 각 태그는 멀티 센서를 가지고 있습니다.

{
    "_id" : ObjectId("5aef51dfaf42ea1b70d0c4db"),    
    "EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",    
    "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
    "Url" : "test",
    "Tags" : [ 
        {
            "Uid" : "C1:3D:CA:D4:45:11",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("11.029802536740132")
                }, 
                {
                    "Type" : 4,
                    "Value" : NumberDecimal("27.25")
                }, 
                {
                    "Type" : 6,
                    "Value" : NumberDecimal("2924")
                }
            ]
        },         
        {
            "Uid" : "C1:3D:CA:D4:45:11",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("11.413037961112279")
                }, 
                {
                    "Type" : 4,
                    "Value" : NumberDecimal("27.25")
                }, 
                {
                    "Type" : 6,
                    "Value" : NumberDecimal("2924")
                }
            ]
        },          
        {
            "Uid" : "E5:FA:2A:35:AF:DD",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:02.666Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-97")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-58")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("10.171658037099185")
                }
            ]
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5aef51e0af42ea1b70d0c4dc"),    
    "EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",    
    "Url" : "test",
    "Tags" : [ 
        {
            "Uid" : "E2:02:00:18:DA:40",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-98")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-65")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("7.845424441900629")
                }, 
                {
                    "Type" : 4,
                    "Value" : NumberDecimal("0.0")
                }, 
                {
                    "Type" : 6,
                    "Value" : NumberDecimal("3012")
                }
            ]
        }, 
        {
            "Uid" : "12:3B:6A:1A:B7:F9",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("12.939770381907275")
                }
            ]
        }
    ]
}

나는 특정 EndpointId 관련 태그 및 센서의 수를 계산합니다. 어떻게하여 MongoDB에서 해당 쿼리를 작성할 수 있습니까?

해결법

  1. ==============================

    1.쿼리가 될 것 "센서"의 "태그"에서 "UID"각각의 "엔드 포인트"및 "형식"내 "독특한"항목을 계산하려면 :

    쿼리가 될 것 "센서"의 "태그"에서 "UID"각각의 "엔드 포인트"및 "형식"내 "독특한"항목을 계산하려면 :

    db.collection.aggregate([
      { "$unwind": "$Tags" },
      { "$unwind": "$Tags.Sensors" },
      { "$group": {
        "_id": {
          "EndpointId": "$EndpointId",
          "Uid": "$Tags.Uid",
          "Type": "$Tags.Sensors.Type"
        },
      }},
      { "$group": {
        "_id": {
          "EndpointId": "$_id.EndpointId",
          "Uid": "$_id.Uid",
        },
        "count": { "$sum": 1 }
      }},
      { "$group": {
        "_id": "$_id.EndpointId",
        "tagCount": { "$sum": 1 },
        "sensorCount": { "$sum": "$count" }
      }}
    ])
    

    또는 C 번호

        var results = collection.AsQueryable()
          .SelectMany(p => p.Tags, (p, tag) => new
            {
              EndpointId = p.EndpointId,
              Uid = tag.Uid,
              Sensors = tag.Sensors
            }
          )
          .SelectMany(p => p.Sensors, (p, sensor) => new
            {
              EndpointId = p.EndpointId,
              Uid = p.Uid,
              Type = sensor.Type
            }
          )
          .GroupBy(p => new { EndpointId = p.EndpointId, Uid = p.Uid, Type = p.Type })
          .GroupBy(p => new { EndpointId = p.Key.EndpointId, Uid = p.Key.Uid },
            (k, s) => new { Key = k, count = s.Count() }
          )
          .GroupBy(p => p.Key.EndpointId,
            (k, s) => new
            {
              EndpointId = k,
              tagCount = s.Count(),
              sensorCount = s.Sum(x => x.count)
            }
          );
    

    어떤 출력 :

    {
      "EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",
      "tagCount" : 4,
      "sensorCount" : 16
    }
    

    비록 실제로 "가장 효율적인"방법은 문서는 문서 자체 내 양을 줄일 $하는 것입니다 어쨌든 "UID"에 대한 고유 한 값을 제시하는 것이이 고려를 할 수 :

    db.collection.aggregate([
      { "$group": {
        "_id": "$EndpointId",
        "tags": {
          "$sum": {
            "$size": { "$setUnion": ["$Tags.Uid",[]] }
          }
        },
        "sensors": {
          "$sum": {
            "$sum": {
              "$map": {
                "input": { "$setUnion": ["$Tags.Uid",[]] },
                "as": "tag",
                "in": {
                  "$size": {
                    "$reduce": {
                      "input": {
                        "$filter": {
                          "input": {
                            "$map": {
                              "input": "$Tags",
                              "in": {
                                "Uid": "$$this.Uid",
                                "Type": "$$this.Sensors.Type"
                              }
                            }
                          },
                          "cond": { "$eq": [ "$$this.Uid", "$$tag" ] }
                        }
                      },
                      "initialValue": [],
                      "in": { "$setUnion": [ "$$value", "$$this.Type" ] }
                    }
                  }
                }
              }
            }
          }
        }
      }}
    ])
    

    당신이 문에 대한 BSON을 구축하기 위해 BsonDocument 인터페이스를 사용해야 할 것이다 있도록 문은 정말, 그러나 LINQ에 잘 매핑되지 않습니다. 그리고 같은 "UID"값이 실제로 컬렉션에서 여러 문서 내에서 발생하는 "않았다"물론, 다음 $ 언 와인드 문은 "그룹"배열 항목 내에서 문서를 통해 그 함께하기 위해 필요하다.

    당신은 배열의 $ 크기를 획득하여이 문제를 해결. 외부 배열이 단순히 문서의 배열의 필드 경로에 적용되며, 내부 배열의 항목에 대해 당신은 "센서"의 $ 크기를 각각 "태그"요소를 처리 한 후 얻기 위해 $지도 처리해야 그리고 $ 합 결과 배열은 전체 개수를 감소시킨다.

    문서 당에게이 될 것이라고 :

    db.collection.aggregate([
      { "$project": {
        "tags": { "$size": "$Tags" },
        "sensors": {
          "$sum": {
            "$map": {
              "input": "$Tags",
               "in": { "$size": "$$this.Sensors" }
            }
          }
        }
      }}
    ])
    

    당신이 좋아하는 것 당신의 C # 코드에서 클래스에 할당 한 경우 어떤 :

    collection.AsQueryable()
      .Select(p => new
        {
          tags = p.Tags.Count(),
          sensors = p.Tags.Select(x => x.Sensors.Count()).Sum()
        }
      );
    

    어디 그 반환 :

    { "tags" : 3, "sensors" : 13 }
    { "tags" : 2, "sensors" : 8 }
    

    당신은 전체 콜렉션 예를 들어, 같은 그룹에 결과를 $ 할 경우, 당신은 할 것이다 :

    db.collection.aggregate([
      /* The shell would use $match for "query" conditions */
      //{ "$match": { "EndpointId": "89799bcc-e86f-4c8a-b340-8b5ed53caf83" } },
      { "$group": {
        "_id": null,
        "tags": { "$sum": { "$size": "$Tags" } },
        "sensors": {
          "$sum": {
            "$sum": {
              "$map": {
                "input": "$Tags",
                 "in": { "$size": "$$this.Sensors" }
              }
            }
          }
        }
      }}
    ])
    

    것 전에 같이 당신의 C # 코드에 대한 어떤 :

    collection.AsQueryable()
      .GroupBy(p => "", (k,s) => new
        {
          tags = s.Sum(p => p.Tags.Count()),
          sensors = s.Sum(p => p.Tags.Select(x => x.Sensors.Count()).Sum())
        }
      );
    

    어디 그 반환 :

    { "tags" : 5, "sensors" : 21 }
    

    EndpointId는, 당신은 단순히 그룹화 키보다는 null 또는 0으로 해당 필드를 사용합니다 "를 그리고는 C #을 드라이버 매핑에 의해 적용됩니다 같이 :

    collection.AsQueryable()
      /* Use the Where if you want a query to match only those documents */
      //.Where(p => p.EndpointId == "89799bcc-e86f-4c8a-b340-8b5ed53caf83")            
      .GroupBy(p => p.EndpointId, (k,s) => new
        {
          tags = s.Sum(p => p.Tags.Count()),
          sensors = s.Sum(p => p.Tags.Select(x => x.Sensors.Count()).Sum())
        }
      );
    

    어떤 당신이 우리에게 준이 개 문서 샘플 물론 동일 합이다 :

    { "tags" : 5, "sensors" : 21 }
    

    당신이 구문에 익숙해지면이 너무 간단 파이프 라인 실행 매우 간단한 결과입니다.

    나는 핵심 문서에서 집계 연산자에 익숙해 및 제안 물론 표현의 "LINQ 치트 시트"및 C #을 드라이버 코드 저장소 withing에에서 자신의 사용 매핑.

    또 다른 예는 C #을 드라이버 참조의 일반 LINQ 참조를 참조하는 방법을 일반적으로 MongoDB를의 집계 프레임 워크에이지도.

  2. from https://stackoverflow.com/questions/50243453/calculate-the-count-of-nested-objects-with-c-sharp by cc-by-sa and MIT license