#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; $songIndex = $this->_playlist->tracks()->count() + 1;
$this->_playlist->tracks()->attach($this->_track, ['position' => $songIndex]); $this->_playlist->tracks()->attach($this->_track, ['position' => $songIndex]);
$this->_playlist->touch();
Playlist::whereId($this->_playlist->id)->update([ Playlist::whereId($this->_playlist->id)->update([
'track_count' => DB::raw('(SELECT COUNT(id) FROM playlist_track WHERE playlist_id = ' . $this->_playlist->id . ')') '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) { Playlist::withTrashed()->chunk(200, function(Collection $playlists) {
// foreach($playlists as $playlist) { foreach($playlists as $playlist) {
// $this->info("Processing playlist #{$playlist->id}..."); $this->info("Processing playlist #{$playlist->id}...");
// $playlist->ensureElasticsearchEntryIsUpToDate(); $playlist->ensureElasticsearchEntryIsUpToDate();
// } }
// }); });
//
// User::withTrashed()->chunk(200, function(User $user) { User::chunk(200, function(Collection $users) {
// $user->ensureElasticsearchEntryIsUpToDate(); 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 DB;
use Elasticsearch\Client; use Elasticsearch\Client;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Poniverse\Ponyfm\Models\Album; use Poniverse\Ponyfm\Models\Album;
use Poniverse\Ponyfm\Models\Playlist; use Poniverse\Ponyfm\Models\Playlist;
@ -53,11 +54,11 @@ class Search {
'multi_match' => [ 'multi_match' => [
'query' => $query, 'query' => $query,
'fields' => [ 'fields' => [
'title', 'title^3',
'artist', 'artist^2',
'genre', 'genre',
'track_type', 'track_type',
'show_songs', 'show_songs^2',
], ],
], ],
], ],
@ -71,7 +72,7 @@ class Search {
'multi_match' => [ 'multi_match' => [
'query' => $query, 'query' => $query,
'fields' => [ 'fields' => [
'title', 'title^2',
'artist', 'artist',
'tracks', 'tracks',
], ],
@ -87,8 +88,9 @@ class Search {
'multi_match' => [ 'multi_match' => [
'query' => $query, 'query' => $query,
'fields' => [ 'fields' => [
'title', 'title^3',
'user', 'curator',
'tracks^2',
], ],
], ],
], ],
@ -102,7 +104,8 @@ class Search {
'multi_match' => [ 'multi_match' => [
'query' => $query, 'query' => $query,
'fields' => [ 'fields' => [
'display_name', 'display_name^2',
'tracks',
], ],
], ],
], ],
@ -150,7 +153,14 @@ class Search {
} }
$caseStatement .= 'END'; $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)) ->whereIn('id', array_keys($ids))
->orderBy(DB::raw($caseStatement)) ->orderBy(DB::raw($caseStatement))
->get(); ->get();

View file

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

View file

@ -27,7 +27,7 @@ use Illuminate\Foundation\Bus\DispatchesJobs;
use Auth; use Auth;
use Cache; use Cache;
use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException; use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch; use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Poniverse\Ponyfm\Traits\TrackCollection; use Poniverse\Ponyfm\Traits\TrackCollection;
use Poniverse\Ponyfm\Traits\SlugTrait; use Poniverse\Ponyfm\Traits\SlugTrait;
use Venturecraft\Revisionable\RevisionableTrait; use Venturecraft\Revisionable\RevisionableTrait;
@ -61,7 +61,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/ */
class Playlist extends Model class Playlist extends Model
{ {
use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection, RevisionableTrait, IndexedInElasticsearch; use SoftDeletes, SlugTrait, DispatchesJobs, TrackCollection, RevisionableTrait, IndexedInElasticsearchTrait;
protected $elasticsearchType = 'playlist'; protected $elasticsearchType = 'playlist';
@ -295,6 +295,10 @@ class Playlist extends Model
* @return array * @return array
*/ */
public function toElasticsearch() { 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 DB;
use Elasticsearch; use Elasticsearch;
use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException; use Poniverse\Ponyfm\Exceptions\TrackFileNotFoundException;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch; use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Poniverse\Ponyfm\Traits\SlugTrait; use Poniverse\Ponyfm\Traits\SlugTrait;
use Exception; use Exception;
use External; use External;
@ -97,7 +97,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/ */
class Track extends Model class Track extends Model
{ {
use SoftDeletes, IndexedInElasticsearch; use SoftDeletes, IndexedInElasticsearchTrait;
protected $elasticsearchType = 'track'; protected $elasticsearchType = 'track';

View file

@ -29,7 +29,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Foundation\Auth\Access\Authorizable;
use Auth; use Auth;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Poniverse\Ponyfm\Traits\IndexedInElasticsearch; use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait;
use Venturecraft\Revisionable\RevisionableTrait; use Venturecraft\Revisionable\RevisionableTrait;
/** /**
@ -65,7 +65,7 @@ use Venturecraft\Revisionable\RevisionableTrait;
*/ */
class User extends Model implements AuthenticatableContract, CanResetPasswordContract, \Illuminate\Contracts\Auth\Access\Authorizable 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'; protected $elasticsearchType = 'user';
@ -258,6 +258,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
* @return array * @return array
*/ */
public function toElasticsearch() { 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 * @package Poniverse\Ponyfm\Traits
*/ */
trait IndexedInElasticsearch trait IndexedInElasticsearchTrait
{ {
/** /**
* Returns this model in Elasticsearch-friendly form. The array returned by * Returns this model in Elasticsearch-friendly form. The array returned by
@ -83,7 +83,7 @@ trait IndexedInElasticsearch
} }
public function ensureElasticsearchEntryIsUpToDate() { public function ensureElasticsearchEntryIsUpToDate() {
if ($this->trashed()) { if (method_exists($this, 'trashed') && $this->trashed()) {
$this->deleteElasticsearchEntry(); $this->deleteElasticsearchEntry();
} else { } else {
$this->createOrUpdateElasticsearchEntry(); $this->createOrUpdateElasticsearchEntry();

View file

@ -42,6 +42,7 @@ class SetupElasticsearch extends Migration
'properties' => [ 'properties' => [
'title' => ['type' => 'string'], 'title' => ['type' => 'string'],
'artist' => ['type' => 'string', 'index' => 'not_analyzed'], 'artist' => ['type' => 'string', 'index' => 'not_analyzed'],
'published_at' => ['type' => 'date'], 'published_at' => ['type' => 'date'],
'genre' => ['type' => 'string', 'index' => 'not_analyzed'], 'genre' => ['type' => 'string', 'index' => 'not_analyzed'],
'track_type' => ['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 // See: https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html
'tracks' => ['type' => 'string'] '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']
]
],
] ]
] ]
]); ]);