본문 바로가기
Web Development/SPARQL

[SPARQL / RDF] 검색 기능 구현 및 개선하기(like 검색 엔진)

by 감자맹고우 2022. 1. 18.
728x90
반응형

이전 글에서 단어를 통해 결과를 조회할 수 있는 검색 쿼리를 작성해보았다.

 

▼▼▼ 검색 쿼리를 작성해놓은 이전 글 링크

 

[SPARQL / RDF] 검색어(단어)가 포함된 결과 조회하기

SPARQL로 프로젝트를 진행하다가 검색 기능을 구현하게 됐다. RDB였다면 %나 CONCAT을 이용하면 됐지만, SPARQL에서 해당 쿼리를 작성하려고 하니 쉬워보이지 않았다. 하지만, 역시 SPARQL도 쿼리의 일종

devlifetestcase.tistory.com

 

그러나 단순 쿼리만으로는 검색에 아쉬운 점이 있었다.

 

1. 띄어쓰기
▶ 띄어쓰기 또한 문자로 인식하기 때문에 '가나'와 '가 나'를 검색했을 때 결과가 다르다

2. 순서
▶ 검색결과는 가장 일치하는 문자부터 출력되어야 한다

3. 검색 성능
▶ 글로벌 DBPedia에서 Execution timeout을 30000ms로 설정하고 검색하였을 경우 검색 시간이 많이 소모되는 것을 알 수 있다

 

물론 단어 포함 검색만 제공될 경우, 위의 쿼리만으로 충분하다.

하지만, RDF는 RDB와 달리 웹의 연결을 중심으로 두기 때문에, FORM 검색 보다는 검색엔진에서 검색하는 것처럼 구현해야하는 경우가 있다.

그렇다면 위의 3가지를 고려할 수 밖에 없다.

 

어떻게하면 구현할 수 있을까?

 

사실 아직 정상적인 방법은 찾지 못했다. SPARQL 쿼리 기능이 아직 부족하기 때문인지, 아니면 내가 잘 쓰지 못해서인지 확실하지 않지만, 나는 후자라고 생각한다.

 

그렇지만 인간은 언제나 해결방법을 찾아내기에 고민 끝에 잔꾀를 좀 부리기로 했다.

 

반응형

 

1. 띄어쓰기

 

띄어쓰기는 SQL처럼 %를 이용하면 된다.

필요에 맞게 %의 위치를 변경해주면 된다.

 

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT *
WHERE{
    ?s rdfs:label ?o.
    FILTER (?o LIKE "%%%")
}
LIMIT 20

 

반응형

 

2. 순서

 

순서는 꾀를 좀 부렸다. 가장 일치하는 결과를 먼저 보여주기 위해 UNION을 사용해서 조회한다.

1. 전부 일치하는 결과
2. Full Text가 포함된 결과
3. 모든 음절이 포함된 결과

의 순서로 결과를 조회한다.

 

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT DISTINCT *
WHERE{
    {
        SELECT *
        WHERE{
            ?s rdfs:label ?o.
            FILTER(STR(?o) = "가나")
        }
    }
    UNION
    {
        SELECT DISTINCT *
        WHERE{
            ?s rdfs:label ?o.
           ?o bif:contains "'가나'".
        }
    }
    UNION
    {
        SELECT DISTINCT *
        WHERE{
            ?s rdfs:label ?o.
           ?o bif:contains "'가나*'".
        }
    }
    UNION
    {
        SELECT DISTINCT *
        WHERE{
            ?s rdfs:label ?o.
            FILTER(?o LIKE "%가%나%").
        }
    }
}

 

이렇게 작성할 수 있다.

UNION 외에 DISTINCT와 bif:contains를 사용했는데 DISTINCT는 SQL과 동일하게 중복을 제외한 결과를 조회하고, bif:contains는 Full Text Search를 지원하는 기능이다. 아래에서 조금 더 살펴보겠다.

 

 

FILTER(STR(?o) = "가나") => STR로 전부 일치하는 내용 검색 시 Endpoint에 따라 조회가 안되는 경우가 있다. 그럴 때는 해당 쿼리를 다르게 변경해야 할 것 같다.

 

반응형

 

3. 검색 성능

 

이 부분이 어려웠다. CONTAINS나 UNION 등을 사용하니 검색 성능이 훨씬 떨어졌는데, 이를 보완할 수 있었던 것이 ' bif:contains '였다. bif:contains는 Full Text Search를 지원하는 기능이라고 하는데 아직 어떻게 돌아가는지 정확하게 파악하지 못했다.

 

그렇지만, CONTAINS, LIKE, REGEX 등을 사용하는 것보다 bif:contains로 조회를 하면 매우 빠르게 결과가 조회된다.

하지만, bif:contains를 사용할 때는 2가지 유의점이 있다.

 

(1) 한글 단어로 조회할 때 CONTAINS 등은 더블 쿼테이션("") 안에 단어를 그대로 적으면 되지만, bif:contains는 더블 쿼테이션("")안에 싱글 쿼테이션('')으로 한번 더 감싸주어야 한다.

 

SELECT *
WHERE{
      ?s rdfs:label ?o.
      ?o bif:contains "'가나'".
}

 

(2) bif:contains는 Full Text Search이기 때문에 음절이 따로 떨어져있으면 검색되지 않는다.

 

하지만 bif:contains는 "'가나*'"과 같이 * 기능을 제공한다.

예를 들어 '가나'로만 조회하면 '가나'가 띄어쓰기 등으로 따로 구분된 결과만 조회한다.

그러나 '가나*'로 조회하면 가나 뒤에 다른 글자가 붙어도 조회가 되므로 더 많은 조회가 가능하다.

 

🤞 도움이 되셨기를 바랍니다. 한 번의 클릭과 댓글은 어딘가의 누군가에게 진실로 큰 힘이 됩니다. 🐱‍🏍

 

728x90
반응형

댓글