programing

MongoDB Aggregation - 배열의 match if 값

telebox 2023. 6. 21. 22:31
반응형

MongoDB Aggregation - 배열의 match if 값

집계를 수행하는 컬렉션이 있으며 기본적으로 다음과 같이 정리했습니다.

{array:[1,2,3], value: 1},
{array:[1,2,3], value: 4}

값이 배열에 있는지 확인하기 위해 집계 일치를 어떻게 수행합니까?사용해 보았습니다.{$match: {"array: {$in: ["$value"]}}}하지만 아무것도 찾지 못합니다.

(위의 예를 들어) 출력은 다음과 같습니다.

{array:[1,2,3], value:1}

3.6 버전의 일반 쿼리에서 집계 표현식을 사용할 수 있습니다.

db.collection_name.find({"$expr": {"$in": ["$value", "$array"]}})

집계 사용:

사용할 수 있습니다.$match + $expr현재의3.6판본

db.collection_name.aggregate({"$match": {"$expr": {"$in": ["$value", "$array"]}}})

시도해 보세요$redact + $in에 있어서의 표현.3.4판본

db.collection_name.aggregate({
  "$redact": {
    "$cond": [
      {
        "$in": [
          "$value",
          "$array"
        ]
      },
      "$$KEEP",
      "$$PRUNE"
    ]
  }
})

앞서 설명한 바와 같이, 집계 파이프라인에서 논리를 계속할 필요가 없는 경우에는 이 옵션이 좋습니다.

그러나 사용하는 경우 를 사용하여 "값"을 배열로 변환하고 를 사용하여 비교합니다.다음을 사용하여 문서를 복제할 필요가 없으므로 이 방법이 가장 빠릅니다.

db.collection.aggregate([
   { "$redact": {
       "$cond": {
           "if": { "$setIsSubset": [
                { "$map": {
                    "input": { "$literal": ["A"] },
                    "as": "a",
                    "in": "$value"
                }},
                "$array"
           ]},
           "then": "$$KEEP",
           "else": "$$PRUNE"
       }
   }}
])

파이프라인 연산자는 내부에서 논리 조건의 처리를 허용하고 논리 조건이 참인 문서를 "보관"하거나 조건이 거짓인 문서를 "제거"하기 위해 특수 작업을 사용합니다.

이를 통해 후속 제품과 동일하게 작동할 수 있지만 단일 파이프라인 단계가 더 효율적입니다.

이러한 연산자가 자바스크립트가 아닌 네이티브 코딩 연산자라는 점을 고려할 때, 일치를 수행하는 "가장 빠른" 방법일 가능성이 높습니다.따라서 MongoDB 2.6 이상 버전을 사용하는 경우 문서에서 이러한 요소를 비교하기 위해 이 방법을 사용해야 합니다.

@chridam의 대답에 기초한 약간의 변화:

db.test.aggregate([
    { "$unwind": "$array" },
    { "$group": {
                  _id: { "_id": "$_id", "value": "$value" },
                  array: { $push: "$array" },
                  mcount: { $sum: {$cond: [{$eq: ["$value","$array"]},1,0]}}
                }
    },
    { $match: {mcount: {$gt: 0}}},
    { "$project": { "value": "$_id.value", "array": 1, "_id": 0 }}
])

하는 것이 목적입니다.$unwind그리고.$group배열 뒤로, 카운트 인mcount값과 일치하는 항목의 수입니다.그 후에, 간단한.$matchmcount > 0원하지 않는 문서를 필터링합니다.

보다 효율적인 접근 방식에는 다음과 같이 연산자를 사용하는 단일 파이프라인이 포함됩니다.

db.collection.aggregate([
    { 
        "$redact": {
            "$cond": [
                { 
                    "$setIsSubset": [ 
                        ["$value"],
                        "$array"  
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

지원하지 않는 MongoDB의 이전 버전(버전 < 2.6)의 경우 연산자를 사용하는 이 집계 파이프라인을 고려하십시오.

db.collection.aggregate([
    { "$unwind": "$array" },
    {
        "$project": {
            "isInArray": {
                "$cond": [
                    { "$eq": [ "$array", "$value" ] },
                    1,
                    0
                ]
            },
            "value": 1,
            "array": 1
        }
    },
    { "$sort": { "isInArray": -1 } },
    {
        "$group": {
            "_id": {
                "_id": "$_id",
                "value": "$value"
            },
            "array": { "$push": "$array" },
            "isInArray": { "$first": "$isInArray" }
        }
    },
    { "$match": { "isInArray": 1 } },
    { "$project": { "value": "$_id.value", "array": 1, "_id": 0 } }
])

답변이 조금 늦었지만 이것은 또 다른 해결책을 제시합니다.

addFields와 match를 개별적으로 사용하면 수정보다 유연성이 높아집니다.여러 필드를 노출한 다음 결과에 따라 다른 일치 논리를 함께 사용할 수 있습니다.

db.applications.aggregate([
    {$addFields: {"containsValueInArray": {$cond:[{$setIsSubset: [["valueToMatch"], "$arrayToMatchIn"]},true,false]}}},
    {$match: {"containsValueInArray":true}}
]);

$eq와 $setIntersection의 조합을 시도합니다.

{$group :{
  _id: "$id",
  yourName :  { $sum:
  { $cond :[
       {$and : [
          {$eq:[{$setIntersection : ["$someArrayField", ["$value"]]  },["$value"]]}
         ]
      },1,0]
  }

} }

그룹화 없이 V.3.2 이후로 쉬운 접근 방식이 선호됩니다.

...aggregate([
      {
        $addFields: {
          arrayFilter: {
            $filter: {
              input: '$array',
              as: 'item',
              cond: ['$$item', '$value']
            }
          }
        }
      },
      {
        $unwind: '$arrayFilter'
      },
      {
        $project: {
          arrayFilter: 0
        }
      }
    ]);
  1. 임시 필터 필드 추가
  2. 결과 어레이에 대한 $find(빈 어레이가 포함된 결과 제거)
  3. (선택사항) 프로젝트를 통해 결과에서 필터 필드 제거

간단한 $project & $match로 할 수 있습니다.

db.test.aggregate([{
$project: {
              arrayValue: 1,
              value: 1,
              "has_same_value" : { $in: ["$value", "$arrayValue"] }
          }
},
{
   $match: {has_same_value: true}
},
{
  $project: {has_same_value: 0}
}])
      "$match": { "name": { "$in":["Rio","Raja"] }} }])

언급URL : https://stackoverflow.com/questions/30537317/mongodb-aggregation-match-if-value-in-array

반응형