193 lines
6.5 KiB
TypeScript
193 lines
6.5 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { Headers, Http } from '@angular/http';
|
|
|
|
import { Observable } from 'rxjs/Observable';
|
|
import 'rxjs/add/operator/toPromise';
|
|
import 'rxjs/add/operator/map';
|
|
|
|
import { Song } from './object/song';
|
|
import { Album } from './object/album';
|
|
import { Artist } from './object/artist';
|
|
|
|
@Injectable()
|
|
export class ElsService {
|
|
private elsUrl = 'http://localhost:9200/itunessongs/';
|
|
private headers = new Headers({'Content-Type': 'application/json'});
|
|
|
|
public static readonly DEFAULT_SIZE:number = 50;
|
|
|
|
constructor(private http: Http) { }
|
|
|
|
getTime(): Promise<number> {
|
|
return this.http.post(this.elsUrl + "_search", JSON.stringify({aggs:{sum_time:{sum:{field:"Total Time"}}},"size":0}), {headers: this.headers})
|
|
.toPromise()
|
|
.then(res => res.json().aggregations.sum_time.value as number)
|
|
.catch(this.handleError);
|
|
}
|
|
|
|
getTimeSlowly(): Promise<number> {
|
|
return new Promise(resolve => {
|
|
setTimeout(() => resolve(this.getTime()), 2000);
|
|
});
|
|
}
|
|
|
|
getSize(): Promise<number> {
|
|
return this.http.post(this.elsUrl + "_search", JSON.stringify({aggs:{sum_time:{sum:{field:"Size"}}},"size":0}), {headers: this.headers})
|
|
.toPromise()
|
|
.then(res => res.json().aggregations.sum_time.value as number)
|
|
.catch(this.handleError);
|
|
}
|
|
|
|
getSizeSlowly(): Promise<number> {
|
|
return new Promise(resolve => {
|
|
setTimeout(() => resolve(this.getSize()), 2000);
|
|
});
|
|
}
|
|
|
|
getCountSong(type: string): Promise<number> {
|
|
return this.http.get(this.elsUrl + type + "/_count")
|
|
.toPromise()
|
|
.then(res => res.json().count as number)
|
|
.catch(this.handleError);
|
|
}
|
|
|
|
getCountNeverListenSong(): Promise<number> {
|
|
return this.http
|
|
.post(this.elsUrl + "song/_count",
|
|
JSON.stringify({"query":{"bool":{"must_not": {"exists": {"field": "Play Count"}}}}}),
|
|
{headers: this.headers})
|
|
.toPromise()
|
|
.then(res => res.json().count as number)
|
|
.catch(this.handleError);
|
|
}
|
|
|
|
getTrackCountSlowly(type: string): Promise<number> {
|
|
return new Promise(resolve => {
|
|
setTimeout(() => resolve(this.getCountSong(type)), 2000);
|
|
});
|
|
}
|
|
|
|
getMostPlayedTrack(): Observable<Song[]> {
|
|
// Thank to http://chariotsolutions.com/blog/post/angular2-observables-http-separating-services-components/
|
|
// for the map part
|
|
|
|
// Could be shorter but I think it's more readable like this.
|
|
return this.http
|
|
.post(this.elsUrl + "song/_search",
|
|
JSON.stringify({"sort":[{"Play Count":{"order":"desc"}}],"size": 5}),
|
|
{headers: this.headers})
|
|
.map(res => {
|
|
return res.json().hits.hits;
|
|
})
|
|
.map((hits: Array<any>) => {
|
|
let result:Array<Song> = [];
|
|
hits.forEach((hit) => {
|
|
result.push(hit._source);
|
|
});
|
|
return result;
|
|
});
|
|
// Shorter way:
|
|
// .map(res => {
|
|
// let result: Array<Song> = [];
|
|
// res.json().hits.hits.forEach(element => {
|
|
// result.push(element._source);
|
|
// });
|
|
// return result;
|
|
// });
|
|
}
|
|
|
|
getAlbumSongs(albumName: string, from: number = 0): Observable<Song[]> {
|
|
console.debug("getAlbumSongs- Album name: " + albumName + " - from: " + from);
|
|
return this.http
|
|
.post(this.elsUrl + "song/_search",
|
|
JSON.stringify({"query":{"match_phrase":{"Album":albumName}},"size": ElsService.DEFAULT_SIZE, "from": from}),
|
|
{headers: this.headers})
|
|
.map(res => {
|
|
return res.json().hits.hits;
|
|
})
|
|
.map((hits: Array<any>) => {
|
|
let result:Array<Song> = [];
|
|
hits.forEach((hit) => {
|
|
result.push(hit._source);
|
|
});
|
|
return result;
|
|
});
|
|
}
|
|
|
|
getArtistSongs(artistName: string, from: number = 0): Observable<Song[]> {
|
|
console.debug("getArtistSongs- Artist name: " + artistName + " - from: " + from);
|
|
return this.http
|
|
.post(this.elsUrl + "song/_search",
|
|
JSON.stringify(
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"should": [
|
|
{"match_phrase" : { "Album Artist" : artistName }},
|
|
{"match_phrase" : { "Artist" : artistName }}
|
|
]
|
|
}
|
|
},
|
|
"size": ElsService.DEFAULT_SIZE,
|
|
"from": from
|
|
}),
|
|
{headers: this.headers})
|
|
.map(res => {
|
|
return res.json().hits.hits;
|
|
})
|
|
.map((hits: Array<any>) => {
|
|
let result:Array<Song> = [];
|
|
hits.forEach((hit) => {
|
|
result.push(hit._source);
|
|
});
|
|
return result;
|
|
});
|
|
}
|
|
|
|
getAlbum(albumName: string): Observable<Album> {
|
|
return this.http
|
|
.post(this.elsUrl + "album/_search",
|
|
JSON.stringify({"query":{"match_phrase":{"Album":albumName}},"size": ElsService.DEFAULT_SIZE}),
|
|
{headers: this.headers})
|
|
.map(res => {
|
|
return res.json().hits.hits;
|
|
})
|
|
.map((hits: Array<any>) => {
|
|
if (hits.length < 1) {
|
|
console.info('No album "' + albumName + '" found.');
|
|
return undefined;
|
|
}
|
|
if (hits.length > 1) {
|
|
console.error('More than one album "' + albumName + '" found (' + hits.length + '), return the first.');
|
|
}
|
|
return hits[0]._source;
|
|
});
|
|
}
|
|
|
|
getArtist(artistName: string): Observable<Artist> {
|
|
return this.http
|
|
.post(this.elsUrl + "artist/_search",
|
|
JSON.stringify({"query":{"match_phrase":{"Artist":artistName}},"size": ElsService.DEFAULT_SIZE}),
|
|
{headers: this.headers})
|
|
.map(res => res.json().hits.hits)
|
|
.map((hits: Array<any>) => {
|
|
// Theorically, my script prevent to found two documents with this query.
|
|
// But Prevention is better than cure as Shakespeare said
|
|
console.log(hits.length);
|
|
if (hits.length < 1) {
|
|
console.info('No artist "' + artistName + '" found.');
|
|
return undefined;
|
|
}
|
|
if (hits.length > 1) {
|
|
console.error('More than one artist "' + artistName + '" found (' + hits.length + '), return the first.');
|
|
console.error('This is not normal!')
|
|
}
|
|
return hits[0]._source;
|
|
});
|
|
}
|
|
|
|
private handleError(error: any): Promise<any> {
|
|
console.error('An error occurred', error); // for demo purposes only
|
|
return Promise.reject(error.message || error);
|
|
}
|
|
} |