Pymon go неэффективный запрос - PullRequest
0 голосов
/ 16 января 2020

В настоящее время у меня есть следующий фрагмент кода:

houses = self.database[self.database_name][constants.DATABASE_HOUSES_COLLECTION]           

bulk_houses = houses.initialize_unordered_bulk_op()

for house in houses.find().skip(self.from_index).limit(
        constants.MAX_HOUSE_FUNCTION_DOCUMENTS_PER_THREAD):

    house_coords = (house.get("longitude"), house.get("latitude"))

    min = 10000

    for c in self.collection.find({"city": house.get("city")}, {"longtitude": 1, "latitude": 1}):

        collection_coords = (c.get("longitude"), c.get("latitude"))

        distance = geopy.distance.distance(collection_coords, house_coords).km

        if distance < min:
            min = distance

    if min == 10000:
        min = None

    bulk_houses.find({"_id": house.get("_id")}).update(
        {"$set": {f"demography.distanceClosest{translated.get(self.collection.name)}": min}})

bulk_houses.execute()

Что он делает, он проходит по каждому дому в коллекции домов.

Для каждого дома он проходит по второй коллекции это было дано и только захватывает долготу и широту.

Он вычисляет ближайшее расстояние в пределах одного и того же города.

Эта функция является многопоточной, я вызываю функцию следующим образом:

houses_count = self.houses.count_documents({})

for i in range(len(self.collections)):

    x = 0
    while x < houses_count:
        match_demography_house = MatchDemographyHouse(self.collections[i], self.mongo_db,
                                                        constants.DATABASE_NAME, x,
                                                        x + constants.MAX_HOUSE_FUNCTION_DOCUMENTS_PER_THREAD)
        match_demography_house.add_to_pool(self.match_house_demography_executor)
        x += constants.MAX_HOUSE_FUNCTION_DOCUMENTS_PER_THREAD

И, как вы можете себе представить, это очень неэффективно. Добавление указателя на город улучшило скорость незначительно, а также только захват долготы и широты немного увеличил скорость.

Для 1000 домов требуется 1 минута до go, и в коллекции, в которой она проходит, 240 документов. В настоящее время он делает 50 домов на поток.

1 Ответ

1 голос
/ 16 января 2020

Попробуйте этот тестовый ремень. На моей машине он работает менее чем за секунду без индексации:

import pymongo
import random
import datetime
import geopy.distance

db = pymongo.MongoClient()['testhouses']

db.testhouses.delete_many({})
db.testcollection.delete_many({})

for i in range(1000):
    longitude = random.randint(-89, 89)
    latitude = random.randint(-180, 180)
    city = f'City {i}'
    db.testhouses.insert_one({'city': city, 'longitude': longitude, 'latitude': latitude})
    if i < 240:
        db.testcollection.insert_one({'city': city, 'longitude': longitude, 'latitude': latitude})

start_time = datetime.datetime.now()

bulk_houses = db.testhouses.initialize_unordered_bulk_op()

for house in db.testhouses.find():
    house_coords = (house.get("longitude"), house.get("latitude"))
    minimum = 10000

    for c in db.testcollection.find({"city": house.get("city")}, {"longtitude": 1, "latitude": 1}):
        collection_coords = (c.get("longitude"), c.get("latitude"))
        distance = geopy.distance.distance(collection_coords, house_coords).km

        if distance < minimum: minimum = distance

    if minimum == 10000: minimum = None

    bulk_houses.find({"_id": house.get("_id")}).update({"$set": {f"demography.distanceClosest": minimum}})

result = bulk_houses.execute()
print(f'Bulk updates: {result["nModified"]} updated')
print(f'Time taken: {(datetime.datetime.now() - start_time).microseconds / 1000000} seconds')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...