Meilisearch-laravel-scout: ๋‚ด ๋ฌธ์„œ์˜ ์ƒ‰์ธ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(Algolia์—์„œ๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค).

์— ๋งŒ๋“  2020๋…„ 08์›” 04์ผ  ยท  30์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: meilisearch/meilisearch-laravel-scout

์ €๋Š” Laravel 7, MS 0.13์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ์ธ๋ฑ์‹ฑํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
php artisan scout:import "App\Models\Product"
๊ทธ๋Ÿฐ ๋‹ค์Œ (local_product๋Š” ๋‚ด ์ƒ‰์ธ์ž…๋‹ˆ๋‹ค):
curl -X GET 'http://localhost:7700/indexes/local_product/documents'
๊ทธ๋ฆฌ๊ณ  [] ๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

Algolia์—์„œ ์ƒ‰์ธ์„ ์ž‘์„ฑํ•˜๋ฉด ๋‚ด ๋ฌธ์„œ๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ๋‚ด๊ฐ€ ํ•˜๋Š” ์˜ํ™”๋ฅผ ์ƒ‰์ธํ™”ํ•˜๋Š” ๊ฒฝ์šฐ:
curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' --data @movies.json
์˜ํ™”๋„ ์ƒ‰์ธ๋ฉ๋‹ˆ๋‹ค.

Laravel integration

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

 public function toSearchableArray()
    {
        $array = $this->toArray();

        $array['id'] = (string)$array['_id'];

        return $array;
    }

์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค

๋ชจ๋“  30 ๋Œ“๊ธ€

์•ˆ๋…•ํ•˜์„ธ์š” @elffeff ๋‹˜

์ด๊ฒƒ์€ ๋” ๋งŽ์€ ์ •๋ณด ์—†์ด๋Š” ๋‹น์‹ ์„ ๋•๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

meilisearch ์ธ์Šคํ„ด์Šค๋ฅผ ๊ธฐ๋กํ•˜๋ฉด ๋‹ค์Œ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"POST /indexes/local_product/documents?primaryKey=id HTTP/1.1" 202 14 

์ œํ’ˆ ๋ชจ๋ธ์— toSearchableArray() ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋™์ผํ•œ ์˜ค๋ฅ˜๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ๋ชฝ๊ณ ๋””๋น„๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ‚ค๋Š” _id๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
toSearchableArray๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ถ€ ํ•„๋“œ๋ฅผ ํ•„ํ„ฐ๋งํ•˜์ง€๋งŒ Algolia์—์„œ ์ƒ‰์ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ตœ์ข… ๋ฐฐ์—ด์„ ๋คํ”„ํ•˜๊ณ  ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” ์ง€๊ธˆ ์ปดํ“จํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฌด์—‡์„ ์‹œ๋„ํ•˜๊ธฐ๋ฅผ ์›ํ•˜์‹ญ๋‹ˆ๊นŒ?

๋‚˜๋Š” ๋‹น์‹ ์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค

meilisearch ์ธ์Šคํ„ด์Šค๋ฅผ ๊ธฐ๋กํ•˜๋ฉด ๋‹ค์Œ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ๋ฌด์—‡์„ ์‹œ๋„ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ์„ธ์š”

๋‚ด๊ฐ€ ์‹œ๋„ํ•˜๋ฉด

curl \-X POST 'http://localhost:7700/indexes/local_product/documents' \--data '[{"id": 287947,"title": "Shazam","poster": "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date": "2019-03-23"}]'

๋‚˜๋Š” ์–ป๋‹ค
{"updateId":31}

ํ•˜์ง€๋งŒ ๊ทธ๋•Œ ๋‚˜๋Š”
curl -X GET 'http://localhost:7700/indexes/local_product/documents'
๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ์–ป๋Š”๋‹ค

[]
๋‹ค์‹œ

์•ˆ๋…•ํ•˜์„ธ์š” @elffeff

ํ•ญ์ƒ ์—…๋ฐ์ดํŠธ ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ MeiliSearch๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ์‹คํŒจํ•œ ๊ฒฝ์šฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

๋‹ค์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธ ์ƒํƒœ ๊ฐ€์ ธ์˜ค๊ธฐ

๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰ ์˜ˆ์˜ ๊ฒฝ์šฐ ์‹œ๋„ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

curl -X GET 'http://localhost:7700/indexes/local_product/updates/31'

๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” ๋ชฝ๊ณ ๋””๋น„๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ‚ค๋Š” _id๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

local_product ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ‚ค ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜์…จ์Šต๋‹ˆ๊นŒ?
php artisan scout:index local_product --key _id

toSearchableArray๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ถ€ ํ•„๋“œ๋ฅผ ํ•„ํ„ฐ๋งํ•˜์ง€๋งŒ Algolia์—์„œ ์ƒ‰์ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ตœ์ข… ๋ฐฐ์—ด์„ ๋คํ”„ํ•˜๊ณ  ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

toSearchableArray() ์ฃผ์„์œผ๋กœ ์‹œ๋„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์—ฌ๊ธฐ์—์„œ ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์ง€๋งŒ ์‹œ๋„ํ•˜๋Š” ๋ฐ ๋น„์šฉ์ด ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

toSearchableArray()๋ฅผ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚˜๋Š” ๋‹ค์Œ์„ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.
php artisan scout:index local_product --key _id
์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ
php artisan scout:index local_product --key id
ํ•จ๊ป˜

/**
     * Get the value used to index the model.
     *
     * <strong i="14">@return</strong> mixed
     */
    public function getScoutKey()
    {
        return $this->id;
    }

    /**
     * Get the key name used to index the model.
     *
     * <strong i="15">@return</strong> mixed
     */
    public function getScoutKeyName()
    {
        return 'id';
    }

์•„๋ฌด๊ฒƒ๋„, ๋‚ด๊ฐ€ ํ•  ๋•Œ
curl -X GET 'http://localhost:7700/indexes/local_product/documents'

๋‚˜๋Š” ๋‹จ์ง€ ํ•˜๋‚˜์˜ ๋ฌธ์„œ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ‰์ธํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

curl \-X POST 'http://localhost:7700/indexes/local_product/documents' \--data '[{"id": 287947,"title": "Shazam","poster": "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date": "2019-03-23"}]'

ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๊นŒ?

shok@pop-os:~/web/blog$ php artisan scout:import "App\Models\Post"
Imported [App\Models\Post] models up to ID: 100
All [App\Models\Post] records have been imported.

๋กœ๊ทธ๋Š” storage/logs/laravel.log ์— ์žˆ์Šต๋‹ˆ๋‹ค.

scout.php ์—์„œ queue => true ๋˜๋Š” .env์—์„œ SCOUT_QUEUE=true๋ฅผ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๊นŒ?

๋Œ€๊ธฐ์—ด์— ๋Œ€ํ•ด true์™€ false๋ฅผ ๋ชจ๋‘ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ญ์ƒ ๋‚˜๋Š” ์–ป๋Š”๋‹ค

๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea4b314c80095faf5be593
๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea4bd94c80095faf5be787
๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea4cc34c80095faf5be97b
๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea4dfa4c80095faf5beb6f
๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea4f6b4c80095faf5bed63
๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea51164c80095faf5bef57
๊ฐ€์ ธ์˜จ [AppModelsProduct] ๋ชจ๋ธ ์ตœ๋Œ€ ID: 5eea524e4c80095faf5bf099

๊ทธ๋Ÿฌ๋‚˜ ๋ฌธ์„œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
laravel์˜ ๋กœ๊ทธ๊ฐ€ ์žˆ๋Š” ์œ„์น˜๋ฅผ ์•Œ๊ณ  ์žˆ์ง€๋งŒ ์˜ค๋ฅ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ณด๊ณ  ์‹ถ์€ ๊ฒƒ์€ MS ๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ๋ณผ ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋ชจ๋“  ๋™์ผํ•œ ์„ค์ •์œผ๋กœ Algolia๋Š” ๋‚ด ๋ฌธ์„œ๋ฅผ ์ƒ‰์ธํ™”ํ•ฉ๋‹ˆ๋‹ค.

์ข‹์•„, Meilisearch laravel scout๋Š” Algolia์˜ ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ธฐ ๊ฐ™์€ ์—”์ง„์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์€ ๋ฌธ์ œ๊ฐ€๋˜์–ด์„œ๋Š” ์•ˆ๋˜์ง€๋งŒ mongodb๋กœ ์‹คํ–‰ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•œ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค ...

@eskombro @curquiza ๊ฐ€ MS ๋กœ๊ทธ์— ๋Œ€ํ•ด ๋‹ต๋ณ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์‚ฌ์šฉ์ž ๋ชจ๋ธ์ด MySQL์ด๊ณ  ์ž‘๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— MongoDB์™€ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
Algolia๋Š” MongoDB์™€๋„ ์ž‘๋™ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ MongoDB/Meilisearch์™€ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

MS์—์„œ ์ผ๋ถ€ ๋กœ๊ทธ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Algolia๊ฐ€ ์ง€์›ํ•˜์ง€๋งŒ Meilisearch๋Š” ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•ˆํƒ€๊น์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ํŒŒํ—ค์น  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ laravel๊ณผ ํ•จ๊ป˜ mongoDB๋ฅผ ์„ค์น˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ท€ํ•˜์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ MeiliSearch ๋กœ๊ทธ๋Š” stdout์— ์ง์ ‘ ์ธ์‡„๋˜๋ฏ€๋กœ MeiliSearch ์ธ์Šคํ„ด์Šค๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์œ„์น˜์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์–ด๋””์—์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์—ฌ๊ธฐ์—์„œ MeiliSearch์˜ ์˜๊ตฌ ๋กœ๊ทธ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ฌธ์ œ๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค. https://github.com/meilisearch/MeiliSearch/issues/898

@elffeff ์ด์ „ ๋Œ“๊ธ€์—์„œ ์ œ์•ˆํ•œ ๋Œ€๋กœ ์—…๋ฐ์ดํŠธ ์ƒํƒœ๋ฅผ ํ™•์ธํ–ˆ์Šต๋‹ˆ๊นŒ? ๋ฌธ์„œ๊ฐ€ MeilISearch๋กœ ์„ฑ๊ณต์ ์œผ๋กœ ์ „์†ก๋˜์—ˆ๊ณ  ์ƒํƒœ ID๋ฅผ ์–ป์€ ๊ฒฝ์šฐ MeilISearch๊ฐ€ ์ƒ‰์ธ์„ ์ƒ์„ฑํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ•ด๋‹น ์—…๋ฐ์ดํŠธ ์ƒํƒœ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์‹œ๋„ํ•˜์‹ญ์‹œ์˜ค : https://github.com/meilisearch/meilisearch-laravel-scout/issues/36#issuecomment -668787383

์ด๊ฒƒ ์ข€๋ด

curl \-X POST 'http://localhost:7700/indexes/local_product/documents' \--data '[{"id": 287947,"title": "Shazam","poster": "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date": "2019-03-23"}]'

์ž‘๋™ํ•˜์ง€๋งŒ

curl \-X POST 'http://localhost:7700/indexes/local_product/documents' \--data '[{"id": 5eea4bd94c80095faf5be787,"title": "Shazam 2","poster": "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date": "2019-03-23"}]'

"5eea4bd94c80095faf5be787"์€ MongoDB _id์ž…๋‹ˆ๋‹ค.
์ด ์•„๋ฆ„๋‹ค์›€์„ ๋Œ๋ ค์ฃผ๋Š”

{"message":"์ž˜๋ชป๋œ JSON: 1ํ–‰ 11์—ด์˜ ์ˆซ์ž๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.","errorCode":"bad_request","errorType":"invalid_request_error","errorLink":" https://docs.meilisearch.com/errors #bad_request "}

JSON์ด ์œ ํšจํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. MS ๋ฐ ์‚ฌ์šฉ์ž ์ •์˜ ํ‚ค์— ์•ฝ๊ฐ„์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ธธ์ด์ธ์ง€, ๊ธ€์ž์ธ์ง€, ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ช‡ ๋ฒˆ ์‹œ๋„ํ•œ ํ›„ ๋ฌธ์ž๊ฐ€ ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. MS๋Š” ID์— ๋ฌธ์ž๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Laravel์€ ๊ฑฐ๊ธฐ์— ํŽธ์ง€๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ๋ฌธ์ œ๋‹ค.

์˜ˆ, ํฐ๋”ฐ์˜ดํ‘œ๋กœ ๋ฌถ์ธ ๋ฌธ์ž์—ด๋กœ ๋ณด๋‚ด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

5eea4bd94c80095faf5be787 "id": 5eea4bd94c80095faf5be787 "id": "5eea4bd94c80095faf5be787" ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ™‚

ํ•˜์ง€๋งŒ Scout ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์€ ์ œ์–ดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๐Ÿ™‚

์ด๋ ‡๊ฒŒ ํ•ด๋„

/**
     * Get the value used to index the model.
     *
     * <strong i="6">@return</strong> mixed
     */
    public function getScoutKey()
    {
        return (string)$this->_id;
    }

์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์—”์ง„์ด ๋ฌธ์ž์—ด ID๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

toSearchableArray()์—์„œ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

return [ 'id' => (string) $this->_id]
or
return [ '_id' => (string) $this->_id]

๋ฌด์—‡์„ ํ‚ค๋กœ ์„ค์ •ํ–ˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

 public function toSearchableArray()
    {
        $array = $this->toArray();

        $array['id'] = (string)$array['_id'];

        return $array;
    }

์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค

๋งˆ์ง€๋ง‰ ํ•œ๊ฐ€์ง€.
Algolia๋Š” ์ธ๋ฑ์Šค ์ƒ์„ฑ๊ณผ ํ•จ๊ป˜ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
๋‚ด ๋ง์€, Algolia๋Š” ์ธ๋ฑ์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ƒ์„ฑํ•˜๊ณ  ๋‚˜๋Š” ๋ณ€ํ™˜ ์—†์ด ๋ฌธ์ž๋กœ ID๋ฅผ ์ธ๋ฑ์‹ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
MS์—๋Š” ๋‘ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ๋ชจ๋‘ ํฌํ•จ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ๋ง์€, Algolia๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ MeiliSearch API๋Š” ์•„์ง ์ด ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๋Œ€์•ˆ ์†”๋ฃจ์…˜์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ SDK๋Š” get_or_create_index ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค(PHP SDK๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ) ๐Ÿ™‚

๋ณ€ํ™˜ ์—†์ด ๋ฌธ์ž๋กœ ID๋ฅผ ์ธ๋ฑ์‹ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” JSON ์œ ํšจ์„ฑ์—์„œ ๋น„๋กฏ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Algolia API๋„ ์œ ํšจํ•˜์ง€ ์•Š์€ JSON์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ˆซ์ž๋ฅผ ์ธ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฌธ์ž๊ฐ€ ํฌํ•จ๋œ ์ˆซ์ž๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ( " )์€ ์œ ํšจํ•˜์ง€ ์•Š์€ JSON์œผ๋กœ ๊ฐ„์ฃผ๋˜์–ด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

Algolia ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

Capture dโ€™eฬcran 2020-08-06 aฬ€ 10 52 59

Capture dโ€™eฬcran 2020-08-06 aฬ€ 10 53 15

Algolia์˜ Laravel SDK๋Š” ๋ฌธ์ž๊ฐ€ ํฌํ•จ๋œ ์ˆซ์ž๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋ฏ€๋กœ ์‹คํŒจ๊ฐ€ ์—†์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค ๐Ÿ™‚

MS์—๋Š” ๋‘ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ๋ชจ๋‘ ํฌํ•จ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ meilisearch-laravel-scout ์—๋Š” "์ธ์šฉ ๊ธฐ๋Šฅ"์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์ง€๋งŒ MeiliSearch๋Š” ์œ ํšจํ•œ JSON์„ ๊ธฐ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํฌํ•จํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ๐Ÿ˜‰

์˜ˆ, ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์ด Scout Engine์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์—ฌ๊ธฐ์—์„œ Scout ํ†ตํ•ฉ์— ์žˆ์Šต๋‹ˆ๋‹ค.
SDK๋Š” ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ธ๋ฑ์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด Scout๊ฐ€ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ž๊ฐ€ ์žˆ๋Š” Id์™€ ๋™์ผํ•˜๊ฒŒ JSOn์˜ ํ˜•์‹์ด ์ž˜๋ชป๋˜์—ˆ์Œ์„ ์ดํ•ดํ•˜์ง€๋งŒ Scout ์—”์ง„์€ ์‹คํŒจํ•˜๊ธฐ ์ „์— ์ด๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
Algolia์˜ ๊ฒฝ์šฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฌธ์ž๋กœ ์‹คํŒจํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์•Œ์•˜์–ด ์•Œ์•˜์–ด ์ดํ•ด๊ฐ€ ์ž˜ ์•ˆ๋์–ด ๐Ÿ˜‰

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ตฌํ˜„ํ•˜๊ธฐ์— ์ข‹์€ ๊ธฐ๋Šฅ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐Ÿ™‚

ํŽธ์ง‘: meilisearch-php ๋˜๋Š” meilisearch-laravel-scout ํŒจํ‚ค์ง€์—์„œ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@curquiza
๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ์ข‹์Šต๋‹ˆ๋‹ค.

scout์—์„œ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด symfony(๋ฐ ๊ธฐํƒ€ ํ”„๋ ˆ์ž„์›Œํฌ ๊ตฌํ˜„)๋„ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(์ด๋ฏธ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์Œ). ๋”ฐ๋ผ์„œ ๋Œ€์‹  SDK์— ์žˆ๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์Šค์นด์šฐํŠธ๊ฐ€ Algolia์šฉ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด Algolia PHP SDK์—์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•ฝ๊ฐ„์˜ ์—ฌ์œ  ์‹œ๊ฐ„์ด ์žˆ์„ ๋•Œ ์ด๋ฅผ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

@shokme , ๋งž์Šต๋‹ˆ๋‹ค. laravel-scout ํ†ตํ•ฉ๋ณด๋‹ค๋Š” PHP SDK์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋” ํ˜„๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์กฐ์‚ฌ์— ๋Œ€ํ•ด ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ทธ์— ๋”ฐ๋ผ ๋ฌธ์ œ๋ฅผ ์ด๋™(๋˜๋Š” ๋‹ค์‹œ ์ƒ์„ฑ)ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! ๐Ÿ™‚

๊ทธ๋ž˜์„œ ๋ชจ๋“  ๊ฒƒ์„ ์กฐ์‚ฌํ•œ ํ›„.
jenssegers/laravel-mongodb ์‚ฌ์šฉํ•˜์—ฌ laravel์— mongodb๋ฅผ ์„ค์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์œผ๋กœ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.
php artisan scout:index cars -k _id

๋ชจ๋ธ์„ ๋งŒ๋“ค๋‹ค

<?php

namespace App;

use Jenssegers\Mongodb\Eloquent\Model;
use Laravel\Scout\Searchable;

class Car extends Model
{
    use Searchable;

    public function getScoutKey() // not required if this is already your primary key
    {
        return $this->_id;
    }

    public function getScoutKeyName() // not required if this is already your primary key
    {
        return '_id';
    }
}

์ƒˆ ์ฐจ ๋งŒ๋“ค๊ธฐ

$car = new App\Car();
$car->name = 'mustang';
$car->constructor = 'ford';
$car->type = 'muscle';
$car->horses = 280;
$car->save();

๋ชจ๋ธ์€ ๋ฌธ์ œ ์—†์ด meilisearch๋กœ ๋ณด๋‚ด์กŒ์Šต๋‹ˆ๋‹ค!

{
  "status": "processed",
  "updateId": 1,
  "type": {
    "name": "DocumentsAddition",
    "number": 1
  },
  "duration": 0.005275826,
  "enqueuedAt": "2020-08-29T17:43:55.104917708Z",
  "processedAt": "2020-08-29T17:43:55.121602037Z"
}

๊ฒ€์ƒ‰ํ•  ๋•Œ ์ •ํ™•ํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค

App\Car::search('mustang')->get();

```json
[
{
"_id": "5f4a93dbd9668370086c7752",
"์ด๋ฆ„": "๋จธ์Šคํƒฑ",
"์ƒ์„ฑ์ž": "ํฌ๋“œ",
"์œ ํ˜•": "๊ทผ์œก",
"๋ง": 280,
"updated_at": "2020-08-29T17:43:55.102000Z",
"created_at": "2020-08-29T17:43:55.102000Z"
}
]

The only problem I have encounter while trying to reproduce the bug was by forgot to set `_id` has primaryKey
and the update status was returning:
```json
{
  "status": "failed",
  "updateId": 3,
  "type": {
    "name": "DocumentsAddition",
    "number": 1
  },
  "error": "serializer error; Primary key is missing.",
  "duration": 9.817e-6,
  "enqueuedAt": "2020-08-29T17:21:00.098580201Z",
  "processedAt": "2020-08-29T17:21:00.100495474Z"
}

๊ทธ๋ž˜์„œ ์†”์งํžˆ ๋งํ•ด์„œ ์™œ $this->_id @elfeffe ์—์„œ ๋ฌธ์ž์—ด์„ ๋ฐ›์ง€ ๋ชปํ•˜๋Š”์ง€ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@shokme ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฉฐ์น  ๋‚ด๋กœ ๊ฒ€์ƒ‰ ์ž‘์—…์„ ์žฌ๊ฐœํ•˜๊ณ  ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•˜๋ฉด ์•Œ๋ ค ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.
SDK๋Š” ์‹ค์ˆ˜๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด Algolia๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž๋™์œผ๋กœ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

SDK๋Š” ์‹ค์ˆ˜๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด Algolia๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž๋™์œผ๋กœ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

MeiliSearch ์ฝ”์–ด ์—”์ง„์—์„œ ๊ธฐํš๋˜์—ˆ์Šต๋‹ˆ๋‹ค! ๐Ÿ™‚
https://github.com/meilisearch/MeiliSearch/issues/918

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰