New post

Find

Article
· Dec 31, 2024 8m read

Creating a REST client to get Tracks from Spotify REST API - Part4 Save the Search Result

Last Chapter: Creating a REST client to get Tracks from Spotify REST API - Part3 Get some data (e.g. Artists)

Git link: https://github.com/ecelg/InterSystems-IRIS-as-a-Spotify-REST-client

 

OK we create a method to get data and lets try to get some Tracks 😁

Now open a terminal and test the code

Run the following line

w ##class(rest.utli.requestUtli).getdata("Spotify","/search","offset=5&limit=10&query=Shape%20of%20you&type=track&market=SG")

ooooo no seems there is huge among of data returns.....😥

I would like to know what information can be found in 1 track....🤔 how about only query 1 track?

let's try the following

w ##class(rest.utli.requestUtli).getdata("Spotify","/tracks/5cy3CNTBZbX8vZUIsu4p7K","market=SG")

Ok... there are quite a lot of information about a track...🤔... but I am pretty sure I don't need them all....🤔

maybe name, spotify url, album basic information and artists basic information are good enough for me....  just make it simple is ok

the hierarchy of the 3 object should be like this...

 

So... let's go

 


1. Build the object class to store the Artists information

create a spotify folder under rest

create a class  artists.cls

Create a Persistent object and extend it with the %JSON.Adaptor for generating JSON string in a convenience way.

you can use a different key field name of the JSON  string by adding the setting %JSONFIELDNAME

Class rest.spotify.artists Extends (%Persistent, %JSON.Adaptor)
{

Property name As %String;
Property spotifyid As %String(%JSONFIELDNAME = "id");
Property spotifyurl As %String(%JSONFIELDNAME = "spotify", MAXLEN = 100);
ClassMethod checkRowid(spotifyid As %String = "") As %Integer [ Language = objectscript ]
{
	//w ##class(rest.spotify.artists).checkRowid("6eUKZXaKkcviH0Ku9w2n3V")
	set rtn=0
	set rowid=""
	&sql(select id into :rowid from rest_spotify.artists where spotifyid=:spotifyid )
	//w rowid,!
	if rowid'="" set rtn=rowid
	return rtn
}
}

Save the class

 


2. Build the object class to store the Album information

under the spotify folder create a class album.cls

Create a Persistent object and extend it with the %JSON.Adaptor

Class rest.spotify.album Extends (%Persistent, %JSON.Adaptor)
{

Property name As %String;
Property albumtype As %String(%JSONFIELDNAME = "album_type");
Property releasedate As %String(%JSONFIELDNAME = "release_date");
Property spotifyid As %String(%JSONFIELDNAME = "id");
Property spotifyurl As %String(%JSONFIELDNAME = "spotify", MAXLEN = 100);
Property artists As artists;
ClassMethod checkRowid(spotifyid As %String = "") As %Integer [ Language = objectscript ]
{
	//w ##class(rest.spotify.album).checkRowid("6rUYFVeZl5rExNNV8seV98")
	set rtn=0
	set rowid=""
	&sql(select id into :rowid from rest_spotify.album where spotifyid=:spotifyid )
	//w rowid,!
	if rowid'="" set rtn=rowid
	return rtn
}
}

Save the class

 


3. Build the object class to store the Track information

under the spotify folder create a class track.cls

Create a Persistent object and extend it with the %JSON.Adaptor

Class rest.spotify.track Extends (%Persistent, %JSON.Adaptor)
{

Property name As %String;
Property popularity As %String;
Property tracknumber As %String(%JSONFIELDNAME = "track_number");
Property spotifyid As %String(%JSONFIELDNAME = "id");
Property spotifyurl As %String(%JSONFIELDNAME = "spotify", MAXLEN = 100);
Property album As album;
ClassMethod checkRowid(spotifyid As %String = "") As %Integer [ Language = objectscript ]
{
	//w ##class(rest.spotify.track).checkRowid("1cKuv7hAoX7ZN8f39hlDKX")
	set rtn=0
	set rowid=""
	&sql(select id into :rowid from rest_spotify.track where spotifyid=:spotifyid )
	//w rowid,!
	if rowid'="" set rtn=rowid
	return rtn
}

}

Save the class

 


4.  Now, we try to study what is the result look like if we try to search a track

Let's try to run the following command in the terminal again

w ##class(rest.utli.requestUtli).getdata("Spotify","/search","offset=5&limit=10&query=Shape%20of%20you&type=track&market=SG")

paste the result in a JSON fromatter for easy reading

Mummmm...🤨 mummmmm..............🤔

I think ... I need to write a function to loop through the the items of the result  JSON to get the tracks information and save it. We also need to save the album information inside the items.......😐........ and...... also.... loop through the artist information inside the items and save them........oooooooooooooooooooooo.... tones of work!!!

 


5. write some functions to loop though and save the search track result.

Create a class spotifyUtli.cls under the folder utli

write the following class methods

Class rest.utli.spotifyUtli Extends %RegisteredObject
{
ClassMethod getSearchResult(str As %String = "") As %Status [ Language = objectscript ]
{
	//w ##class(rest.utli.spotifyUtli).getSearchResult()
	set rtn=0
	set a={}.%FromJSON(str) //from json tn dynamic object
	//w a,!
	// loop through the object using an iterator
	set iter = a.%GetIterator()
	while iter.%GetNext(.key , .value ) 
	{
		//write !, ?5, "Key: ", key, ", Value: ", value, " type: ", a.%GetTypeOf(key)_" with value "_a.%Get(key)
		if key="tracks"
		{
			//w !,?10,"call get tracks",!
			set std=##class(rest.utli.spotifyUtli).getTrakSearchResult(.value)
		}
		//set b=value
		//w !,?10,b.name
	}
	
	kill a
	return rtn
}

ClassMethod getTrakSearchResult(ByRef tracksobj As %DynamicObject) As %Status [ Language = objectscript ]
{
	//w ##class(rest.utli.spotifyUtli).getTrakSearchResult()
	set rtn=0
	// loop through the object using an iterator
	set iter = tracksobj.%GetIterator()
	while iter.%GetNext(.key , .value ) 
	{
		//write !, ?5, "Key: ", key, ", Value: ", value
		if key="items"
		{
			// loop through the array using an iterator twice**
			set iter1=value.%GetIterator()
			while iter1.%GetNext(.key1 , .value1 )
			{
				kill tkobj
				set tkobj=##class(rest.spotify.track).%New()
				set rowid=""
				//write !, ?10, "Key: ", key1, ", Value: ", value1
				set iter2=value1.%GetIterator()
				while iter2.%GetNext(.key2 , .value2)
				{
					//write !, ?10, "Key: ", key2, ", Value: ", value2
					if key2="album"
					{
						//set std=##class(rest.utli.spotifyUtli).getTrakSearchAlbumResult(.value2) //w !,?15,"call get album"
						set album=##class(rest.spotify.album).%New()
						set std=##class(rest.utli.spotifyUtli).getTrakSearchAlbumResult(.value2,.album)
						set tkobj.album=album
						kill album
					}
					if key2="external_urls"
					{
						//w !,?15,value2.spotify
						set tkobj.spotifyurl=value2.spotify
					}
					if key2="name"
					{
						//w !,?15,"name: ",value2
						set tkobj.name=value2
					}
					if key2="popularity"
					{
						//w !,?15,"popularity: ",value2
						set tkobj.popularity=value2
					}
					if key2="track_number"
					{
						//w !,?15,"track_number: ",value2
						set tkobj.tracknumber=value2
					}
					if key2="id"
					{
						//w !,?15,"id: ",value2
						set tkobj.spotifyid=value2
						set rowid=##class(rest.spotify.track).checkRowid(value2)
					}
				}
				
				if (rowid=0)
				{
					set std=tkobj.%Save()
				}
				kill tkobj
			}
		}		
	}
	
	set rtn=1
	return rtn
}

ClassMethod getTrakSearchAlbumResult(ByRef albumobj As %DynamicObject, ByRef album As rest.spotify.album) As %Status [ Language = objectscript ]
{
	//w ##class(rest.utli.spotifyUtli).getTrakSearchAlbumResult()
	set rtn=0
	kill alobj
	set alobj=##class(rest.spotify.album).%New()
	set rowid=""
	// loop through the object using an iterator
	set iter = albumobj.%GetIterator()
	while iter.%GetNext(.key , .value ) 
	{
		//write !, ?5, "Key: ", key, ", Value: ", value
		if key="name"
		{
			//w !,?10,"name: ",value
			set alobj.name=value
			
		}
		if key="release_date"
		{
			//w !,?10,"release_date: ",value
			set alobj.releasedate=value
		}
		if key="id"
		{
			//w !,?10,"id: ",value
			set alobj.spotifyid=value
			set rowid=##class(rest.spotify.album).checkRowid(value)
		}
		if key="artists"
		{
			set artist=##class(rest.spotify.artists).%New()
			set std=##class(rest.utli.spotifyUtli).getTrakSearchArtistsResult(.value,.artist)
			set alobj.artists=artist
			kill artist
			//w !,?10,"call get artists"
		}
		if key="album_type"
		{
			//w !,?10,"album_type: ",value
			set alobj.albumtype=value
			
		}
		if key="external_urls"
		{
			//w !,?10,value.spotify
			set alobj.spotifyurl=value.spotify
		}
	}
	
	if (rowid=0)
	{
		set std=alobj.%Save()
		set album=alobj
	}
	if (rowid>0)
	{
		set album=##class(rest.spotify.album).%OpenId(rowid)
	}
	kill alobj
	
	set rtn=1
	return rtn
}

ClassMethod getTrakSearchArtistsResult(ByRef artistsobj As %DynamicObject, ByRef artist As rest.spotify.artists) As %Status [ Language = objectscript ]
{
	//w ##class(rest.utli.spotifyUtli).getTrakSearchArtistsResult()
	set rtn=0
	// loop through the array using an iterator twice**
	set iter = artistsobj.%GetIterator()
	while iter.%GetNext(.key , .value ) 
	{
		kill aobj
		set aobj=##class(rest.spotify.artists).%New()
		set rowid=""
		set iter1 = value.%GetIterator()
		while iter1.%GetNext(.key1 , .value1 ) 
		{
			//write !, ?5, "Key: ", key1, ", Value: ", value1
			if key1="id"
			{
				set aobj.spotifyid=value1
				set rowid=##class(rest.spotify.artists).checkRowid(value1)
			}
			if key1="name"
			{
				//w !,?12,"name: ",value1
				set aobj.name=value1
			}
			if key1="external_urls"
			{
				//w !,?12,value1.spotify
				set aobj.spotifyurl=value1.spotify
			}
		}
		
		if (rowid=0)
		{
			set std=aobj.%Save()
			set artist=aobj
		}
		if (rowid>0)
		{
			set artist=##class(rest.spotify.artists).%OpenId(rowid)
		}
		
		kill aobj
	}
	
	set rtn=1
	return rtn
}
}

Save the class

 


6. Test the class method getSearchResult

Run the following line

w ##class(rest.utli.spotifyUtli).getSearchResult(##class(rest.utli.requestUtli).getdata("Spotify","/search","offset=5&limit=10&query=Shape%20of%20you&type=track&market=SG"))

Seems ok.... so far....😀

 


7. Check the data from the table

 

a. check the artist by the following SQL

SELECT
ID, name, spotifyid, spotifyurl
FROM rest_spotify.artists

b. Check the album by the following SQL

SELECT
ID, albumtype, artists->name as artist, name, releasedate, spotifyid, spotifyurl
FROM rest_spotify.album

 

c. Check the track by the following SQL

SELECT
ID, album->name as album, album->artists->name as artist, name, popularity, spotifyid, spotifyurl, tracknumber
FROM rest_spotify.track

 

Yeah!!!! Working!!! I can create my track list by querying Spotify now!!!!!!!!😂🤣😉

Discussion (0)1
Log in or sign up to continue
Question
· Dec 31, 2024

How to Connect Laravel 11 with InterSystems IRIS Data Platform via ODBC?

Hi everyone,

I'm trying to connect my Laravel application with the InterSystems IRIS Data Platform using ODBC.I need help setting up the ODBC connection and querying the database properly. What is the proper way to configure Laravel to work with an ODBC connection to InterSystems IRIS?

Any help would be greatly appreciated!

Thanks in advance!

1 Comment
Discussion (1)1
Log in or sign up to continue
Question
· Dec 30, 2024

Unique Index Open on Empty String

I have a unique index on two properties in a class, and I want to open the instance by index key with one of the two properties is set to the empty string. Is this possible to perform?

Take the example class here

Class TestIndex
{

Property Mandatory as TestClass [Required];
Property Alternate as TestClass;
Property AltOrEmpty As %String [ Calculated, Required, SqlComputeCode = {Set {*} = $Case({Alternate},"":$c(0),:{Alternate})}, SqlComputed ];
Index AlternateMandatory on (Mandatory, AltOrEmpty) [ Unique ];
}

And example data as

Mandatory Alternate AltOrNUL
2    
2 3 3

I can open the second line in the table as 

>set testInstance = ##class(TestIndex).AlternateMandatoryOpen(2,3,.st)
>w st
1

And I want to be able to use the same functionality to open the first line. This would be as open on one valid Id and on empty string, which results in an attempt to open NULL and fails. 

>set testInstance = ##class(TestIndex).AlternateMandatoryOpen(2,"",.st)
>zw st
ERROR #5770: Object open failed because 'AlternateMandatory' key value of '2:NULL' was not found

I am wondering if there is a syntax that would work to find and open this instance based on the unique index containing the empty string, or not based on the inherent design to have a unique index on an empty string.

2 Comments
Discussion (2)2
Log in or sign up to continue
Digest
· Dec 30, 2024

Publicações Desenvolvedores InterSystems, Dezembro 23 - 29, 2024, Resumo

Dezembro 23 - 29, 2024Week at a GlanceInterSystems Developer Community
Digest
· Dec 30, 2024

InterSystems Developers Publications, Week December 23 - 29, 2024, Digest

Articles
Announcements
#InterSystems IRIS
#IRIS contest
#Developer Community Official
Questions
Discussions
December 23 - 29, 2024Week at a GlanceInterSystems Developer Community