검색어 띄어쓰기에 따라 검색 결과가 달라질 수 있나요?

1,251 views
Skip to first unread message

Tae Woo Kim

unread,
Jul 29, 2014, 6:25:18 AM7/29/14
to eun...@googlegroups.com
안녕하세요..
제가 요즘 질문을 많이 드려서 죄송합니다.. ^^;;

은전한닢을 적용해서 검색 데모 페이지를 만들어서 테스트 해보고 있는데요.
테스트 하다가 이상한 점을 발견 했습니다.

[검색 필드]
<fieldType name="text_ko3" class="solr.TextField" positionIncrementGap="100">
      <analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
        <tokenizer class="org.bitbucket.eunjeon.mecab_ko_lucene_analyzer.StandardIndexTokenizerFactory" compoundNounMinLength="2" />
      </analyzer>
 <analyzer type="query">
<tokenizer class="org.bitbucket.eunjeon.mecab_ko_lucene_analyzer.StandardIndexTokenizerFactory" compoundNounMinLength="2" />
 </analyzer>
    </fieldType>

검색 대상은 모두 위에 정의된 text_ko3 필드타입을 적용했고요 ..
"강남빌라" 로 검색 했을 때는 5건이 검색 되는데 "강남 빌라"로 검색하면 80건이 검색 됩니다...
또 하나 예를 들자면 "호텔모텔로 검색 하면 0건이 검색 되고 "호텔 모텔"로 검색하면 18건이 나옵니다.
mm=100%로 줬기 때문에 색인 토큰이 모두 포함된 문서만 나오게 되어 있는데요..

형태소 분석에서는 각각 띄어쓰기를 하던 안하던 "강남", "빌라", "호텔", "모텔" 로 분석이 되는데 검색 된 건수가 
이렇게 달라지는 이유는 왜 그런것인지 모르겠습니다.

의견 부탁 드립니다..

(혹시 더 필요한 정보가 있으시면 말씀주세요)

유영호

unread,
Jul 29, 2014, 9:10:07 PM7/29/14
to eun...@googlegroups.com
"강남빌라"로 검색 했을 때보다 "강남 빌라"로 검색했을 때 결과로 더 나오는 애들은 어떤 애들인가요?
Message has been deleted

Tae Woo Kim

unread,
Jul 29, 2014, 11:00:16 PM7/29/14
to eun...@googlegroups.com
글 수정 기능이 없네요 -_-;;
디버깅 정보 추가해서 다시 올려요.
쿼리 디버깅에서 뭔가 다르긴 한데 어떻게 작용하는지 잘 모르겠네요..

아래는 "강남빌라"로 검색 했을 때 검색이 안되다가 "강남 빌라"로 검색했을 때 결과로 나오는 데이터 입니다.
필드가 더 있지만 검색어가 등장한 주요 필드만 추렸습니다.

[데이터-1]
TITLE: "구포 강남그린빌라 82㎡ 매1억1300만 올수리 밝고깨끗"
AREANM: "부산 북구 구포동"
EX_CONTENTS: "★ 구포동 강남그린빌라 ★

[데이터-2]
TITLE: "원룸/투룸39㎡ 월세1000만/38만 "
AREANM: "서울 강남구 개포동",
EX_CONTENTS: "공간넓은 원룸 깨끗하고 조용한 관리잘된 빌라 원룸 입주 하시 가능함",

[쿼리 디거깅 정보]
혹시 참고가 되실지 해서 쿼리 디버깅 정보도 포함합니다.

[강남빌라]
debug: {
rawquerystring: "_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
querystring: "_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
parsedquery: "(+DisjunctionMaxQuery((FINDCODENAME:"강남 빌라" | EX_CONTENTS:"강남 빌라" | AREANM:"강남 빌라" | CONTENTS:"강남 빌라" | TITLE:"강남 빌라")) DisjunctionMaxQuery((FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)))/no_coord",
parsedquery_toString: "+(FINDCODENAME:"강남 빌라" | EX_CONTENTS:"강남 빌라" | AREANM:"강남 빌라" | CONTENTS:"강남 빌라" | TITLE:"강남 빌라") (FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)",


[강남 빌라]
debug: {
rawquerystring: "_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
querystring: "_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
parsedquery: "(+((DisjunctionMaxQuery((FINDCODENAME:강남 | EX_CONTENTS:강남 | AREANM:강남 | CONTENTS:강남 | TITLE:강남)) DisjunctionMaxQuery((FINDCODENAME:빌라 | EX_CONTENTS:빌라 | AREANM:빌라 | CONTENTS:빌라 | TITLE:빌라)))~2) DisjunctionMaxQuery((FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)))/no_coord",
parsedquery_toString: "+(((FINDCODENAME:강남 | EX_CONTENTS:강남 | AREANM:강남 | CONTENTS:강남 | TITLE:강남) (FINDCODENAME:빌라 | EX_CONTENTS:빌라 | AREANM:빌라 | CONTENTS:빌라 | TITLE:빌라))~2) (FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)",

유영호

unread,
Jul 30, 2014, 12:03:47 AM7/30/14
to eun...@googlegroups.com
일단 현상적으로는..
"강남 빌라" 일때는 다른 필드에 걸쳐서 검색이 된 놈이 나왔네요. 그러니까, "AREANM:강남", "EX_CONTENTS:빌라". 그러나 "강남빌라"일때는 한 필드에 "강남"과 "빌라"가 모두 있어야 나온거구요.

[강남빌라]
+(FINDCODENAME:"강남 빌라" | EX_CONTENTS:"강남 빌라" | AREANM:"강남 빌라" | CONTENTS:"강남 빌라" | TITLE:"강남 빌라") 
(FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)

[강남 빌라]
+(
(
(FINDCODENAME:강남 | EX_CONTENTS:강남 | AREANM:강남 | CONTENTS:강남 | TITLE:강남) 
(FINDCODENAME:빌라 | EX_CONTENTS:빌라 | AREANM:빌라 | CONTENTS:빌라 | TITLE:빌라)
)~2
(FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)

원하는 해결책이 될지 모르겠는데, 이용운님이 쓰신 글을 한번 보시겠어요?


Yong-woon Lee

unread,
Jul 30, 2014, 12:56:53 AM7/30/14
to eun...@googlegroups.com
경험상 dismax와 edismax가 동작하는 방식이 다르더라구요. 혹시 edismax로 바꿔서 한 번 테스트하실 수 있으신가요?

Tae Woo Kim

unread,
Jul 30, 2014, 4:01:46 AM7/30/14
to eun...@googlegroups.com

edismax도 dismax와 비슷하게 질의가 처리 되는 것 같습니다..
검색 결과도 같네요.

[강남빌라]

debug: {

rawquerystring: "_query_:"{!edismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",

querystring: "_query_:"{!edismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",

parsedquery: "(+DisjunctionMaxQuery((FINDCODENAME:"강남 빌라" | EX_CONTENTS:"강남 빌라" | AREANM:"강남 빌라" | CONTENTS:"강남 빌라" | TITLE:"강남 빌라")) DisjunctionMaxQuery((TITLE:"강남 빌라"^500.0)) DisjunctionMaxQuery((EX_CONTENTS:"강남 빌라"^50.0)) DisjunctionMaxQuery((CONTENTS:"강남 빌라"^50.0)) DisjunctionMaxQuery((AREANM:"강남 빌라"^100.0)) DisjunctionMaxQuery((FINDCODENAME:"강남 빌라"^50.0)))/no_coord",

parsedquery_toString: "+(FINDCODENAME:"강남 빌라" | EX_CONTENTS:"강남 빌라" | AREANM:"강남 빌라" | CONTENTS:"강남 빌라" | TITLE:"강남 빌라") (TITLE:"강남 빌라"^500.0) (EX_CONTENTS:"강남 빌라"^50.0) (CONTENTS:"강남 빌라"^50.0) (AREANM:"강남 빌라"^100.0) (FINDCODENAME:"강남 빌라"^50.0)",


[강남 빌라]

debug: {

rawquerystring: "_query_:"{!edismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",

querystring: "_query_:"{!edismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",

parsedquery: "(+((DisjunctionMaxQuery((FINDCODENAME:강남 | EX_CONTENTS:강남 | AREANM:강남 | CONTENTS:강남 | TITLE:강남)) DisjunctionMaxQuery((FINDCODENAME:빌라 | EX_CONTENTS:빌라 | AREANM:빌라 | CONTENTS:빌라 | TITLE:빌라)))~2) DisjunctionMaxQuery((TITLE:"강남 빌라"^500.0)) DisjunctionMaxQuery((EX_CONTENTS:"강남 빌라"^50.0)) DisjunctionMaxQuery((CONTENTS:"강남 빌라"^50.0)) DisjunctionMaxQuery((AREANM:"강남 빌라"^100.0)) DisjunctionMaxQuery((FINDCODENAME:"강남 빌라"^50.0)))/no_coord",

parsedquery_toString: "+(((FINDCODENAME:강남 | EX_CONTENTS:강남 | AREANM:강남 | CONTENTS:강남 | TITLE:강남) (FINDCODENAME:빌라 | EX_CONTENTS:빌라 | AREANM:빌라 | CONTENTS:빌라 | TITLE:빌라))~2) (TITLE:"강남 빌라"^500.0) (EX_CONTENTS:"강남 빌라"^50.0) (CONTENTS:"강남 빌라"^50.0) (AREANM:"강남 빌라"^100.0) (FINDCODENAME:"강남 빌라"^50.0)",



유영호님이 주신 글은 보긴 봤는데 비슷한 문제지만 문제를 해결할 수 있는 답이 됐다고 보기에는 부족한 것 같고용...ㅠ_ㅠ


그냥 단순히 생각해보면...
한 필드에서 검색이 모두 되야 되는 것이면 색인 사이즈는 좀 커지겠지만 한필드에 검색 대상 데이터를 몰아넣고 색인을 하면 되긴 할 것 같네요..
대신.. 필드별 가중치라던지 정렬 순서에 영향을 미칠 수 있을 것 같아 완벽한 해결책이라고 볼수 있을 지는 잘 모르겠습니다...

사전만 잘 구축하면 될 줄 알았더니...이제 보니 dismax 질의 구문 분석기가 검색 결과에 많은 영향을 미치네요.. 
가급적 사용자가 입력한 검색어를 그대로 사용해서 dismax나 edismax로 커버하려고 했는데... 별도의 전처리가 필요한 건가요...

따로 뭔가 전처리를 해준다고 해도 "강남빌라"는 형태소로 분석되는 토큰이 붙어 있는 형태라서 분리하는 기준도 모호하고..
워낙 검색어 케이스가 많아서 손도 많이 가고 만족할 만한 결과가 나올지 잘 모르겠습니다.
문득 띄어쓰기 없는 일본어는 어떻게 검색 되는지 모르겠네요.ㅎㅎ;

구글도 "강남빌라"랑 "강남 빌라" 검색 결과 건수가 다르긴한데.. (예상과 다르게 "강남빌라"가 검색 건수가 더 많군요)


[질문-1]
이 경우 필드 하나에 데이터를 몰아 넣는 것 외에 다른 해결 방법은 없을 까요? (필드별 가중치, 정렬을 고려)
띄어쓰기 하나 때문에 필드별 검색 방법이 바뀌다니... 당황스럽네요..


질문을 하나 더 쓸려고 했는데... 
일단.. 좀 더 개인적으로 검토해보고 질문 드리겠습니다...







Yong-woon Lee

unread,
Jul 31, 2014, 3:02:29 AM7/31/14
to eun...@googlegroups.com
TITLE, CONTENTS, EX_CONTENTS 필드가 있고, 순서대로 가중치가 높다면 다음과 같이 하실 수도 있습니다.

1. 세 필드의 내용이 합쳐진, COMBINE_TITLE_CONTENTS라는 필드를 생성
2. 다음과 같이 쿼리
TITLE="강남빌라"~100^10.0 OR CONTENTS="강남빌라"~100^5.0 OR EX_CONTENTS="강남빌라"~100^3.0 OR COMBINE_TITLE_CONTENTS="강남빌라"~100
Solr/Lucene에서 score는 각 필드에서의 hit값이 합산되는 방식이므로, 위의 식으로도 필드별 가중치가 적용됩니다.

Tae Woo Kim

unread,
Jul 31, 2014, 10:50:43 PM7/31/14
to eun...@googlegroups.com
답변 감사합니다..

그런데 최초 질문에서 검색이 안됐던 원인을 정확하게 파악하지 못했던 것 같습니다. ㅠ_ㅠ
제가 통합 필드를 만들어서 데이터를 몰아넣고 검색 대상으로 잡고 해도 검색이 안됩니다.

[적용한 필드타입]
<fieldType name="text_ko3" class="solr.TextField" positionIncrementGap="100" >
      <analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>
        <tokenizer class="org.bitbucket.eunjeon.mecab_ko_lucene_analyzer.StandardIndexTokenizerFactory" compoundNounMinLength="2" />
      </analyzer>
 <analyzer type="query">
<tokenizer class="org.bitbucket.eunjeon.mecab_ko_lucene_analyzer.StandardIndexTokenizerFactory" compoundNounMinLength="2" />
 </analyzer>
    </fieldType>

<강남빌라>
debug
{
  • parsedquery_toString"+(FINDCODENAME:"강남 빌라"^50.0 | TOTAL_CONTENT:"강남 빌라" | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0) (FINDCODENAME:"강남 빌라"^50.0 | TOTAL_CONTENT:"강남 빌라" | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)",

<강남 빌라>
debug
{
  • parsedquery_toString"+(((FINDCODENAME:강남^50.0 | TOTAL_CONTENT:강남 | EX_CONTENTS:강남^50.0 | AREANM:강남^100.0 | CONTENTS:강남^50.0 | TITLE:강남^500.0) (FINDCODENAME:빌라^50.0 | TOTAL_CONTENT:빌라 | EX_CONTENTS:빌라^50.0 | AREANM:빌라^100.0 | CONTENTS:빌라^50.0 | TITLE:빌라^500.0))~2) (FINDCODENAME:"강남 빌라"^50.0 | TOTAL_CONTENT:"강남 빌라" | EX_CONTENTS:"강남 빌라"^50.0 | AREANM:"강남 빌라"^100.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)",


"강남빌라"일 때는 검색이 안되고 "강남 빌라" 일 때 검색이 되는 데이터는 이미 하나의 필드에 "강남"과 "빌라"를 모두 포함한 TITLE과 EX_CONTENTS을 가지고 있었습니다. 

[데이터-1]
TITLE: "구포 강남그린빌라 82㎡ 매1억1300만 올수리 밝고깨끗"
AREANM: "부산 북구 구포동"
EX_CONTENTS: "★ 구포동 강남그린빌라

즉 "강남빌라"가 검색어 일 경우 하나의 필드에 검색어 토큰이 모두 출현한 데이터만 검색이 되었던게 아니라 다른 원인이 있었던 것 같습니다.

"강남빌라"로 검색 했을 경우 나오는 문서는 그야말로 "강남빌라"가 붙어있는 데이터만 나옵니다.
평거강남빌라 86㎡ 10호광장 주변 4층 인테리어완전됨 매9200만원 [누리공인중개사 경남 진주 김경란] 

그리고 autoGeneratePhraseQueries도 확인해서 옵션을 제거하고 다시 색인을 돌려도 똑같습니다..

dismax의 쿼리를 보면 형태가 다르긴 다르지만 빌드별로 or 조건이고 TITLE:"강남 빌라"^500.0 라고 하더라도 형태소 분석에 의해서 토큰이 분리되어 검색이 되어야 되는데 뭐가 원인인지 파악하기 어렵네요;

apache solr는 원래 이렇다라고 인정하고 사용자에게 띄어쓰기를 잘 해라 라고 해야 되는건지 다른 해결책이 있는지 고민이 필요해 보입니다...

Yong-woon Lee

unread,
Jul 31, 2014, 11:38:38 PM7/31/14
to eun...@googlegroups.com
원쿼리를 보여주시면 좋겠습니다. 아무래도 phrase query를 사용하고 계신듯합니다. phrase query는 말씀해주신대로 token이 붙어있는 것만 검색하게 됩니다. 혹시 q="강남빌라" 이런식으로 입력하고 계신 것 아닌가요?

Tae Woo Kim

unread,
Aug 1, 2014, 1:12:48 AM8/1/14
to eun...@googlegroups.com
용운님 답변을 보고 제가 놓치고 있는 부분이 있는 것 같아서 처음부터 하나하나 확인 해보니..
autoGeneratePhraseQueries 옵션을 제가 기본값이 false라고 생각하고 옵션을 삭제하고 색인을 돌렸었는데
기본값이 true인건지.. autoGeneratePhraseQueries="false"로 줘서 돌리니 검색이 되긴 합니다.... oTL
그런데... 이번에는 반대로 "강남빌라"일 때는 8675건이 검색 되고 "강남 빌라" 일때 72건이 검색 됩니다....

아래는 쿼리 정보 입니다.

[requestHandler]
<requestHandler name="/paper_new_search" class="solr.StandardRequestHandler">
    <lst name="defaults">
 <str name="q">_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"</str>
 <str name="qfQuery">TITLE^500 EX_CONTENTS^50 CONTENTS^50 AREANM^100 FINDCODENAME^50</str>
 <str name="pfQuery">TITLE^500 EX_CONTENTS^50 CONTENTS^50 AREANM^100 FINDCODENAME^50</str>
 <str name="df">TITLE, EX_CONTENTS, CONTENTS, AREANM, FINDCODENAME</str>
         <str name="hl">true</str>
         <str name="hl.fl">TITLE</str> 
 <str name="hl.simple.pre"><![CDATA[<b>]]></str>
         <str name="hl.simple.post"><![CDATA[</b>]]></str>
 <str name="hl.tag.pre"><![CDATA[<b>]]></str> 
         <str name="hl.tag.post"><![CDATA[<b>]]></str>     
 <str name="f.TITLE.hl.fragsize">5000</str>
<str name="f.EX_CONTENTS.hl.fragsize">5000</str>
    </lst>    
</requestHandler>

[강남빌라] - 8675건
mainQuery에 감남빌라가 들어갑니다.

debug
{
  • rawquerystring"_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
  • querystring"_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
  • parsedquery"(+((DisjunctionMaxQuery((FINDCODENAME:강남^50.0 | EX_CONTENTS:강남^50.0 | AD_OWNER:강남^100.0 | AREANM:강남^50.0 | CONTENTS:강남^50.0 | TITLE:강남^500.0)) DisjunctionMaxQuery((FINDCODENAME:빌라^50.0 | EX_CONTENTS:빌라^50.0 | AD_OWNER:빌라^100.0 | AREANM:빌라^50.0 | CONTENTS:빌라^50.0 | TITLE:빌라^500.0)))~2) DisjunctionMaxQuery((FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AD_OWNER:"강남 빌라"^100.0 | AREANM:"강남 빌라"^50.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)))/no_coord",
  • parsedquery_toString"+(((FINDCODENAME:강남^50.0 | EX_CONTENTS:강남^50.0 | AD_OWNER:강남^100.0 | AREANM:강남^50.0 | CONTENTS:강남^50.0 | TITLE:강남^500.0) (FINDCODENAME:빌라^50.0 | EX_CONTENTS:빌라^50.0 | AD_OWNER:빌라^100.0 | AREANM:빌라^50.0 | CONTENTS:빌라^50.0 | TITLE:빌라^500.0))~2) (FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AD_OWNER:"강남 빌라"^100.0 | AREANM:"강남 빌라"^50.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)",

[강남 빌라] - 72건

debug
{
  • rawquerystring"_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
  • querystring"_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"",
  • parsedquery"(+((DisjunctionMaxQuery((FINDCODENAME:강남^50.0 | EX_CONTENTS:강남^50.0 | AD_OWNER:강남^100.0 | AREANM:강남^50.0 | CONTENTS:강남^50.0 | TITLE:강남^500.0)) DisjunctionMaxQuery((FINDCODENAME:빌라^50.0 | EX_CONTENTS:빌라^50.0 | AD_OWNER:빌라^100.0 | AREANM:빌라^50.0 | CONTENTS:빌라^50.0 | TITLE:빌라^500.0)))~2) DisjunctionMaxQuery((FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AD_OWNER:"강남 빌라"^100.0 | AREANM:"강남 빌라"^50.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)))/no_coord",
  • parsedquery_toString"+(((FINDCODENAME:강남^50.0 | EX_CONTENTS:강남^50.0 | AD_OWNER:강남^100.0 | AREANM:강남^50.0 | CONTENTS:강남^50.0 | TITLE:강남^500.0) (FINDCODENAME:빌라^50.0 | EX_CONTENTS:빌라^50.0 | AD_OWNER:빌라^100.0 | AREANM:빌라^50.0 | CONTENTS:빌라^50.0 | TITLE:빌라^500.0))~2) (FINDCODENAME:"강남 빌라"^50.0 | EX_CONTENTS:"강남 빌라"^50.0 | AD_OWNER:"강남 빌라"^100.0 | AREANM:"강남 빌라"^50.0 | CONTENTS:"강남 빌라"^50.0 | TITLE:"강남 빌라"^500.0)",


디버그 쿼리 자체는 차이가 없는 것 같습니다.
그런데 autoGeneratePhraseQueries="false"로 주니 오히려 "강남빌라"가 더 많이 검색 되며 건수 차이가 많이 납니다...
oTL 




Tae Woo Kim

unread,
Aug 1, 2014, 3:16:19 AM8/1/14
to eun...@googlegroups.com
아... 이번에 테스트 해보고 딜레마에 빠졌습니다.. oTL


제가 원하는 검색은 !!!!
검색어에서 추출된 형태소 토큰들이 검색 되는데... 검색 대상으로 설정된 필드들에서 검색어에서 분리된 토큰들이 모두 등장하는 데이터를 검색 하도록 하고 싶습니다.
그리고 정렬을 기준으로 봤을 때는 모든 토큰들이 등장하는 데이터 중에서도 가급적 검색어와 근접한 문서를 위에 올리고 싶습니다.

그런데 용운님과 질문게시판에서 질문, 답변을 주고 받으며 보니...
autoGeneratePhraseQueries는 정렬 측면에서 정확도를 높이는 것이 아니라 인접한 토큰의 거리에 따라 검색이 되냐 안되는냐를 판단하는 옵션이기 때문에 ...  
모든 토큰이 등장하더라도 토큰 거리에 따라 검색이 아예 안되기 때문에 제가 원하는 검색이 아닙니다...

그래서 autoGeneratePhraseQueries="false"로 하고 
dismax에서 띄어쓰기를 안하면 mm=100%인데도 검색어에서 추출된 형태소 토큰들이 하나라도 매칭 되는 경우 데이터가 전부 나오게 되더군요...

예를들어 지하철역 필드만 검색 대상으로 잡고 보더라도..
"압구정로데오역"을 검색하면 압구정+로데오+역 으로 분석 되고 분석 된 토큰들 중에서 하나라도 일치하는 문서가 있으면 전부 가져옵니다..
"신림역"도 "역"이 포함되어 있어서 검색 됩니다...

(+DisjunctionMaxQuery(((AREANM:압구정 AREANM:로데오 AREANM:역) | (SUBWAYNAME:압구정 SUBWAYNAME:로데오 SUBWAYNAME:역))) DisjunctionMaxQuery((AREANM:"압구정 로데오 역"^10.0 | SUBWAYNAME:"압구정 로데오 역"^10.0)))/no_coord

그런데 띄어쓰기 해서 "압구정 로데오 역"을 검색하면 아래와 같이 되서

(+((DisjunctionMaxQuery((AREANM:압구정 | SUBWAYNAME:압구정)) DisjunctionMaxQuery((AREANM:로데오 | SUBWAYNAME:로데오)) DisjunctionMaxQuery((AREANM:역 | SUBWAYNAME:역)))~3) DisjunctionMaxQuery((AREANM:"압구정 로데오 역"^10.0 | SUBWAYNAME:"압구정 로데오 역"^10.0)))/no_coord

..."압구정" "로데오" "역" 각 토큰이 모두 포함된 데이터만 검색이 됩니다. 이게 제가 원하는 검색이죠.
비록 한필드만 대상으로 해서 여러 필드일 때 어떻게 작용할지 모르겠지만... 일단 한개 필드만 대상으로 했을 때도 이렇습니다..

쿼리는 mm=100% 인데... 왜 이렇게 결과가 나오는지 모르겠습니다.
형태소별로 AND 검색이 되어야 되는데 뭔가 옵션을 바꿔줘야 하나 해서 
<solrQueryParser defaultOperator="AND"/>이것도 해보고 q.op=AND도 줘봤습니다... 
그런데도 결과는 똑같습니다..


조언을 부탁드립니다.... oTL


Yong-woon Lee

unread,
Aug 1, 2014, 3:31:27 AM8/1/14
to eun...@googlegroups.com
저도 DisMax를 사용한 경험이 거의 없고, 관련 지식도 많이 없어서 더 도움을 드리긴 힘들것 같습니다. 꼭 DisMax를 사용해야하는 이유가 있으신가요?
말씀하신 정도면 제가 위에서 설명한 lucene query parser를 사용하는 방법도 괜찮을 것으로 보입니다.

Tae Woo Kim

unread,
Aug 1, 2014, 3:53:54 AM8/1/14
to eun...@googlegroups.com
꼭 dismax를 써야되는건 아닙니다.
제가 원하는 범주의 검색 방법이면 lucene query parser를 사용해도 상관 없습니다.

저는 "아파치 Solr 4 구축과 관리" 라는 책을 보고 solr wiki를 보면서 필요한 내용을 보충하고 있는 중인데요...
물론 은전한닢 질문게시판에서도 많은 도움을 받았습니다.
책에 "단어 거리가 가까운 문서 우선 반환" 이라는 내용을 보면 dismax 쿼리에 bq(boostQuery)를 사용해서 처리하고 있더군요..
그래서 검토하기 시작했고 검색어를 알아서 분석해서 적절하게 검색 쿼리를 만들어주는 것이 매력적이여서 쓴 것인데 
이번에 이런 문제가 생겨서.. 처음부터 다시 생각을 해봐야 할 것 같습니다.

lucene query parser 
처음에 접했을 때 검색 대상이 되는 필드에 각 키워드들을 일일이 토큰을 분리해서 쿼리를 만들어야 
내가 원하는 검색을 할 수 있는 것인가 생각하고 복잡해 보여서... dismax만 사용했습니다.

이용운님이 dismax를 거의 안쓰시고 lucene query parser를 쓰셨다고하니 제가 잘못 생각한 것일 수도 있겠구나 싶네요..

그렇다면.. 아래와 같은 쿼리를 lucene query parser로 짰을 때 검색어의 띄어쓰기 혹은 사용자가 자연어 식으로 검색을 할 때
사용자가 입력한 검색어를 다른 전처리 없이 그대로 가지고 모든 토큰이 등장하면서 비교적 거리가 가까운 문서를 위로 올리는 검색 쿼리를 만들 수 있나요???

<requestHandler name="/paper_new_search" class="solr.StandardRequestHandler">
    <lst name="defaults">
 <str name="q">_query_:"{!dismax qf=$qfQuery mm=100% pf=$pfQuery v=$mainQuery}"</str>
 <str name="qfQuery">TITLE^500 EX_CONTENTS^50 CONTENTS^50 AREANM^100 FINDCODENAME^50</str>
 <str name="pfQuery">TITLE^500 EX_CONTENTS^50 CONTENTS^50 AREANM^100 FINDCODENAME^50</str>
 <str name="df">TITLE, EX_CONTENTS, CONTENTS, AREANM, FINDCODENAME</str>
         <str name="hl">true</str>
         <str name="hl.fl">TITLE</str> 
 <str name="hl.simple.pre"><![CDATA[<b>]]></str>
         <str name="hl.simple.post"><![CDATA[</b>]]></str>
 <str name="hl.tag.pre"><![CDATA[<b>]]></str> 
         <str name="hl.tag.post"><![CDATA[<b>]]></str>     
 <str name="f.TITLE.hl.fragsize">5000</str>
 <str name="f.EX_CONTENTS.hl.fragsize">5000</str>
    </lst>    
</requestHandler>

아니라면 어느정도 기능을 절충해서 요정도 까지 가능한지라도 알고 싶습니다...
너무 질문을 많이 드려서 죄송합니다. 
제가 설정한 solr가 곧 서비스로 반영되야 되서 마음이 급하네요... oTL

Yong-woon Lee

unread,
Aug 1, 2014, 4:06:18 AM8/1/14
to eun...@googlegroups.com
네 가능합니다 위에서 보시면 "강남 빌라"~100 이런게 볼 수 있는데, 이것이 근접 검색 기능을 합니다. 정확히는 100단어 내에 위치하는 것을 찾는 것이고 기본적으로 더 가까운 문서가 더 높은 점수를 받습니다.

다만 mm=70%와 같은 것을 할 수 없다는 것이 문제인데... 일단은 100%만 이라면 solr query를 사용하시고 추후에 DisMax query를 좀 더 살펴보시는 것이 좋을 것으로 보입니다. URL이 좀 길어지긴 하는데 생각보다 딱히 복잡할 것은 없습니다. :)

Tae Woo Kim

unread,
Aug 1, 2014, 4:51:03 AM8/1/14
to eun...@googlegroups.com
답변 감사합니다. ^^

오늘부터 말씀해주신 solr query를 테스트 해보겠습니다!
dismax 문제는 나중에라도 해결되면 게시판에 공유해 보겠습니다.

감사합니다~~~


Reply all
Reply to author
Forward
0 new messages