2017-10-23 9 views
0

MongoDB에 ~ 600,000 개의 문서가있는 콜렉션이 있습니다. 그 중 정확히 절반은 필드를 0으로 설정하고 다른 필드는 1로 설정하는 동일한 필드를 가지고 있습니다. (PyMongo를 통해) 집계 파이프 라인에서 sample 작업을 사용하여이 컬렉션에서 무작위 샘플을 얻으려고하면 크게 왜곡됩니다 1 값쪽으로 초기 모음이 동일하게 배포되는 경우 해당 필드가 1MongoDB의 "임의"샘플이 크게 왜곡 된 결과를 반환합니다.

있는 필드가 0 300-400 기록하고 24,000 기록이있을 수 25,000 기록 샘플에서

는 이유는 이렇게 많이 다른 분포로 결과를 반환하는 $sample의 사용과 컬렉션에서 대표 샘플을 얻으려면 어떻게해야합니까?

가 여기에 PyMongo의 I 쿼리를 위해 사용하고 라인이다 : MongoDB를 3.4.9의로

cursor = foo_database.bar_collection.aggregate([ { "$sample": { "size": 25000} } ]) 
+0

['$ sample'] (https://docs.mongodb.com/manual/reference/operator/aggregation/sample/)은 서버에 구현되어 있으므로 언어 ​​구현은 아무런 효과가 없습니다. 'size' 이외의 다른 인수 옵션은 없으므로, 이것은 매우 "블랙 박스"이며 구현 될 때 바로 동작합니다. 특정 값에 대해 "고르게 분포"될 것으로 예상되는 경우 실제로는 "두 개"이상의 작업이 필요하며 균등하게 분배 할 것으로 예상되는 값마다 하나씩 있어야합니다. 그렇지 않으면 의도 한대로 단순히 "임의"입니다. –

답변

2

, 당신이 관찰 한 바이어스에 대한 이유의 일부는 $sample는 스토리지에 거의 전적으로 의존하고 있다는 점이다 엔진의 임의 커서 구현 (SERVER-19183 참조). 이렇게하면 컬렉션에 많은 양의 데이터가 포함되어있을 때 $sample이 실행될 수 있습니다. 그러나 저장소 엔진은 B 트리 유형 구현을 사용하여 정렬 된 순서로 문서를 저장하므로 진정한 임의 결과를 생성 할 수있는 것은 아닙니다.

더 나은 $sample 기계에 대한 기능 요청이 두 개 있습니다 (예 : SERVER-22069SERVER-22068).

진정한 편향된 데이터 샘플이 필요하다면 자신의 $sample과 같은 솔루션을 롤링하는 것이 현 시점에서 진행하는 가장 좋은 방법 일 것입니다. 다음과 같이하십시오 :

  1. 컬렉션에있는 모든 _id의 목록을 가져옵니다.
  2. 이 목록에서 임의의 샘플링을 수행합니다 (예 : Python의 random.choice 사용).
  3. _id은 항상 색인되어 있으므로 원하는 표본 크기에 따라 합리적인 성능을 보이는 표본으로 된 _id을 사용하여 모든 관련 문서를 얻으십시오.