2015-01-06 2 views
4

ater에 많은 강의 목록 내부 검색 몽고와 1 쿼리이 SQL 해당 쿼리를 수행 할 수
SELECT * from collection WHERE _id NOT IN (SELECT blacklist from collection WHERE _id = 1) 내가 aggregatio와 함께 많은 일을 시도했지만 처리하지 않았다 일하다. 여기 집계 하위 쿼리, 특정 _id

내 모음입니다 :이 쿼리 예상

{ 
    "_id" : 1, 
    "blacklist" : [8,9,10,3] 
    "code_postal" : 67110, 
    "loc" : { 
     "type" : "Point", 
     "coordinates" : [ 
      7.72, 
      48.91 
     ] 
    } 
} 

{ 
    "_id" : 2, 
"blacklist" : [18,1,93] 
    "code_postal" : 67110, 
    "loc" : { 
     "type" : "Point", 
     "coordinates" : [ 
      7.63, 
      48.91 
     ] 
    } 
} 

{ 
    "_id" : 3, 
    "blacklist" : [7,3] 
    "code_postal" : 67110, 
    "loc" : { 
     "type" : "Point", 
     "coordinates" : [ 
      7.7, 
      48.96 
     ] 
    } 
} 

결과와이 컬렉션은해야 (_id 3 _id의 블랙리스트 1에 있기 때문에 제외) :

{ 
     "_id" : 1, 
     "blacklist" : [8,9,10,3] 
     "code_postal" : 67110, 
     "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
       7.72, 
       48.91 
      ] 
     } 
    } 

    { 
      "_id" : 2, 
     "blacklist" : [18,1,93] 
      "code_postal" : 67110, 
      "loc" : { 
       "type" : "Point", 
       "coordinates" : [ 
        7.63, 
        48.91 
       ] 
      } 
     } 

안부

+1

가 왜 SQL 여기에 아무것도로 변환 있다고 생각 :

다음과 같은 생산? 그것은 유효한 SQL조차도 아니다. 결과가 어떠해야한다고 생각하니? 그냥 여기서 무엇을하는지 알아 내려고 노력하고 있습니다. –

+0

이 SQL은 유효하지 않지만 논리는 매우 낮다는 것을 알고 있습니까? 만약 당신이 선호한다면 semi join이나 subquery 같은 종류 일 겁니다. – jess

+0

아니, 이해할 수 없네. 그 이유는 내가 적어도 질문을 편집하여 다른 방법으로 설명 할 수 없다면 어떤 결과를 기대할 수 있는지를 묻는 이유입니다. –

답변

2

난 당신이 문제를 저장하고 단지 두 개의 쿼리를 사용해야한다고 생각해. (첫째, 블랙리스트에 다음 문서를 조회)하지만 정말 다른 방법이없는 경우 : 모든 문서 하나에이 그룹 때문에, 당신이 알아서해야한다는

db.so.aggregate([ 
{ 
    // First, choose what fields to return (less is better) 
    // and only return a certain document {_id: 1}'s blacklist. 
    $project: { 
     _id:   1, 
     code_postal: 1, 
     loc:   1, 
     bl:   { 
      // Only return blacklists if the parent has 
      // a certain ID. 
      $cond: { 
       if: {$eq: ["$_id", 1]}, // or a different value 
       then: "$blacklist", 
       else: 0 
      } 
     } 
    } 
}, 

{ 
    // Group all documents in one, so that we can embed the 
    // blacklist into all documents, not just in {_id:1}. 
    $group: { 
     _id:  null, // Group everything. 
     items:  { $push: "$$ROOT" }, 
     blacklist: { $max: "$bl" } // "{}" is higher than "0". 
            // This makes sure that we only 
            // get one blacklist, not 
            // [ [], 0, 0, 0, ... ] 
    } 
}, 

{ 
    // Pull the documents apart again. 
    $unwind: "$items" 
}, 

{ 
    $project: { 
     _id:   "$items._id", 
     code_postal: "$items.code_postal", 
     loc:   "$items.loc", 
     whitelisted: { 
      // If everything in the following array is true, 
      // then the _id is not in the blacklist. 
      $allElementsTrue: [{ 
       $map: { 
        // Iterate over $blacklist 
        input: "$blacklist", 
        as: "currentId", 
        in: { 
         // If the ids don't match, return true. 
         $ne: ["$$currentId", "$items._id"] 
        } 
       } 
      }] 
     } 
    } 
}, 

{ 
    // Only find non-blacklisted documents. 
    $match: { 
     "whitelisted": true 
    } 
} 

]); 

참고하지 Mongo's document size limits를 초과 할 수 있습니다.

[ 
    { 
     "_id" : 1, 
     "code_postal" : 67110, 
     "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
       7.72, 
       48.91 
      ] 
     }, 
     "whitelisted" : true 
    }, 
    { 
     "_id" : 2, 
     "code_postal" : 67110, 
     "loc" : { 
      "type" : "Point", 
      "coordinates" : [ 
       7.63, 
       48.91 
      ] 
     }, 
     "whitelisted" : true 
    } 
] 
+0

와우, 그렇게 가능하지만 매우 복잡하게 보입니다. 나는 대답을 연구 할 필요가 있지만 어쩌면 내가 몇 가지 세부 fot 추가해야합니다 "내가 뭘 원하는 그 1 쿼리에서합니까? "블랙리스트 필드에있는 ID의 목록이 꽤 거대 할 수 있기 때문에, +1500 항목을 의미하고 두 번째 쿼리 게시물 크기가 크지는 모르겠지만 내 생각에는 그 좋은 생각이 아니라고 생각합니다. 두 번째 쿼리 NOT IN (1500 ID의 목록)?! – jess

+0

글쎄, 조인하지 않고 DB에서 조인과 같은 작업을하려고합니다. 위와 같은 솔루션의 성능과 두 개의 쿼리 실행 (작은 ID와 큰 ID 목록)을 비교하십시오. 1500 ID 목록을 보내는 것이 위의 솔루션보다 빠를 수도 있습니다. [$ explain을 사용하여 프로파일 링하십시오.] (http://docs.mongodb.org/manual/reference/operator/meta/explain/) – RikkusRukkus

+0

** 나는 더 빨리 ** 될 것이라고 말하고 싶습니다. 다른 쿼리의 작은 목록조차도 예제 파이프 라인의 모든 처리에 대한 추가 비용을 무효화합니다. 단일 문서에 전체 모음을 추가하는 것은 일반적으로 불가능하지는 않지만 실용적이지 않습니다. 그러나 예제를 @ user4406273에 설명하기 위해 여러분이 예의 바른 자세를 보였다고 생각합니다. –