Skip to content

MongoEngine is very slow when fetching LazyReferenceField #2527

@alterEgo123

Description

@alterEgo123

I'm working on referencing objects from the same class using MongoEngine stackoverflow_issue. This is my code below

import random
import string

from mongoengine import *

import timeit


class Person(Document):
    name = StringField()
    best_friend = LazyReferenceField('Person')
    friends = ListField(LazyReferenceField('Person'))

    def fetch_(self, attribute):
        return attribute.fetch().to_dict() if attribute else None

    def to_dict(self):
        return {
            'name': self.name,
            'best_friend': self.fetch_(self.best_friend),
            'friends': [self.fetch_(friend) for friend in self.friends] if self.friends else []

        }


def timer(function):
    def func(*args):
        start_time = timeit.default_timer()
        function(*args)
        elapsed = timeit.default_timer() - start_time
        print('Function "{name}" took {time} seconds to complete.'.format(name=function.__name__, time=elapsed))

    return func


def get_random_string():
    letters = string.ascii_lowercase
    result_str = ''.join(random.choice(letters) for _ in range(8))
    return result_str


@timer
def create_people(number):
    Person.drop_collection()
    everyone = []
    for _ in range(number):
        a = Person(name=get_random_string(), friends=everyone).save()
        b = Person(name=get_random_string(), best_friend=a.id, friends=everyone).save()
        everyone += [a.id, b.id]


@timer
def get_people():
    return [p.to_dict() for p in Person.objects()]


@timer
def main():
    connect()
    create_people(8)
    get_people()


main()


This is the program's execution time:

Function "create_people" took 0.0675540619995445 seconds to complete.
Function "get_people" took 45.54736871900968 seconds to complete.
Function "main" took 45.6171299170237 seconds to complete.

How I reduce the fetching query and add a cache using MongoEngine or at MongoDB level? Isn't MongoEngine supposed to cache results for the same query, even for a short period of time?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions