[Neo4j] 외부 데이터셋을 활용한 GraphDB 간단 테스트

간단하게 GraphDB를 테스트해보고 정리하였습니다.

[Neo4j] 외부 데이터셋을 활용한 GraphDB 간단 테스트
Photo by fabio / Unsplash

개요

이전 문서에서는 기본 데이터셋을 활용하여 구현하였습니다.

이번 문서에서는 Kaggle에서 데이터를 다운로드하여 테스트해보려고 합니다.

15,000 Music Tracks - 19 Genres (w/ Spotify Data)

이 데이터셋은 1923년부터 2023년까지 1세기에 걸친 음악 역사를 아우르는 3,083명의 아티스트의 15,150개 클래식 히트곡을 포괄적으로 수집한 것입니다. 이 다양한 데이터셋은 19개의 구별되는 장르로 나뉘어 있어, 다양한 시대와 스타일에 걸친 대중음악의 진화를 보여줍니다. 데이터셋의 각 트랙은 Spotify 오디오 특성으로 풍부해져, 음향 특성, 리듬, 템포 및 기타 음악적 특징에 대한 상세한 통찰을 제공합니다. 이는 이 데이터셋을 트렌드 탐색과 장르 비교를 위한 귀중한 자료로 만들 뿐만 아니라, 다양한 시대와 장르에 걸쳐 클래식 히트곡을 정의하는 음향적 특성을 분석하는 데에도 유용하게 합니다
TrackArtistYearDurationTime_SignatureDanceabilityEnergyKeyLoudnessModeSpeechinessAcousticnessInstrumentalnessLivenessValenceTempoPopularityGenre
0Hey Jack Kerouac10,000 Maniacs198720641340.6160.5116-15.89410.02790.038400.0000000.15000.604132.01540Alt. Rock
1Like the Weather10,000 Maniacs198723665340.7700.4591-17.45310.04160.112000.0034300.14500.963133.35143Alt. Rock
2What's the Matter Here?10,000 Maniacs198729117340.5930.8169-7.29310.04100.004490.0000320.08960.51999.97812Alt. Rock
3Trouble Me10,000 Maniacs198919356040.8610.3852-10.05710.03410.154000.0000000.12300.494117.91347Alt. Rock
4Candy Everybody Wants10,000 Maniacs199218596040.6220.87610-6.31010.03050.019300.0068400.09870.867104.97043Alt. Rock

15,000 Music Tracks - 19 Genres (w/ Spotify Data)

총 18개의 컬럼을 가지며 각 컬럼은 다음과 같습니다.

  • Track: 노래 제목
  • Artist: 아티스트 이름
  • Year: 발매 연도
  • Duration: 노래 길이
  • Time_Signature: 박자 (예: 4/4)
  • Danceability: 춤추기 강도
  • Energy: 에너지 레벨
  • Key: 음악의 키
  • Loudness: 음량
  • Mode: 장조/단조
  • Speechiness: 말하는 정도
  • Acousticness: 어쿠스틱 사운드 정도
  • Instrumentalness: 악기 사운드 정도
  • Liveness: 라이브 공연 느낌 정도
  • Valence: 긍정적인 분위기 정도
  • Tempo: 템포 (BPM)
  • Popularity: 인기도
  • Genre: 장르

GraphDB(Neo4j) custom 데이터셋 테스트

Neo4j 생성

Your own data를 선택하고 생성합니다.

데이터 연결하기

Neo4j에서는 web workspace를 지원하고 있으므로 해당 페이지에 접근하여 연결할 수 있습니다.

연결에는 Websocket Bolt가 필요하며 Username과 Password를 입력하면 연결됩니다.

Neo4j Workspace

연결되면 상단에 연결된 샌드박스 환경이 표시되며 Drag & Drop으로 데이터를 불러올 수 있습니다.

데이터를 저장했다면 그래프 모델 정의와 데이터를 노드와 관계로 매핑하여야합니다.

저는 해당 데이터를 간단하게 아래와 같은 노드와 관계로 표현하였습니다.

노드 생성 사이퍼입니다.

UNWIND $nodeRecords AS nodeRecord
WITH *
WHERE NOT nodeRecord.`Track` IN $idsToSkip AND NOT nodeRecord.`Track` IS NULL
MERGE (n: `Track` { `Track`: nodeRecord.`Track` })
SET n.`Year` = toInteger(trim(nodeRecord.`Year`))
SET n.`Duration` = toInteger(trim(nodeRecord.`Duration`))
SET n.`Time_Signature` = toInteger(trim(nodeRecord.`Time_Signature`))
SET n.`Danceability` = toFloat(trim(nodeRecord.`Danceability`))
SET n.`Energy` = toFloat(trim(nodeRecord.`Energy`))
SET n.`Key` = toInteger(trim(nodeRecord.`Key`))
SET n.`Loudness` = toFloat(trim(nodeRecord.`Loudness`))
SET n.`Mode` = toLower(trim(nodeRecord.`Mode`)) IN ['1','true','yes']
SET n.`Speechiness` = toFloat(trim(nodeRecord.`Speechiness`))
SET n.`Acousticness` = toFloat(trim(nodeRecord.`Acousticness`))
SET n.`Instrumentalness` = toFloat(trim(nodeRecord.`Instrumentalness`))
SET n.`Liveness` = toFloat(trim(nodeRecord.`Liveness`))
SET n.`Valence` = toFloat(trim(nodeRecord.`Valence`))
SET n.`Tempo` = toFloat(trim(nodeRecord.`Tempo`))
SET n.`Popularity` = toInteger(trim(nodeRecord.`Popularity`));
UNWIND $nodeRecords AS nodeRecord
WITH *
WHERE NOT nodeRecord.`Artist` IN $idsToSkip AND NOT nodeRecord.`Artist` IS NULL
MERGE (n: `Artist` { `Artist`: nodeRecord.`Artist` });
Load statement
UNWIND $nodeRecords AS nodeRecord
WITH *
WHERE NOT nodeRecord.`Genre` IN $idsToSkip AND NOT nodeRecord.`Genre` IS NULL
MERGE (n: `Genre` { `Genre`: nodeRecord.`Genre` });

관계 생성 사이퍼입니다.

UNWIND $relRecords AS relRecord
MATCH (source: `Track` { `Track`: relRecord.`Track` })
MATCH (target: `Artist` { `Artist`: relRecord.`Artist` })
MERGE (source)-[r: `PERFORMED`]->(target);
UNWIND $relRecords AS relRecord
MATCH (source: `Track` { `Track`: relRecord.`Track` })
MATCH (target: `Genre` { `Genre`: relRecord.`Genre` })
MERGE (source)-[r: `BELONGS_TO`]->(target);

다음과 같이 Metal 장르를 보유한 Artist를 조회하는 Cypher문을 실행하였습니다.

조회해보았을 땐 다음과 같이 출력되는 것을 확인할 수 있었습니다.

MATCH (g:Genre {Genre: "Metal"})<-[:BELONGS_TO]-(t:Track)-[:PERFORMED]->(a:Artist)
RETURN DISTINCT a.Artist

# 리턴
...
{
  "keys": [
    "a.Artist"
  ],
  "length": 1,
  "_fields": [
    "Eric Clapton"
  ],
  "_fieldLookup": {
    "a.Artist": 0
  }
},
...

Metal 장르를 보유한 사람의 수는 171명인 것을 확인할 수 있었습니다.

MATCH (g:Genre {Genre: "Metal"})<-[:BELONGS_TO]-(t:Track)-[:PERFORMED]->(a:Artist)
RETURN COUNT(DISTINCT a) AS MetalArtistCount

# MetalArtistCount
171

앞선 문서상의 연결을 통해 어떻게 데이터를 처리하는지 간단하게 확인해보았습니다.