Files
iTunes/dashboard/src/app/els.service.ts

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);
}
}