Skip to content

Struggles working with Nova with large datasets #2345

Closed
@kfirba

Description

@kfirba
  • Laravel Version: 6.14.0
  • Nova Version: 2.10.1
  • PHP Version: 7.3.14

Description:

Hello,

I've installed Nova on one of our projects which has quite a large dataset. It seems like we can't properly optimize the database queries that are being run by Nova. To demonstrate the issue, let's assume we have a few models:

  • User - (We have well over 1M users)
  • Post
  • Tip
  • Comment (user_id, commentable_type, commentable_id)

The relationships:

  • User hasMany Comment
  • Tip morphToMany Comment
  • Post morphToMany Comment

The Comment resource's fields are:

public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),

            BelongsTo::make('User')->searchable()->readonly(),

            MorphTo::make('Commentable')->types([
                Tip::class,
                Post::class,
            ])->searchable(),

            Textarea::make('Body'),
        ];
    }

The Issue

There are a few issues in this scenario.

  1. Making the User field readonly() did not prevent the request to fetch every user in the system in order to populate the select box (which is disabled). We had to "fake" it and add the searchable() property in order for it to not select all users. It would be nice if it respected the readonly() flag and did not issue a request to populate the select box with every single user but just the one currently selected.

  2. There seems to be no way I can control what the BelongsTo searchable() autocomplete's query:
    2.1. Ideally, since we have so many users and each user record is packed with lot of data, I would not want to do a simple select * but rather choose the columns I know that we are going to need. For example, select only the id, username, and first_name columns. This speeds up the query significantly. I tried to achieve that using the relatableUser method but it seems like it ignored my select() call there. We tried leveraging the $with field ($with = ['user:id,username,first_name']), but it seems to only affect the index page.
    This issue is even worse when we try to fetch Post from an autocomplete since it has a huge body which slows down the query significantly when we fetch many posts.

2.2. When I type into the autocomplete, the system runs a query that matches the index page's query. It will execute a like query against all columns specified in the $search property of the User resource. We know that whenever we search for a user from an autocomplete, we always want to search by its id or by its username. We thought that we could override the default query's filters in the relatableUser method, but we couldn't. When we tried doing so, it seemed like our where clauses were simply appended to the query. At the moment the Autocomplete is basically unusable for us; it takes over 15 seconds to get some results

  1. Eager loading polymorphic relationships - on our Comment resource, we want to eager load the commentable relationship. The Commentable objects have many redundant fields that are never used in the index page or any other place which are slowing the query significantly. I tried to leverage the $with property (just like I did with the user relationship) and pass a callback to it so I can choose which fields I want for each commentable object, but we get an error that we an expression is not allowed as a default value:
public static $with = [
    'user:id,username,first_name',
    'commentable' => function (MorphTo $morphTo) {
        $morphTo->morphWith([Post::class => 'id,title', Tip::class => 'id,title']);
    },
];

It seems like we are struggling to optimize the system to work with very large datasets.
Are we missing something?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions