laravel-scout-tntsearch-driver
laravel-scout-tntsearch-driver copied to clipboard
Json Data type mb_strtolower() expects parameter 1 to be string, array given
I'm using JSON data to store my multi-lang properties on the model, now when am trying to import it to TNT it breaks here
public function tokenize($text, $stopwords = [])
{
>> $text = mb_strtolower($text);
$split = preg_split("/[^\p{L}\p{N}]+/u", $text, -1, PREG_SPLIT_NO_EMPTY);
return array_diff($split, $stopwords);
}
so if my json data is $model->title:
{
"ar": "ماك",
"en": "Mac"
}
it explodes because text becomes an array
array:2 [
"ar" => "ماك"
"en" => "Mac"
]
so I tried to stringify it by doing : $text = is_array($text) ? json_encode($text) : $text;
it did work , but I have lost the capability to search using arabic language! any other way to solve this issue , thanks!
EDIT: to gain the capabilities to search in Arabic back , I used
json_encode($result, JSON_UNESCAPED_UNICODE);
but still TNT-Driver doesn't support json/nested/arrays
good
but still TNT-Driver doesn't support json/nested/arrays
I also utilize JSON fields in MySQL and the consequent $casts and $appends properties on Eloquent models, so I also just encountered this attempting to index via tntsearch for the first time...
In my case, the fields containing JSON are not immediately critical to the indexing and search functioning... although of course it will be a 'nice-to-have', and not have to be concerned about this issue or conjure work-arounds.
But since I am able to get by without the JSON fields getting indexed, I excluded them from the Searchable Array:
/**
* Get the indexable data array for the model.
*
* @return array
*/
public function toSearchableArray()
{
$scanable = $this->toArray(); # dd( $scanable );
# Exclude JSON fields, as they break tntsearch's index processing :/
# => https://github.com/teamtnt/laravel-scout-tntsearch-driver/issues/229
return Arr::only($scanable, ['id',
'name', 'nickname',
'state', 'description'
]);
}
In this case, the text data for nickname is actually stored inside a JSON column, but to ease access to the property for my api endpoint as well as now for tntsearch-indexing purposes, I just expose it with an attribute accessor, like this:
/**
* $team->nickname aliases $team->name_mutations->_nick
*/
public function getNicknameAttribute()
{
return $this->name_mutations['_nick'];
}
... And append that faux-attribute for API responses, with the $appends property:
protected $appends = ['nickname'];
So, using attribute accessors and the $appends model property to flatten some text from inside a JSON column is one way to work around this problem... feasible probably only when the nested JSON attributes is a small part of what you would like to index.
I have a different approach. I save all the translations in the index with different keys.
public function toSearchableArray()
{
$array = array(
'id' => $this->id,
'name-en' => $this->getTranslation('name', 'en'),
'name-sv' => $this->getTranslation('name', 'sv'),
);
return $array;
}
Use Spatie/laravel-translatable package instead