phplaravel-scouttypesense

Laravel Scout with Typesense removing items in related collections


I am new in using Laravel Scout and Typesense. I just ran into a situation when I try to update related collection.

Here's my User Model

public function toSearchableArray()
{

    return array_merge($this->toArray(),[
        'id' => (string) $this->id,
        'name' => (string) $this->name,
        'role_ids' => (array) $this->role_ids,
        'created_at' => $this->created_at->timestamp,
    ]);
}

My scout config

User::class => [
    'collection-schema' => [
        // 'enable_nested_fields' => true,
        'fields' => [
            ['name' => 'id', 'type' => 'string'],
            ['name' => 'name', 'type' => 'string'],
            [
                'name' => 'role_ids',
                'type' => 'string[]',
                'reference' => 'roles_index.id'
            ],
            ['name' => 'created_at', 'type' => 'int64']
        ],
        'default_sorting_field' => 'created_at',
    ],
    'search-parameters' => [
        'query_by' => 'name'
    ],
],

In my postman:

/multi_search

[
    {
        "collection": "users_index",
        "q": "*",
        "query_by": "name",
        "include_fields": "$roles_index(*) as roles"
    }
]

When I have 1 user.role_ids and try to add another, in the typesense it will update both the role_ids and roles fields. But when I try to remove 1 id from role_ids, the object item in the roles field will stay the same.

Scenario 1

// upon updating and adding 1 role
role_ids: [1, 2]
roles: [
{
  id: 1,
  name: "role 1"
},
{
  id: 2,
  name: "role 2"
}
]

Scenario 2

// upon updating and removing 1 role
role_ids: [1]
roles: [
{
  id: 1,
  name: "role 1"
},
{ // this should be removed as well
  id: 2,
  name: "role 2"
}
]

Solution

  • I manage to solve it by using the $model->unsearchable(); after the $model->update(); line in my controller.

    The $model->unsearchable(); will delete the document thus resetting all fields.

    public function update ($id, Request $request) {
       $model = Model::find($id);
       $model['field_to_update'] = 'new value';
       $model->update();
       
       // unsearchable function
       $model->unsearchable();
    
       // other update logic (related collection updates)
    
       // make model to be searchable again
       $model->searchable();
       return response()->json($model, 200);
    }