2013-04-27 2 views
9

에 나는 일치 필드 내부적으로 MongoDB를

{ 
     "_id" : ObjectId("517b88decd483543a8bdd95b"), 
     "studentId" : 23, 
     "students" : [ 
      { 
      "id" : 23, 
      "class" : "a" 
      }, 
      { 
      "id" : 55, 
      "class" : "b" 
      } 
     ] 
    } 
    { 
     "_id" : ObjectId("517b9d05254e385a07fc4e71"), 
     "studentId" : 55, 
     "students" : [ 
      { 
      "id" : 33, 
      "class" : "c" 
      } 
     ] 
    } 

Note:하지 실제 데이터 만 스키마가 정확히 같은 인 MongoDB를

의 다음 문서를 데.

Requirement:단일 쿼리를 사용하여 학생들 배열 내부의 studentIdstudents.id (ID와 일치하는 문서를 찾기.

나는

db.data.aggregate({$match:{"students.id":"$studentId"}},{$group:{_id:"$student"}}); 

Result: 빈 배열 아래, 만약 같은 코드를 시도 전 { "students.id": "$ studentId"}를 { "students.id": 33}으로 대체하면 위의 json에서 두 번째 문서가 반환됩니다.

단일 쿼리를 사용하여이 시나리오에 대한 문서를 가져올 수 있습니까? 불행하게도 그것은 불가능

답변

13

가능한 경우 빠른 진리 체크 (isInStudentsList)를 할 수 있도록 데이터를 저장하는 동안 조건을 설정하는 것이 좋습니다. 이 유형의 쿼리를 수행하는 것은 매우 빠르다. 당신의 입력 예를 감안할 때

db.students.aggregate( 
    {$project: 
     {studentId: 1, studentIdComp: "$students.id"}}, 
    {$unwind: "$studentIdComp"}, 
    {$project : { studentId : 1, 
     isStudentEqual: { $eq : [ "$studentId", "$studentIdComp" ] }}}, 
    {$match: {isStudentEqual: true}}) 

출력은 다음과 같습니다 :

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("517b88decd483543a8bdd95b"), 
      "studentId" : 23, 
      "isStudentEqual" : true 
     } 
    ], 
    "ok" : 1 
} 

그렇지 않으면, 하나의 쿼리에서 당신이 원하는 것을 할 집계 프레임 워크 파이프 라인을 사용하여 상대적으로 복잡한 방법이있다 단계

간략한 설명 :

  1. 그냥으로 문서의 투영 구축과 배열이있는 새로운 필드는 id (첫 번째 문서에는 [23, 55]이 포함될 것입니다.
  2. 해당 구조체를 사용하면 $unwind입니다. 그러면 studentIdComp 배열에있는 각 배열 요소에 대해 새 임시 문서가 만들어집니다.
  3. 이제 해당 문서를 가져 와서 studentId을 계속 유지하고 및 studentIdComp이라는 두 필드의 동일성을 비교하는 isStudentEqual이라는 새 필드를 추가합니다. 이 시점에서이 두 필드가 포함 된 임시 문서가 하나만 있음을 기억하십시오.
  4. 마지막으로 비교 값 isStudentEqual이 true인지 확인하고 해당 문서 (원본 문서 _idstudentId 포함)를 반환하십시오.
  5. 학생이 목록에 여러 번 등록 된 경우 중복을 방지하기 위해 결과를 studentId 또는 _id으로 그룹화해야 할 수도 있습니다.하지만 필자는 그 사실을 알 필요가 없습니다.
+0

잘 작동합니다. 설명해 주셔서 감사합니다. +1 – karthick

-1

db.data.find({students: {$elemMatch: {id: 23}} , studentId: 23});

+0

나는 문제는 조건이 (. 학생 목록이 studentId을 포함 문서를 선택) – WiredPrairie

0

(

이 문 (예 어디 $를 사용할 필요가이 문제를 해결하기 위해 : Finding embeded document in mongodb?),

하지만 $가이 어디를 을 집합 프레임 워크와 함께 사용하지 못하도록 제한했습니다.

+0

@Asya 덕분 사실입니다 모든 문서를 찾는 방법입니다 믿는다) –

+0

메모를하지만 집계 프레임 워크를 필요가 없습니다 경우 $ (로 그 WiredPrairie의 답변에 따르면 $ project를 사용하여 새 필드를 만든 다음 $ match를 사용합니다. –

+0

정확히 @AsyaKamsky이지만 많은 질문에서 고전적인 상황을 관찰합니다. 하나의 필드와 일부 필드의 다른 필드를 비교합니다. 그 문제는 일반적으로 나쁜 데이터 모델에서 알 수 있습니다. 많은 devs는 관계형 저장소에서 직접 복사 + 붙여 넣기 만하는 데이터 저장소 모델을 만듭니다.) –