#SPARQL - RDF 질의어, 데이터베이스를 위한 시맨틱 질의어
본문 바로가기
Programming/SPARQL

#SPARQL - RDF 질의어, 데이터베이스를 위한 시맨틱 질의어

by 권가 2019. 8. 6.

  • 정의: RDF로 표현된 데이터를 찾기 위해 SPARQL이라는 언어를 사용해 자원 기술 프레임워크(RDF) 형식으로 저장된 데이터를 검색, 조작할 수 있다.
    SPARQL 쿼리가 트리플 페턴, 논리 곱, 논리 합, 선택적 패턴을 구성할 수 있도록 한다.
  • 유형: SELECT, ASK, CONSTRUCT, DESCRIBE
    • SELECT -> 사용자가 데이터를 찾는 용도
    • ASK -> 사용자가 원하는 쿼리의 결과가 있는지 없는지 Boolean 값으로 제공
      즉, SELECT=결과를 가져온다. / ASK=있으면 TRUE, 없으면 FALSE
    • CONSTRUCT -> 사용자가 찾고자 하는 쿼리를 출력하면서 동시에 자신이 원하는 템플릿을 입력해주고 쿼리의 결과가 사용자가 원하는 템플릿대로 나오도록 한다.
    • DESCRIBE -> 사용자가 찾고자 하는 정보에 대해서 그 정보와 연결된 모든 트리플을 반환.
    • 유형: SELECT, ASK, CONSTRUCT, DESCRIBE
  • SPARQL 만들기: SPARQL 쿼리는 기본적으로 트리플 패턴으로 사용자가 찾고자하는 결과를 가져온다.
    트리플: 주(S)-술(P)-목(O) 구성된 패턴
  • SPARQL은 교집합 연산으로 이루어져있다.


  • 아래의 링크에서 실습을 진행한다.

http://lod.nl.go.kr/sparql

PREFIX
SELECT / CONSTRUCT / ASK / DESCRIBE
(DISTINCT / REDUCED)
FROM (NAMED)
WHERE
Graph Pattern / OPTIONAL / FILTER / UNION / GRAPH
ORDER BY
LIMIT
OFFSET

SELECT ?id
WHERE { ?id rdf:type http://lod.nl.go.kr/ontology/author . } -> WHERE { "트리플 패턴 정의 .(문장 끝은 마침표) " }

SELECT

질의 유형

?id

찾는 변수( '?' 또는 '$' 를 사용한다.)

WHERE

찾는 조건 입력 부분

?id

트리플의 주어부로 SELECT 문에서도 사용하고 있는 변수

rdf:type

트리플의 술어부로 클래스 타입이 무엇인지 지정

http://lod.nl.go.kr/ontology/author

트리플의 목적부로 Author를 가리키는 URI
  • WHERE 사용하기: 질의하는 대상은 데이터베이스에서는 FROM 절을 사용하여 표현하지만, SPARQL에서는 데이터베이스의 조건에 해당하는 WHERE 절을 사용하는 점이 다르다.
    Ex_) (DataBase) SELECT * FROM s WHERE stuno=1111;
          (SPARQL)  SELECT * WHERE { 주 술 목 }
    하나의 트리플 패턴이 끝날 때에는 마침표(.)를 사용해 트리플의 문장을 끝을 맺는다.
  • 패턴 추가하기
    name을 찾기 위해 찾는 변수 부분엔 ?name을 추가하고 WHERE 절에 패턴을 추가해야 한다.
    국립중앙도서관의 저자정보에는 이름을 <http://xmlns.com/foaf/0.1/name>을 사용해 트리플을 생성했기에 이 정보를 가지고 패턴을 만들어보자

SELECT ?id ?name
WHERE {
?id rdf:type <http://lod.nl.go.kr/ontology/Author> .
?id <http://xmlns.com/foaf/0.1/name> ?name .
}

저자 중 id와 name을 찾는 쿼리.
공통된 주(Subject)를 갖는 트리플 패턴에서는 공통인 S(주)를 하나만 사용하고 술(Predicate)와 목(Object)를 각각 표현하며 그 부분을 세미콜론으로 표현한다.

SELECT ?id ?name
WHERE {
?id rdf:type <http://lod.nl.go.kr/ontology/Author>;
    <http://xmlns.com/foaf/0.1/name> ?name.
}

 

세미콜론으로 공통된 Subject를 갖는 트리플 패턴을 생성한 것으로 마칠 때에는 "."(마침표)를 사용해 마무리한다.

  • PREFIX 사용

SELECT ?id ?name
WHERE {
?id rdf:type <http://lod.nl.go.kr/ontology/Author> ;
    <http://xmlns.com/foaf/0.1/name> ?name

WHERE에서 URI를 길게 쓰지 않고 PREFIX로 간결하게 입력할 수 있다.

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE {
?id rdf:type nlon:Author ;
    foaf:name ?name . 
}

rdf:type 또한 PREFIX로 간추려진 대상이며 상위 PREFIX 선언 부분에 써주지 않아도 되는 이유는 SPARQL를 처리하는 엔젠에서 디폴트로 선언되어 있다.

  • Filter 사용
    특정 조건에 맞는 정보를 찾을 때 사용한다.
    WHERE 절 안에 FILTER를 만들어 조건을 입력하도록 되어 있다.
    WHERE 절에서 트리플의 패턴이 어떠한 것인지 정의되어 있지 않다면 FILTER에서도 적용되지 않는다.

PREFIX nlon: <http://lod.nl.go.kr/ontology>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE {
?id rdf:type nlon:Author ;
    foaf:name ?name ;
    nlon:bithYear ?birth .
}

-> PREFIX로 경량화

 

-> ?id와 ?name을 출력하겠다.

 

-> ?id는 rdf:type이다 nlon:Author이라는

-> (?id는) foaf:name이다 ?name이라는

-> (?id는) nlon:birthYear이다 ?birth라는.

 

 

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE {
?id rdf:type nlon:Author ;
    foaf:name ?name ;
    nlon:birthYear ?birth .
FILTER(?birth=1933)
}

FILTER안에는 (" ") 형식으로 조건을 입력해야한다.
조건을 제한하고자 하는 변수(?birth)와 그 조건을 명시하여 FILTER 완성

  • ORDER BY 사용하기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE {
?id rdf:type nlon:Author ;
foaf:name ?name ;
nlon:birthYear ?birth .
FILTER(?birth=1933)
}
ORDER BY (?id)

+
ORDER BY DESC (?id)
ORDER BY ?name DESC (?id)

ORDER BY ?id = ?id를 오름차순 정렬

+
ORDER BY DESC ?id = ?id를 내림차순 정렬
ORDER BY ?name DESC ?id
= ?name을 오름차순정렬하며 ?id를 내림차순 정렬

  • LIMIT, OFFSET 사용하기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE {
?id rdf:type nlon:Author ;
    foaf:name ?name ;
    nlon:birthYear ?birth .
FILTER(?birth=1933)
}
ORDER BY DESC (?id)
LIMIT 10
OFFSET 120

-> ?id를 내림차순으로 정렬하고
-> 10개만 출력하며 
-> 120번 Data부터 출력하겠다.

  • DISTINCT 사용하기

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT *
WHERE {
?book a bibo:Book ;
rdfs:label ?label ;
dcterms:creator ?person .
?person foaf:name ?name .
}

+
?book a bibo:Book ; 에서 a = rdf:type(어떠한 집합에 속한 것을 찾을 때 사용한다.)

 

DISTINCTSELECT 뒤에 사용하며 그 다음에 중복을 제거할 변수를 사용합니다.

SELECT DISTINCT ?name

  • UNION 사용하기
    수학의 합집합 개념으로 SPARQL 에서도 합집합으로 반환.
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT *
WHERE { 
  { ?id foaf:name "고은"@ko . }
 UNION
  { ?id nlon:birthYear ?birth . 
    FILTER (?birth=1990) }

UNION 사용 시 WHERE 절과 별개로 {...}로 트리플 패턴을 묶어준다. 즉, WHERE { { 패턴 A } UNION { 패턴 B } }

UNION 사용과 비사용의 차이점
UNION 사용 -> 이름이 "고은" 반환, 1990년생 반환
UNION 비사용 -> 이름이 "고은"인 1990년생만 반환

SPARQL은 교집합 연산

  • OPTIONAL 사용하기
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT *
WHERE { 
  ?id foaf:name ?name ;
      nlon:birthYear ?birth ;
      nlon:deathYear ?death . 
  FILTER(?birth>1960)

이 쿼리는 1960년 이후에 태어났지만, 데이터 상으로 몰년이 존재하지 않으면 결과에 포함하지 않는다.(SPARQL은 교집합 연산이기에)
즉, 생년과 몰년 모두 존재하는 데이터만 결과로 반환한다.

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT *
WHERE { 
  ?id foaf:name ?name ;
      nlon:birthYear ?birth . 
  FILTER(?birth>1960)
  OPTIONAL { ?id nlon:deathYear ?death . }

몰년의 존재 여부를 떠나 1960년 이후에 태어난 사람을 모두 반환 받는다.
OPTIONAL은 DB의 조인 연산
찾고자 하는 트리플 패턴은 { }를 사용해 묶고 여러 OPTIONAL 사용 가능하다.
OPTIONAL의 연산은 연산 시 공통 변수의 여부에 따라 연산하는 방식이 달라진다.
공통변수는 ?id에 해당하는 것으로 각각 패턴에서 공통적으로 사용되는 변수.
공통변수가 있을 때 -> Left Outer Join
공통변수가 없을 때 -> Full Join

  • COUNT 사용하기
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT COUNT(*)
WHERE { 
  ?id foaf:name ?name ;
      nlon:birthYear ?birth . 
  FILTER(?birth>1960)
  OPTIONAL { ?id nlon:deathYear ?death . }

검색된 결과의 개수를 알아보는 쿼리.
SELECT 뒤에 위치하며 괄호를 사용해 변수를 묶어 사용.
중복된 결과를 제외하고 개수를 반환하기 위한 쿼리 = SELECT COUNT(DISTINCT ?birth)

  • GROUP BY
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?birth COUNT(?id)
WHERE { 
  ?id foaf:name ?name ;
      nlon:birthYear ?birth . 
  FILTER(?birth>1980)

GROUP BY ?birth

DB와 같이 하나의 변수에 대해 그룹으로 묶어 결과를 가져오는 쿼리.

birth별로 그룹을 형성하고 각각의 그룹에 존재하는 id의 개수를 COUNT로 반환한다.

 

SPARQL Query Language for RDF

RDF is a directed, labeled graph data format for representing information in the Web. This specification defines the syntax and semantics of the SPARQL query language for RDF. SPARQL can be used to express queries across diverse data sources, whether the d

www.w3.org

  • STR

트리플로 표현된 데이터 중 language tag나 XSDDatatype이 무엇인지 표현하는 경우가 있다. 
nlk:KAC201011569 foaf:name "고은"@ko 라는 트리플이 있을 경우 FILTER을 통해 "고은"을 검색하고자 한다면 language tag인 @ko 를 신경써야 하는 부분이 생긴다.

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT *
WHERE {
?id foaf:name ?name
FILTER(STR(?name)="고은")
}

?name이란 변수를 STR 안에 넣어 String 값만 가져와 "고은"이라는 String과 비교하도록 처리된다.
FILTER(?name="고은"@ko)로 대체 가능.

PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>
SELECT * 
WHERE { 
  ?s dcterms:creator ?c . 
FILTER(afn:substring(str(?c),29)='KAC201011569')

STR은 Resource의 URI를 String으로 변환하는 것에도 사용할 수 있다.
저자 아이디가 KAC201011569로 끝나는 서지와 저자를 찾는 쿼리로 URI 형태인 변수 c를 String으로 바꿔 substring(afn:substring)하도록 하고 있다.

여기서 STR은 URI를 String으로 바꾸는 역할을 하고 있다.

  • LANG

Literal로 표현된 값의 language tag를 반환하는 기능도 사용할 수 있다.
즉, LANG을 사용하면, Literal의 language tag만을 가져오게 된다.

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX nlk: <http://lod.nl.go.kr/resource/>
SELECT ?name 
WHERE { 
  nlk:KAC201011569 foaf:name ?name.
FILTER(LANG(?name)='ko')
KAC201011569라는 id를 가진 사람의 이름 중 language tag가 korean인 이름을 가져오는 쿼리이다.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX nlk: <http://lod.nl.go.kr/resource/>
SELECT LANG(?name)
WHERE { 
  nlk:KAC201011569 foaf:name ?name.
KAC201011569라는 id를 가진 사람의 이름의 language tag를 반환하는 쿼리이다.
  • REGEX
SPARQL에서는 정규 표현식을 지원하고 있다.
이러한 정규 표현식을 통해 텍스트를 검색, 추출, 치환 등을 할 수 있다.
SPARQL에서 정규 표현식을 사용하기 위해서는 REGEX를 사용한다.

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX nlk: <http://lod.nl.go.kr/resource/>
SELECT * 
WHERE { 
  ?id foaf:name ?name. 
  FILTER REGEX(STR(?name), '고은')
}


유형별 SPARQL 따라하기

  • 도서 찾기
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
SELECT * 
WHERE { 
  ?s a bibo:Book.
  ?s dct:title ?title.
FILTER REGEX(STR(?title), '사랑')
}

도서 제목 중 '사랑'이라는 단어가 들어간 도서 찾기

PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
SELECT * 
WHERE { 
  ?s a bibo:Book.
  ?s dct:created '2012'
}

2012년에 발간된 도서 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
SELECT * 
WHERE { 
  ?s a bibo:Book.
  ?s nlon:kdc '810.099'
}

KDC가 810.099인 도서 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
SELECT * 
WHERE { 
  ?s a bibo:Book.
  ?s nlon:ddc '895.714'
}

DDC가 895.714인 도서 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
SELECT * 
WHERE { 
  ?s a bibo:Book.
  ?s bibo:isbn '8975490378'
}

ISBN이 8975490375인 도서 찾기

PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
SELECT ?s count(?c)
WHERE { 
  ?s a bibo:Book.
  ?s nlon:kdc '222.2' .
  ?s dct:creator ?c.
} GROUP BY ?s having(count(?c)=2)

KDC222.2로 분류된 도서 중 저자가 2인 도서 찾기

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX bibo: <http://purl.org/ontology/bibo/>
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
SELECT * 
WHERE { 
  ?s a bibo:Book.
  ?s dct:creator ?c .
  ?c nlon:birthYear "1933"^^xsd:int .
}

1933년에 출생한 저자가 저서한 도서 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?person ?name (count(?book) as ?cnt)
WHERE { 
  ?book dct:creator ?person .
  ?person foaf:name ?name .
  FILTER REGEX(STR(?name), '고은')

GROUP BY ?person ?name

이름에 '고은'이 들어간 저자가 저서한 도서의 건수 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?book
WHERE { 
  ?book dct:creator ?person .
  ?person foaf:name ?name .
  FILTER(?person=<http://lod.nl.go.kr/resource/KAC201011569>)

LIMIT 10

고은(KAC201011569)작가의 도서 중 10개만 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?book ?title
WHERE { 
  ?book dct:creator ?person ;
        dct:title ?title .
  ?person foaf:name ?name .
  FILTER(?person=<http://lod.nl.go.kr/resource/KAC201011569>)

ORDER BY ?title

고은(KAC201011569) 작가의 도서 중 제목 오름차순으로 정렬하여 찾기

PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dct: <http://purl.org/dc/terms/>
SELECT ?book ?title
WHERE { 
  ?book dct:creator ?person ;
        dct:title ?title .
  ?person foaf:name ?name .
  FILTER(?person=<http://lod.nl.go.kr/resource/KAC201011569>)

ORDER BY DESC(?title) OFFSET 10
LIMIT 10

고은(KAC201011569)작가의 도서 중 제목 내림차순으로 정렬하여 10번 째 도서부터 10개의 데이터만 찾기

  • 저자찾기
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE { 
  ?id rdf:type nlon:Author ;
      foaf:name ?name .
  FILTER REGEX(STR(?name), '진명')
}

저자 중 '진명' 이라는 이름이 들어가는 저자 찾기

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE { 
  ?id rdf:type nlon:Author ;
      foaf:name ?name ;
      nlon:birthYear '1980'^^xsd:int .
}

1980년에 출생한 저자 찾기

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?id ?name
WHERE { 
  ?id rdf:type nlon:Author ;
      foaf:name ?name ;
      nlon:deathYear '2000'^^xsd:int .
}

2000년에 사망한 저자 찾기

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX nlon: <http://lod.nl.go.kr/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT *
WHERE { 
  ?id rdf:type nlon:Author ;
      foaf:name ?name .
FILTER REGEX(STR(?name), '^[하-힣]')

ORDER BY ?name
LIMIT 20 

'' 으로 시작하는 저자 찾기

  • 해외 도서관 연결 찾기
SELECT ?s ?o 
WHERE { 
  ?s rdf:type <http://purl.org/ontology/bibo/Book> . 
  ?s owl:sameAs ?o .

LIMIT 100 

해외 도서관의 도서와 동일한 도서로 식별된 국립중앙도서관의 도서 찾기

'Programming > SPARQL' 카테고리의 다른 글

#SPARQL - Virtuoso 설치, 적재, 삭제  (0) 2021.04.16

댓글