Pymongo의 빠른 또는 대량 업스타트
피몽고에서 벌크 업서트를 어떻게 하나요?여러 항목을 업데이트하려고 하는데 한 번에 하나씩 수행하는 작업이 매우 느립니다.
거의 동일한 질문에 대한 답이 여기 있습니다: MongoDB에서 대량 업데이트/업데이트?
받아들여진 대답은 실제로 질문에 대답하지 않습니다.가져오기/내보내기를 수행하기 위한 mongo CLI에 대한 링크를 제공합니다.
또한 대량 업셋을 수행하는 것이 가능하지 않은 이유/모범 사례가 없는 이유를 설명하는 사람도 있겠지만, 이러한 문제에 대한 바람직한 해결책이 무엇인지 설명해 주십시오.
Pymongo의 최신 릴리스(3.x 이상)는 서버 릴리스가 대량 작업을 지원하지 않는 경우 다운그레이드되는 일관된 인터페이스로 대량 작업을 래핑합니다.이는 이제 MongoDB에서 공식적으로 지원되는 드라이버와 일치합니다.
따라서 코드화를 위해 선호되는 방법은 다른 적절한 작업 작업을 대신 사용하는 대신 사용하는 것입니다.그리고 지금은 물론 특정 작성자보다는 자연어 목록을 사용하는 것이 선호됩니다.
이전 설명서의 직접 번역:
from pymongo import UpdateOne
operations = [
UpdateOne({ "field1": 1},{ "$push": { "vals": 1 } },upsert=True),
UpdateOne({ "field1": 1},{ "$push": { "vals": 2 } },upsert=True),
UpdateOne({ "field1": 1},{ "$push": { "vals": 3 } },upsert=True)
]
result = collection.bulk_write(operations)
또는 고전적인 문서 변환 루프:
import random
from pymongo import UpdateOne
random.seed()
operations = []
for doc in collection.find():
# Set a random number on every document update
operations.append(
UpdateOne({ "_id": doc["_id"] },{ "$set": { "random": random.randint(0,10) } })
)
# Send once every 1000 in batch
if ( len(operations) == 1000 ):
collection.bulk_write(operations,ordered=False)
operations = []
if ( len(operations) > 0 ):
collection.bulk_write(operations,ordered=False)
반환된 결과는 일치 및 업데이트된 문서와 반환된 문서의 카운터를 포함합니다._id
발생하는 모든 "uperts"에 대한 값입니다.
대량 작업 배열의 크기에 대해 약간의 오해가 있습니다.이 제한은 BSON 형식을 사용하는 서버로 전송되는 "요청"에도 적용되므로 서버로 전송되는 실제 요청은 16MB BSON 제한을 초과할 수 없습니다.
그러나 실제 작업은 1,000개의 배치로만 전송 및 처리되기 때문에 구축할 수 있는 요청 배열의 크기는 결정되지 않습니다.유일한 실질적인 제한 사항은 이러한 1000개의 작동 명령 자체가 실제로 16MB보다 큰 BSON 문서를 생성하지 않는다는 것입니다.꽤나 어려운 주문이군요.
대량 방법의 일반적인 개념은 한 번에 많은 것을 보내고 하나의 서버 응답만 처리하기 때문에 "트래픽 감소"입니다.모든 업데이트 요청에 대한 오버헤드를 줄임으로써 많은 시간을 절약할 수 있습니다.
MongoDB 2.6+는 대량 작업을 지원합니다.여기에는 대량 삽입, 업서트, 업데이트 등이 포함됩니다.이것의 요점은 레코드별 작업을 수행하는 왕복 지연 시간('정확히는 문서별 문서')을 단축/제거하는 것입니다.
어떻게 작동할까요?파이썬의 예를 들자면, 제가 일하고 있는 것이 바로 그것이기 때문입니다.
>>> import pymongo
>>> pymongo.version
'2.7rc0'
이 기능을 사용하려면 '대량' 개체를 만들고 여기에 문서를 추가한 다음 이 개체에서 실행을 호출하면 모든 업데이트가 한 번에 전송됩니다.주의사항:수집된 작업의 BSON 크기(보손 크기의 합계)는 문서 크기 제한인 16MB를 초과할 수 없습니다. 따라서 작업 수는 크게 달라질 수 있습니다. 마일리지는 달라질 수 있습니다.
대량 업서트 작업의 Pymongo 예제:
import pymongo
conn = pymongo.MongoClient('myserver', 8839)
db = conn['mydbname']
coll = db.myCollection
bulkop = coll.initialize_ordered_bulk_op()
retval = bulkop.find({'field1':1}).upsert().update({'$push':{'vals':1}})
retval = bulkop.find({'field1':1}).upsert().update({'$push':{'vals':2}})
retval = bulkop.find({'field1':1}).upsert().update({'$push':{'vals':3}})
retval = bulkop.execute()
이것이 필수적인 방법입니다.자세한 내용은 다음 사이트에서 확인할 수 있습니다.
http://api.mongodb.org/python/2.7rc1/examples/bulk.html
편집 :- 버전 3.5의 python 드라이버이므로 initialize_ordered_bulk_op은 더 이상 사용되지 않습니다.대신 bulk_write()를 사용합니다.[ http://api.mongodb.com/python/current/api/pymongo/collection.html#pymongo.collection.Collection.bulk_write ]
데이터가 많은 경우 데이터가 존재하는지 여부를 판단하기 위해 "_id"를 사용하려는 경우
당신은 시도할 수 있습니다...
import pymongo
from pymongo import UpdateOne
client = pymongo.MongoClient('localhost', 27017)
db=client['sampleDB']
collectionInfo = db.sample
#sample data
datas=[
{"_id":123456,"name":"aaa","N":1,"comment":"first sample","lat":22,"lng":33},
{"_id":234567,"name":"aaa","N":1,"comment":"second sample","lat":22,"lng":33},
{"_id":345678,"name":"aaa","N":1,"comment":"xxx sample","lat":22,"lng":33},
{"_id":456789,"name":"aaa","N":1,"comment":"yyy sample","lat":22,"lng":33},
{"_id":123456,"name":"aaaaaaaaaaaaaaaaaa","N":1,"comment":"zzz sample","lat":22,"lng":33},
{"_id":11111111,"name":"aaa","N":1,"comment":"zzz sample","lat":22,"lng":33}
]
#you should split judge item and other data
ids=[data.pop("_id") for data in datas]
operations=[UpdateOne({"_id":idn},{'$set':data},upsert=True) for idn ,data in zip(ids,datas)]
collectionInfo.bulk_write(operations)
제가 영어가 많이 서툴러요, 제가 하는 말을 이해하지 못한다면 죄송합니다.
답은 동일하게 유지됩니다. 대량 업그레이드는 지원되지 않습니다.
multi=True를 사용하여 쿼리 사양과 일치하는 모든 문서를 업데이트할 수 있습니다.
원하는 방식으로 명령을 일괄적으로 수행하는 것에 대한 버그가 있습니다.
Python 3.5+, 모터 및 비동기식으로 가장 빠른 대량 업데이트:
import asyncio
import datetime
import logging
import random
import time
import motor.motor_asyncio
import pymongo.errors
async def execute_bulk(bulk):
try:
await bulk.execute()
except pymongo.errors.BulkWriteError as err:
logging.error(err.details)
async def main():
cnt = 0
bulk = db.initialize_unordered_bulk_op()
tasks = []
async for document in db.find({}, {}, no_cursor_timeout=True):
cnt += 1
bulk.find({'_id': document['_id']}).update({'$set': {"random": random.randint(0,10)}})
if not cnt % 1000:
task = asyncio.ensure_future(execute_bulk(bulk))
tasks.append(task)
bulk = db.initialize_unordered_bulk_op()
if cnt % 1000:
task = asyncio.ensure_future(bulk.execute(bulk))
tasks.append(task)
logging.info('%s processed', cnt)
await asyncio.gather(*tasks)
logging.basicConfig(level='INFO')
db = motor.motor_asyncio.AsyncIOMotorClient()['database']['collection']
start_time = time.time()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
execution_time = time.time() - start_time
logging.info('Execution time: %s', datetime.timedelta(seconds=execution_time))
언급URL : https://stackoverflow.com/questions/5292370/fast-or-bulk-upsert-in-pymongo
'sourcecode' 카테고리의 다른 글
MongoDB 셸 쿼리에서 "수집에서 데이터 b가 수집 a에 있지 않음"을 가져옵니다. (0) | 2023.04.29 |
---|---|
배치 파일에서 기다리지 않고 응용 프로그램을 시작하는 방법은 무엇입니까? (0) | 2023.04.29 |
애플리케이션 통찰력 확보 또는 로그 분석 (0) | 2023.04.29 |
내용물-처분:"인라인"과 "애착"의 차이점은 무엇입니까? (0) | 2023.04.29 |
포스트백과 콜백의 차이점 (0) | 2023.04.29 |