몰입공간
[Pymongo] mongoDB 중복 데이터 제거하기 본문
네이버 영화 페이지 리스트의 영화 정보를 크롤링하여 게시하는 프로그램 구현 도중에 중복데이터가 발생하여
그대로 게시되는 일이 발생했습니다.
이참에 mongoDB에 저장한 중복데이터를 삭제하는 방법을 알아보겠습니다.
네이버 영화 랭킹에서 다음과 같이 조회순, 평점순으로 영화 정보를 크롤링하면 중복되는 영화(데이터)가 발생하기 마련입니다.
조회순 50개, 평점순 36개로 총 86개의 데이터가 DB에 저장됩니다.
mongoDB에는 aggregate라는 강력한 데이터 처리 메서드가 있습니다.
db.collection.aggregate(pipeline, options)
첫번째 매개변수인 pipeline이 핵심 개념인데 여러 스테이지(조건) 으로 이루어진 리스트로 저장되며 각각의
스테이지를 통해 데이터를 가공 및 필터링 할 수 있습니다.
공식문서에서 더 자세한 설명과 예제 탐색이 가능합니다.
중복 데이터 제거를 위한 pipeline을 다음과 같이 구성합니다.
data = db.movies.aggregate(
[
{"$group": {"_id": "$title", "count": {"$sum": 1}}}
]
)
영화 제목(title)을 기준으로 그룹화 한 후 $sum 기능을 통해 count 필드에 1씩 더합니다.
data 쿼리의 데이터를 하나씩 꺼내 살펴보면 다음과 같이 중복된 영화는 count가 2개이상으로 나옵니다.
{'_id': '듄', 'count': 2}
**************************************************************************
{'_id': '코다', 'count': 1}
**************************************************************************
{'_id': '인질', 'count': 1}
**************************************************************************
{'_id': '고스트버스터즈 라이즈', 'count': 2}
**************************************************************************
여기서 중복제거를 위해 데이터 고유의 id값을 $addToSet 기능을 통해 저장합니다.
$addToSet 기능은 특정 조건으로 그룹화된 각각의 '고유한' 데이터를 리스트 형태로 반환합니다. (참조)
이후 match 스테이지에서 count가 2 이상인 데이터들만 필터링하여 다음과 같이 추출합니다.
data = db.movies.aggregate(
[
{"$group": {"_id": "$title", "unique_ids": {"$addToSet": "$_id"}, "count": {"$sum": 1}}},
{"$match": {"count": {"$gte": 2}}}
]
)
{'_id': '연애 빠진 로맨스', 'unique_ids': [ObjectId('61c018ea3077e041d9016468'), ObjectId('61c019fac753162ca4249595')], 'count': 2}
************************************************************************************************************************
{'_id': '유체이탈자', 'unique_ids': [ObjectId('61c018ed3077e041d901646f'), ObjectId('61c019f9c753162ca4249592')], 'count': 2}
************************************************************************************************************************
{'_id': '매트릭스', 'unique_ids': [ObjectId('61c018e23077e041d9016454'), ObjectId('61c019ffc753162ca42495a3')], 'count': 2}
************************************************************************************************************************
{'_id': '이터널스', 'unique_ids': [ObjectId('61c01a00c753162ca42495a7'), ObjectId('61c018f13077e041d9016477')], 'count': 2}
************************************************************************************************************************
이후, 데이터 제거를 위한 쿼리를 만들어주면 끝.
duplicated_data = []
for doc in list(data):
# print(doc)
del doc['unique_ids'][0]
for id in doc['unique_ids']:
duplicated_data.append(id)
db.movies.delete_many({"_id": {"$in": duplicated_data}})
중복 제거를 위한 임의의 리스트를 생성하고 중복 데이터 중 하나만 남기고 지우기 위하여 가장 첫번째 요소를 삭제 후 나머지 데이터들을 중복 데이터 리스트에 넣습니다.
delete_many 메서드를 통해 id가 중복데이터 리스트안에 있으면 데이터가 삭제됩니다.
15개의 중복데이터가 삭제되었습니다.
'Programming > Python' 카테고리의 다른 글
[Python] 제너레이터 (Generator) (0) | 2022.02.24 |
---|---|
[Poetry] VScode에서 Poetry 활용하기 (Using python poetry in VScode) (0) | 2022.02.10 |
[Python] boolean 값을 활용한 숫자 연산 (Calculations with bool) (0) | 2022.02.04 |
[MongoDB] GridFS 파일 업데이트 하는 방법 (0) | 2022.01.10 |
[Python] 자료형에 따른 함수 작용 (0) | 2021.12.24 |