Programing

MongoDB 컬렉션의 객체 배열에서 쿼리 된 요소 만 검색

lottogame 2020. 3. 1. 15:35
반응형

MongoDB 컬렉션의 객체 배열에서 쿼리 된 요소 만 검색


내 컬렉션에 다음과 같은 문서가 있다고 가정합니다.

{  
   "_id":ObjectId("562e7c594c12942f08fe4192"),
   "shapes":[  
      {  
         "shape":"square",
         "color":"blue"
      },
      {  
         "shape":"circle",
         "color":"red"
      }
   ]
},
{  
   "_id":ObjectId("562e7c594c12942f08fe4193"),
   "shapes":[  
      {  
         "shape":"square",
         "color":"black"
      },
      {  
         "shape":"circle",
         "color":"green"
      }
   ]
}

쿼리를 수행하십시오.

db.test.find({"shapes.color": "red"}, {"shapes.color": 1})

또는

db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})

일치하는 문서 (문서 1)를 반환 하지만 항상 모든 배열 항목을 포함합니다 shapes.

{ "shapes": 
  [
    {"shape": "square", "color": "blue"},
    {"shape": "circle", "color": "red"}
  ] 
}

그러나 다음 을 포함하는 배열로만 문서 (문서 1) 를 얻고 싶습니다 color=red.

{ "shapes": 
  [
    {"shape": "circle", "color": "red"}
  ] 
}

어떻게해야합니까?


MongoDB 2.2의 새로운 $elemMatch프로젝션 연산자는 첫 번째로 일치하는 shapes요소 만 포함하도록 반환 된 문서를 변경하는 다른 방법을 제공합니다 .

db.test.find(
    {"shapes.color": "red"}, 
    {_id: 0, shapes: {$elemMatch: {color: "red"}}});

보고:

{"shapes" : [{"shape": "circle", "color": "red"}]}

2.2에서는을 사용하여이 작업을 수행 할 수도 있습니다 $ projection operator. 여기서 $투영 객체의 필드 이름은 쿼리에서 필드의 첫 번째 일치하는 배열 요소의 인덱스를 나타냅니다. 다음은 위와 동일한 결과를 반환합니다.

db.test.find({"shapes.color": "red"}, {_id: 0, 'shapes.$': 1});

MongoDB 3.2 업데이트

3.2 릴리스부터는 새로운 $filter집계 연산자를 사용하여 프로젝션 중에 배열을 필터링 할 수 있습니다 . 첫 번째 배열 대신 모든 일치 항목 을 포함시킬 수 있다는 이점이 있습니다.

db.test.aggregate([
    // Get just the docs that contain a shapes element where color is 'red'
    {$match: {'shapes.color': 'red'}},
    {$project: {
        shapes: {$filter: {
            input: '$shapes',
            as: 'shape',
            cond: {$eq: ['$$shape.color', 'red']}
        }},
        _id: 0
    }}
])

결과 :

[ 
    {
        "shapes" : [ 
            {
                "shape" : "circle",
                "color" : "red"
            }
        ]
    }
]

MongoDB 2.2+ 의 새로운 Aggregation Framework 는 Map / Reduce의 대안을 제공합니다. $unwind연산자 별도하는 데 사용할 수있는 shapes정합 될 수있는 문서의 스트림으로 배열 :

db.test.aggregate(
  // Start with a $match pipeline which can take advantage of an index and limit documents processed
  { $match : {
     "shapes.color": "red"
  }},
  { $unwind : "$shapes" },
  { $match : {
     "shapes.color": "red"
  }}
)

결과 :

{
    "result" : [
        {
            "_id" : ObjectId("504425059b7c9fa7ec92beec"),
            "shapes" : {
                "shape" : "circle",
                "color" : "red"
            }
        }
    ],
    "ok" : 1
}

주의 : 이 답변은 MongoDB 2.2 이상의 새로운 기능이 도입되기 전에 당시 관련 솔루션을 제공합니다 . 최신 버전의 MongoDB를 사용하는 경우 다른 답변을 참조하십시오.

필드 선택기 매개 변수는 완전한 특성으로 제한됩니다. 배열의 일부를 선택하는 데 사용할 수 없으며 전체 배열 만 선택할 수 있습니다. $ positional operator 사용하려고 시도했지만 작동하지 않았습니다.

가장 쉬운 방법은 클라이언트 에서 도형 필터링하는 것 입니다.

실제로 MongoDB에서 직접 올바른 출력 필요한 경우 map-reduce사용 하여 모양을 필터링 할 수 있습니다 .

function map() {
  filteredShapes = [];

  this.shapes.forEach(function (s) {
    if (s.color === "red") {
      filteredShapes.push(s);
    }
  });

  emit(this._id, { shapes: filteredShapes });
}

function reduce(key, values) {
  return values[0];
}

res = db.test.mapReduce(map, reduce, { query: { "shapes.color": "red" } })

db[res.result].find()

또 다른 중요한 방법은 MongoDB 2.6 의 새로운 집계 기능 중 하나 인 $ redact 를 사용 하는 것입니다 . 2.6을 사용하는 경우 큰 배열이있는 경우 성능 문제를 일으킬 수있는 $ unwind가 필요하지 않습니다.

db.test.aggregate([
    { $match: { 
         shapes: { $elemMatch: {color: "red"} } 
    }},
    { $redact : {
         $cond: {
             if: { $or : [{ $eq: ["$color","red"] }, { $not : "$color" }]},
             then: "$$DESCEND",
             else: "$$PRUNE"
         }
    }}]);

$redact "문서 자체에 저장된 정보를 기반으로 문서의 내용을 제한합니다" . 따라서 문서 내부 에서만 실행됩니다 . 기본적으로 문서를 맨 아래까지 스캔하고에있는 if조건 과 일치하는지 확인합니다. 일치하는 $cond경우 content ( $$DESCEND) 또는 remove ( $$PRUNE)를 유지합니다 .

위의 예에서 먼저 $match전체 shapes배열을 반환 하고 $ redact는 배열을 예상 결과로 제거합니다.

참고 {$not:"$color"}그것뿐만 아니라 상단의 문서를 스캔하기 때문에, 필요하며, 경우 $redact찾을 수없는 color최고 수준에 필드를이 반환됩니다 false그것이 우리가 원하지 않는 문서 전체를 제거 할 수도 있습니다.


배열 $slice에서 중요한 객체를 반환하는 것이 도움이되므로 배열 요소를 일치시키는 쿼리를 더 잘 수행 할 수 있습니다 .

db.test.find({"shapes.color" : "blue"}, {"shapes.$" : 1})

$slice요소의 색인을 알고 있지만 때로는 어떤 기준 요소와 일치하는 배열 요소를 원할 때 유용합니다. $연산자 와 일치하는 요소를 반환 할 수 있습니다 .


 db.getCollection('aj').find({"shapes.color":"red"},{"shapes.$":1})

출력

{

   "shapes" : [ 
       {
           "shape" : "circle",
           "color" : "red"
       }
   ]
}

mongodb에서 find의 구문은 다음과 같습니다.

    db.<collection name>.find(query, projection);

그리고 두 번째로 작성한 쿼리는

    db.test.find(
    {shapes: {"$elemMatch": {color: "red"}}}, 
    {"shapes.color":1})

여기에서는 $elemMatch쿼리 부분에서 연산자를 사용했지만 투영 부분에서이 연산자를 사용하면 원하는 결과를 얻을 수 있습니다. 검색어를 다음과 같이 작성할 수 있습니다

     db.users.find(
     {"shapes.color":"red"},
     {_id:0, shapes: {$elemMatch : {color: "red"}}})

원하는 결과를 얻을 수 있습니다.


JohnnyHK 에게 감사합니다 .

여기에 좀 더 복잡한 사용법을 추가하고 싶습니다.

// Document 
{ 
"_id" : 1
"shapes" : [
  {"shape" : "square",  "color" : "red"},
  {"shape" : "circle",  "color" : "green"}
  ] 
} 

{ 
"_id" : 2
"shapes" : [
  {"shape" : "square",  "color" : "red"},
  {"shape" : "circle",  "color" : "green"}
  ] 
} 


// The Query   
db.contents.find({
    "_id" : ObjectId(1),
    "shapes.color":"red"
},{
    "_id": 0,
    "shapes" :{
       "$elemMatch":{
           "color" : "red"
       } 
    }
}) 


//And the Result

{"shapes":[
    {
       "shape" : "square",
       "color" : "red"
    }
]}

당신은 단지 쿼리를 실행해야합니다

db.test.find(
{"shapes.color": "red"}, 
{shapes: {$elemMatch: {color: "red"}}});

이 쿼리의 출력은

{
    "_id" : ObjectId("562e7c594c12942f08fe4192"),
    "shapes" : [ 
        {"shape" : "circle", "color" : "red"}
    ]
}

예상대로 배열에서 색상 : '빨간색'과 일치하는 정확한 필드를 제공합니다.


$ project와 함께 다른 현명한 일치 요소가 문서의 다른 요소와 함께 클럽 화되는 것이 더 적합합니다.

db.test.aggregate(
  { "$unwind" : "$shapes" },
  { "$match" : {
     "shapes.color": "red"
  }},
{"$project":{
"_id":1,
"item":1
}}
)

db.test.find( {"shapes.color": "red"}, {_id: 0})

참고 URL : https://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection



반응형