[Perl] Array 숫자 정렬

Perl 2012.03.03 17:36
저작자 표시 비영리 변경 금지
신고
Posted by 용식
TAG array, perl, sort
저작자 표시 비영리 변경 금지
신고
Posted by 용식
저작자 표시 비영리 변경 금지
신고
Posted by 용식
저작자 표시 비영리 변경 금지
신고
Posted by 용식

검색결과에 대한 기본적인 정렬은
TF-IDF 의한 유사도 점수입니다. 하지만 검색결과를
우리의 입맛대로 조절해야 하는 경우가 있습니다. 이를 위해서 루씬에서는
Sort클래스와 그외 몇가지 확장 가능한 API 제공합니다.

여기서는 우선 Sort클래스의 기본적인 사용법을 확인해보겠습니다.

 

SortTest.java

보시면 2 필드에 대해서 정렬을 하고 있습니다.
Sort클래스의 사용은 우선 정렬에 사용 SortField 생성하고 이를 사용해
Sort클래스의 인스턴스를 만들어서 IndexSearcher 통해 검색을 합니다.

여태까지
IndexSearcher로부터 받아오는 결과 클래스가 TopDocs였지만
필드 정렬을 사용 때는 TopFieldDocs라는 클래스로 결과가 받아집니다.
외에도 Collector 사용하여 결과를 받아 수도 있습니다.

Field 의한 정렬이 되기 위해서는 해당 필드가
NOT_ANALYZED 색인이 되어 있어야 합니다. 그래서 예제 같은 경우
검색을 위한 title 외에 title2라는 필드를 추가로 생성하고 정렬에 사용하고 있습니다.

하나는 SortField 설정하는 SortType 색인시 Field 설정한 타입이 같아야 합니다.

만약 예제에서 sortByField 메서드의 SortField 타입을 INT형으로 바꾼다면
예제는 에러가 발생합니다.

위의 예제가 기본적으로 루씬에서 제공되는 정렬 방법입니다.
다만 정렬이라는 것이 전체 데이터셋을 구한 상태에서의 작업이기 때문에 결과셋이 많을 수록
(즉, 정렬해야 하는 대상 문서가 많을수록...) 속도나 리소스 사용 측면에서 성능이 떨어지는 경우가
있습니다.

이를 조금 다르게 생각해보면
전체 결과를 구해놓고 정렬하는 것이 아니라 TF-IDF점수를 활용하여 정렬하는 것 처럼
대상 문서를 가져 올 때 정렬을 시키면 어떨까? 라는 생각을 해 볼 수 있습니다. 

"짐승"이란 닉네임으로 활동하고 계시는 진성주님의 블로그를 참고해보세요.
(http://blog.softwaregeeks.org/archives/89)

보시면 CustomScoreQuery 클래스를 활용하여 위에서 얘기되었던 고민을 해결하고 있습니다.
즉, 검색 대상 문서를 찾으면서 정렬하는 방식이지요...

이 부분에 대한 설명은 예전에 제가 CustomScoreQuery 사용하여 정렬에 대한 예제와 설명을
작성했던 글이 있습니다.

이 부분은 그 포스트들의 링크로 대신하려고 합니다.

루씬에서뿐만이 아니라 어느 검색엔진에서도 결과Set굉장히 클 때의 정렬은 고민거리가 됩니다.
여러분께서도 루씬을 사용하시면서 문서의 수가 점점 커질 수록 이 부분에 대한 고민이
되실 것 입니다. 그때 하나의 해결책으로써의 방법이 될 수도 있으니 꼭 한번 읽어보시기를 권해드립니다.


이 포스트까지 하면 루씬을 활용하여 검색엔진을 만들어보기 위한
기본적인 내용들은 다 작성을 한 것 같습니다

사실 Analyzer의 구현이 가장 어려운 부분이고 끊임없이 손을대고 사전을 다듬어야 하기 때문에
가장 번거로운 부분이기도 합니다. Analyzer를 제외한 나머지 부분들은 잘 만들어진 API를 잘 사용하는 것이기 때문에
직접 사용하시면서 숙달하시는 방법이 가장 좋은 방법이구요..

이후에는 Replication에 대한 내용과
그외 생각나는 Tip과 경험담의 위주로 내용을 작성해나가려고 합니다.

실제로 하나의 완성된 검색엔진 개발 과정을 보여드리려고 했는데
내년 정도에 한번 진행을 해보게 될 것 같네요.

about Lucene 카테고리 외에 Lucene 카테고리에도 이미 경험했던 내용들에 대한
많은 내용들이 있으니 참고해주세요.
 
예제는
https://github.com/need4spd/aboutLucene
에서 받으 실 수 있습니다. 

CustomScoreQuery에 대한 예제 소스는
패키지 com.tistory.devyongsik.customscore 밑에 있습니다. 

저작자 표시 비영리 변경 금지
신고
Posted by 용식
예전에 1.4 버젼으로 개발 할 때는 Sort하는 방법을 하나밖에 몰랐습니다.

Sort 클래스를 이용하는 거였는데요

방법은 아래와 같습니다.

Sort sort = new Sort("TITLE", true);
TopFieldDocs tfd = searcher.search(query,null,50,sort);

물론 예전에는 Hits 객체에다가 바로 받아왔지만 현재는 Hits 는 deprecated 되었으므로
위와 같이 사용합니다.

그리고 지금은 하나의 방법을 더 알게 되었는데 그것이

SortField를 사용하는 방법입니다.

위의 예제를 SortField를 사용하는 방식으로

변경해보면

SortField sf = new SortField("TITLE",SortField.STRING,true);
Sort sort = new Sort(sf);
TopFieldDocs tfd = searcher.search(query,null,50,sort);

한줄이 더 들어갔는데요 SortField를 사용하는 방식은 아무튼 위와 같습니다.

그러면 저것이 무슨 이득이 있는가..? 하는건데요..

아파치에서 제공한 Solr이라는 검색서버를 보면 알 수 있습니다.

XML에 설정되어 있는 필드와 필드타입에 따라서 SortField를 자유자재로

설정하고 있습니다.

Solr에서 sort를 하기 위해서 요청하는 쿼리는

sort=title desc, score asc, name desc

이런식입니다. 제목역순, 점수순, 이름역순 이렇게 여러가지의 정렬 조건을 사용 할 수도 있습니다.

이것을 parsing하는 부분을 보면 이 SortField를 사용하고 있습니다.

xml에 설정된 필드 내용을 IndexSchema에 넣어놓고 여기서

SchemaField를 가져옵니다. 여기에는 필드명과 필드타입(String,Long..)이 설정되어

있겠죠.. 이정보만 가지고 유동적으로 SortField를 생성 할 수 있습니다.


점수순일 경우에는

SortField sf = SortField.SCORE_FIELD;


점수 역순 일 경우에는

SortField sf = new SortField(null, SortField.SCORE, false);


그 외에는

new SortField(FIELDNAME, SortField.SCORE, REVERSE)


를 사용하면 SortField를 생성 할 수 있습니다.


그 외 조건들은 SortField 클래스를 좀 더 살펴보면 자세히 알 수 있습니다.

그리고 1.4부터 있던 내용인데..

Sort를 하려는 필드는 NOT_ANALYZED 여야 합니다.

만약, Sort를 하려는 필드가 반드시 분석(ANALYZED 혹은 TOKENIZED) 되어야 한다면

필드를 두개 만들어야 합니다.

검색 할 때 사용 할 필드와 정렬 할 때 사용 할 필드...

document.add(new Field("TITLE", value, Field.Store.NO. Field.Index.ANALYZED)
document.add(new Field("TITLE_FOR_SORT", value, Field.Store.NO, Field.Index.NOT_ANALYZED)

이런식으로요...

분석된 필드를 sort하려고 하니

there are more terms than documents in field "name", but it's impossible to sort on tokenized fields

이런 exception이 발생하네요.

아마 저것이 위의 경우 말고도 하나의 document에 같은 필드를 여러개 추가하는 경우에도
발생하는 것으로 알고 있습니다.

document.add(new Field("TITLE_FOR_SORT", value, Field.Store.NO, Field.Index.NOT_ANALYZED)
document.add(new Field("TITLE_FOR_SORT", value2, Field.Store.NO, Field.Index.NOT_ANALYZED)

이런 경우죠...

sort에 대한 내용은

http://hudson.zones.apache.org/hudson/job/Lucene-trunk/javadoc/org/apache/lucene/search/Sort.html

여기서 참고하세요~
신고
Posted by 용식


티스토리 툴바