#1: Implemented Elasticsearch mappings for playlists and users.

This commit is contained in:
Peter Deltchev 2016-01-15 20:10:20 -08:00
parent a5bb117ae7
commit dbbaa03542
9 changed files with 82 additions and 31 deletions

View file

@ -54,6 +54,7 @@ class AddTrackToPlaylistCommand extends CommandBase
{
$songIndex = $this->_playlist->tracks()->count() + 1;
$this->_playlist->tracks()->attach($this->_track, ['position' => $songIndex]);
$this->_playlist->touch();
Playlist::whereId($this->_playlist->id)->update([
'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = ' . $this->_playlist->id . ')')

View file

@ -79,15 +79,18 @@ class RebuildSearchIndex extends Command
}
});
// Playlist::withTrashed()->chunk(200, function(Collection $playlists) {
// foreach($playlists as $playlist) {
// $this->info("Processing playlist #{$playlist->id}...");
// $playlist->ensureElasticsearchEntryIsUpToDate();
// }
// });
//
// User::withTrashed()->chunk(200, function(User $user) {
// $user->ensureElasticsearchEntryIsUpToDate();
// });
Playlist::withTrashed()->chunk(200, function(Collection $playlists) {
foreach($playlists as $playlist) {
$this->info("Processing playlist #{$playlist->id}...");
$playlist->ensureElasticsearchEntryIsUpToDate();
}
});
User::chunk(200, function(Collection $users) {
foreach($users as $user) {
$this->info("Processing user #{$user->id}...");
$user->ensureElasticsearchEntryIsUpToDate();
}
});
}
}

View file

@ -22,6 +22,7 @@ namespace Poniverse\Ponyfm\Library;
use DB;
use Elasticsearch\Client;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Poniverse\Ponyfm\Models\Album;
use Poniverse\Ponyfm\Models\Playlist;
@ -53,11 +54,11 @@ class Search {
'multi_match' => [
'query' => $query,
'fields' => [
'title',
'artist',
'title^3',
'artist^2',
'genre',
'track_type',
'show_songs',
'show_songs^2',
],
],
],
@ -71,7 +72,7 @@ class Search {
'multi_match' => [
'query' => $query,
'fields' => [
'title',
'title^2',
'artist',
'tracks',
],
@ -87,8 +88,9 @@ class Search {
'multi_match' => [
'query' => $query,
'fields' => [
'title',
'user',
'title^3',
'curator',
'tracks^2',
],
],
],
@ -102,7 +104,8 @@ class Search {
'multi_match' => [
'query' => $query,
'fields' => [
'display_name',
'display_name^2',
'tracks',
],
],
],
@ -150,7 +153,14 @@ class Search {
}
$caseStatement .= 'END';
$modelInstances = $modelClass::withTrashed()
/** @var Builder $modelInstances */
$modelInstances = $modelClass::query();
if (method_exists($modelClass, 'withTrashed')) {
$modelInstances = $modelInstances->withTrashed();
}
$modelInstances = $modelInstances
->whereIn('id', array_keys($ids))
->orderBy(DB::raw($caseStatement))
->get();

View file

@ -28,7 +28,7 @@ use Illuminate\Foundation\Bus\DispatchesJobs;
use Auth;
use Cache;
use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Poniverse\Ponyfm\Traits\TrackCollection;
use Poniverse\Ponyfm\Traits\SlugTrait;
use Venturecraft\Revisionable\RevisionableTrait;
@ -62,7 +62,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/
class Album extends Model
{
use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection, RevisionableTrait, IndexedInElasticsearch;
use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection, RevisionableTrait, IndexedInElasticsearchTrait;
protected $elasticsearchType = 'album';

View file

@ -27,7 +27,7 @@ use Illuminate\Foundation\Bus\DispatchesJobs;
use Auth;
use Cache;
use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Poniverse\Ponyfm\Traits\TrackCollection;
use Poniverse\Ponyfm\Traits\SlugTrait;
use Venturecraft\Revisionable\RevisionableTrait;
@ -61,7 +61,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/
class Playlist extends Model
{
use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection, RevisionableTrait, IndexedInElasticsearch;
use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection, RevisionableTrait, IndexedInElasticsearchTrait;
protected $elasticsearchType = 'playlist';
@ -295,6 +295,10 @@ class Playlist extends Model
* @return array
*/
public function toElasticsearch() {
return $this->toArray();
return [
'title' => $this->title,
'curator' => $this->user->display_name,
'tracks' => $this->tracks->pluck('title'),
];
}
}

View file

@ -26,7 +26,7 @@ use Config;
use DB;
use Elasticsearch;
use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Poniverse\Ponyfm\Traits\SlugTrait;
use Exception;
use External;
@ -97,7 +97,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/
class Track extends Model
{
use SoftDeletes, IndexedInElasticsearch;
use SoftDeletes, IndexedInElasticsearchTrait;
protected $elasticsearchType = 'track';

View file

@ -29,7 +29,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Auth;
use Illuminate\Support\Str;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Venturecraft\Revisionable\RevisionableTrait;
/**
@ -65,7 +65,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/
class User extends Model implements AuthenticatableContract, CanResetPasswordContract, \Illuminate\Contracts\Auth\Access\Authorizable
{
use Authenticatable, CanResetPassword, Authorizable, RevisionableTrait, IndexedInElasticsearch;
use Authenticatable, CanResetPassword, Authorizable, RevisionableTrait, IndexedInElasticsearchTrait;
protected $elasticsearchType = 'user';
@ -258,6 +258,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
* @return array
*/
public function toElasticsearch() {
return $this->toArray();
return [
'username' => $this->username,
'display_name' => $this->display_name,
'tracks' => $this->tracks->pluck('title'),
];
}
}

View file

@ -30,7 +30,7 @@ use Elasticsearch;
*
* @package Poniverse\Ponyfm\Traits
*/
trait IndexedInElasticsearch
trait IndexedInElasticsearchTrait
{
/**
* Returns this model in Elasticsearch-friendly form. The array returned by
@ -83,7 +83,7 @@ trait IndexedInElasticsearch
}
public function ensureElasticsearchEntryIsUpToDate() {
if ($this->trashed()) {
if (method_exists($this, 'trashed') && $this->trashed()) {
$this->deleteElasticsearchEntry();
} else {
$this->createOrUpdateElasticsearchEntry();

View file

@ -42,6 +42,7 @@ class SetupElasticsearch extends Migration
'properties' => [
'title' => ['type' => 'string'],
'artist' => ['type' => 'string', 'index' => 'not_analyzed'],
'published_at' => ['type' => 'date'],
'genre' => ['type' => 'string', 'index' => 'not_analyzed'],
'track_type' => ['type' => 'string', 'index' => 'not_analyzed'],
@ -65,7 +66,35 @@ class SetupElasticsearch extends Migration
// See: https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html
'tracks' => ['type' => 'string']
]
]
],
'playlist' => [
'_source' => ['enabled' => true],
'dynamic' => 'strict',
'properties' => [
'title' => ['type' => 'string'],
'curator' => ['type' => 'string', 'index' => 'not_analyzed'],
// This field is intended to be used as an array.
// Note that all Elasticsearch fields can technically be used as arrays.
// See: https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html
'tracks' => ['type' => 'string']
]
],
'user' => [
'_source' => ['enabled' => true],
'dynamic' => 'strict',
'properties' => [
'username' => ['type' => 'string', 'index' => 'not_analyzed'],
'display_name' => ['type' => 'string', 'index' => 'not_analyzed'],
// This field is intended to be used as an array.
// Note that all Elasticsearch fields can technically be used as arrays.
// See: https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html
'tracks' => ['type' => 'string']
]
],
]
]
]);