A recommendation tool to find the most popular tracks for each tag.
Explore the docs »
View on Heroku
·
Report Bug
·
Request Feature
This project provides a Resonate.is listener an upgraded experience by allowing users to search for the most popular tracks for a given tag and being able to also find convenient recommendations from different tags through an upgraded user interface. Through this improved search algorithm, people can explore new recommended tracks and add what they like to a personalized playlist through our responsive web application. The playlist is stored via Neo4j to provide an easy-to-use query experience that works seamlessly for the user and allows the engineer to graphically maintain and update connections in a concise manner.
- Python
- Django Web Framework
- Neo4j Graph Database
- Django-Neomodel Plugin
- Bootstrap
- HTML
- CSS
- JavaScript
- jQuery
-
Create a free listener account with Resonate.is
-
Install Python 3.9
python --version
-
Django 3.2.5
-
Neo4j Database
You can manage your own database locally using Neo4j Desktop, or go to Neo4j Aura for a fully managed cloud database.
Before you start, install the APOC Library plugin.
CREATE CONSTRAINT ON (a:Ruser) ASSERT a.uuid IS UNIQUE;
CREATE CONSTRAINT ON (a:TrackGroup) ASSERT a.uuid IS UNIQUE;
CREATE CONSTRAINT ON (a:Track) ASSERT a.uuid IS UNIQUE;
WITH 'https://api.resonate.coop/v2/' AS uri
CALL apoc.load.json(uri + 'trackgroups?type=playlist') // in this example, grabbing listener-generated playlists
YIELD value
UNWIND value["data"] as data
MERGE (u:RUser {uuid:toString(data["user"]["id"])})
MERGE (t:TrackGroup {uuid:toString(data["id"])})
MERGE (u)-[:OWNS]->(t)
SET t.title = data["title"]
SET t.type = data["type"]
SET t.slug = data["slug"]
SET t.tracks_imported = false
WITH 'https://api.resonate.coop/v2/' AS uri
CALL apoc.load.json(uri + 'trackgroups') // in this example, grabbing listener-generated playlists
YIELD value
UNWIND value["data"] as data
MERGE (u:RUser {uuid:toString(data["user"]["id"])})
MERGE (t:TrackGroup {uuid:toString(data["id"])})
MERGE (u)-[:OWNS]->(t)
SET t.title = data["title"]
SET t.type = data["type"]
SET t.slug = data["slug"]
SET t.tracks_imported = false
CALL apoc.periodic.commit(
"MATCH (tg:TrackGroup)
WHERE NOT tg.tracks_imported
SET tg.tracks_imported = true
WITH tg limit $limit
WITH 'https://api.resonate.coop/v2/' AS uri, tg.uuid as tg_id
CALL apoc.load.json(uri + 'trackgroups/' + tg_id )
yield value
UNWIND value['data']['items'] as items
MERGE (u:RUser {uuid:toString(items['track']['creator_id'])})
MERGE (track:Track {uuid:toString(items['track']['id'])})
MERGE (tg)-[:HAS_TRACK]->(track)
MERGE (track)<-[:CREATED]-(u)
SET track.title = items['track']['title']
SET track.tags_imported = false
RETURN count(*)
",
{limit:10});
CALL apoc.periodic.commit(
"
match (tg:TrackGroup)-[:HAS_TAG]-(t:Tag)
where not (tg)-[:HAS_TRACK]-(:Track)
WITH tg limit $limit
WITH 'https://api.resonate.coop/v2/' AS uri, tg.uuid as tg_id, tg
CALL apoc.load.json(uri + 'trackgroups/' + tg_id )
yield value
UNWIND value['data']['items'] as items
MERGE (u:RUser {uuid:toString(items['track']['creator_id'])})
MERGE (track:Track {uuid:toString(items['track']['id'])})
MERGE (tg)-[:HAS_TRACK]->(track)
MERGE (track)<-[:CREATED]-(u)
SET track.title = items['track']['title']
SET track.tags_imported = false
RETURN count(tg)",
{limit:1});
CALL apoc.periodic.commit(
"
MATCH (u:RUser)-[:CREATED]->(track:Track)
WHERE not u.uuid in ['7212','4315','4414'] // bad data
AND NOT track.tags_imported
SET track.tags_imported = true
WITH u as artist, u.uuid as user_id, count(DISTINCT track) as tracks,'https://api.resonate.coop/v2/' as uri
ORDER BY tracks desc
LIMIT $limit
CALL apoc.load.json(uri + 'artists/' + user_id + '/releases') // grabbing all
YIELD value
UNWIND value['data'] as data
UNWIND data['tags'] as tags
MERGE (t:TrackGroup {uuid:toString(data['id'])})
MERGE (user:RUser {uuid:toString(user_id)})-[:OWNS]->(t)
MERGE (tag:Tag {name:toLower(tags)})
MERGE (tag)<-[:HAS_TAG]-(t)
SET tag.uuid=apoc.create.uuid()
SET t.title = data['title']
SET t.type = data['type']
RETURN count(*)
",
{limit:5});
CALL apoc.periodic.commit(
"
MATCH (u:RUser)
WHERE u.twitter_checked=false
WITH u.uuid as user_id, 'https://stream.resonate.coop/api/v2/' as uri, u as artist
LIMIT $limit
CALL apoc.load.json(uri + 'artists/' + user_id) // grabbing all
YIELD value
UNWIND value['data']['links'] as links
WITH apoc.data.url(links['href']) as unwound_links, artist as artist,links
WHERE unwound_links.host='twitter.com'
SET artist.twitter=toLower(substring(unwound_links.path,1))
SET artist.twitter_checked=true
RETURN count(artist)",
{limit:100});
- Clone the repository
git clone https://github.com/Neologic-Audio/reso-neo-playlist.git
Option 1: Using command-line
1. Open up the terminal to the base level of the project folder
2. Type the following commands
* python(python3) -m venv venv <!--different for mac-->
* source venv/bin/activate (Unix OS and macOS)
** venv/bin/activate (Windows)
* pip install -r requirements.txt
3. The packages should be installed
Option 2: Use an IDE (Similar setup depending on the IDE)
In PyCharm (example of setup):
1. Go to File Settings
2. In the Python Interpreter tab, click the gear Icon
3. Click Add (new interpreter)
4. On the virtual environment page, click to create a new environment
* Keep the project location as the base project filepath
* Make sure to use the Python source your Operating System is using <!-- python 3.9 for mac -->
** If you have multiple installations of Python, use "where python" (for Windows) or "which python3" (for mac) in your terminal to find the correct file location
* Keep inheritance and availability unchecked, since it's better to go on a project by project basis
5. Click OK
6. You should be good to run the application afterwards
* note: if your installation is using any version of Django 4.0, then the dependencies will be broken and conflict.
Environment variables can be used for configuration. They must be set before running the project to avoid receiving a server error. This can be configured either through your IDE or PATHs. #should configure by itself when py manage.py migrate
Neo4j Desktop:
export NEO4J_BOLT_URL=bolt://neo4j:password@host-or-ip:port
For Neo4j Aura:
export NEO4J_BOLT_URL=neo4j+s://neo4j:password@host-or-ip:port
Run migrations and create your superuser (for the admin, this is using an SQLite database)
Option 1: Windows
py manage.py migrate
py manage.py createsuperuser
py manage.py runserver
Option 2: Mac
python3 manage.py migrate
python3 manage.py createsuperuser #only for the first time
python3 manage.py runserver
Go to your Heroku dashboard and create a new app and add its git remote to your local clone of this app.
Go your Heroku's app's settings and add the NEO4J_BOLT_URL
environment variable with the correct credentials:
NEO4J_BOLT_URL="bolt://neo4j:password@host-or-ip:port"
Follow the deployment instructions inside your Heroku app.
Adding gunicorn to your project for web deployment
(https://devcenter.heroku.com/articles/python-gunicorn)
Now you can push to Heroku:
git push heroku master/main (depending on how project's original git branch is named)
Noted issues that can interfere with deployment:
Libgeos C DLL missing
To fix:
"This is ultimately because Shapely is currently an install requirement of Neomodel. Shapely requires a C lib to be installed which may/may not be present on your OS.
On UNIX you can simply install this with 'apt-get install libgeos-dev'"
To actually install via Heroku requires several steps:
1. You would need to include a Heroku buildpack into your application (https://github.com/heroku/heroku-buildpack-apt)
2. Create an Aptfile in your root directory and add 'libgeos-dev' as its contents (similar problem here https://stackoverflow.com/questions/34104909/heroku-python-app-with-custom-package-in-aptfile-no-python-packages-installed)
3. Make sure that Gunicorn is installed so that this works
4. Push to Heroku
Application only loads HTML, no Javascript or CSS
To fix:
1. Add Whitenoise to your application (https://devcenter.heroku.com/articles/django-assets)
2. Use Postgresql provided by Heroku application and add to project settings (extract credentials necessary via clicking on the DB in Heroku)
- Ariel Fainstain (Team Lead)
- Adejsha Francis
- Samuel Parker
- Maxim Stroganov
- Gabrielle White
- The SilverLogic for sponsoring this project
- Florida Atlantic University - College of Engineering and Computer Science
- reso-tag-charts
- Resonate.is