메뉴 건너뛰기

Bigdata, Semantic IoT, Hadoop, NoSQL

Bigdata, Hadoop ecosystem, Semantic IoT등의 프로젝트를 진행중에 습득한 내용을 정리하는 곳입니다.
필요한 분을 위해서 공개하고 있습니다. 문의사항은 gooper@gooper.com로 메일을 보내주세요.


solr solr설치및 적용관련

총관리자 2014.09.27 22:00 조회 수 : 2064

원본 : http://kevindoran1.blogspot.co.nz/2013/02/solr-tutorial.html codeflow

최근에 온라인 경매 관련 데이터를 검색해야 하는 일을 하게 되었습니다. eBay 와 비슷한 여러개의 온라인 경매 사이트의 데이터에 접근하게 되었습니다. 주어진 검색어로, 경매 아이템의 제목과 설명을 검색하여, 빠른 시간안에 검색이 되도록 하여야 했습니다. 오픈 소스 검색 엔진인 Solr 를 사용하기로 하였습니다. 이 글에서 Solr 를 셋업하는 과정과, 어려웠던 일들에 대해서 얘기하려고 합니다. 저는 Solr 4.1 을 사용하였습니다.

Solr 를 사용하기로 결정한 이유는, 경매 아이템을 빠르게 찾을 수 있고, 다양한 설정이 가능했기 때문입니다. 처음에는 MySQL 의 fulltext search 기능을 사용하였습니다. fulltext search 는 느리고, 변경이 어려우며, 숫자나 자주 쓰이는 단어등을 구별하지 못하는 문제가 있었습니다.


Overview of Solr Operation



Solr 기능 개요

Solr 는 Apache 같은 웹서버와 유사한 점이 많습니다: Solr 는 클라이언트의 요청을 처리하기 위해 설치 디렉토리에 있는 데이터를 이용합니다. 가장 큰 차이는, 웹 서버가 web page 를 리턴하는 반면에, Solr 는 XML , JSON 또는 다른 포맷의 검색 결과를 리턴한다는 것입니다. Solr 는 독립적입니다: Solr 디렉토리만 있으면 Solr 를 시작하고 이용할 수 있습니다. Java Servlet container 와 어플리케이션 데이터들이 디렉토리에 포함되어 있습니다. configuration 파일을 통하여 Solr 의 설정을 변경합니다. 4 개의 파일이 특히 중요한 역활을 합니다: solr.xml, solrconfig.xml, schema.xml,solr-data-config.xml [schema.xml 과 solr-data-config.xml 의 이름은 변경할 수 있습니다].


Starting Solr

Solr 를 기본 설정 상태로 시작하려면, 다음 디렉토리로 갑니다:
apache-solr-X.X.X/example/

그리고 다음처럼 실행합니다:

java -jar start.jar서버가 시작되고, Solr 가 기본 home directory 즉 ./solr 를 사용하게 됩니다.
새로운 Solr 인스턴스를 만드시려면, 기본 Solr 디렉토리를 카피하고, 이름을 변경합니다. 이 디렉토리가 새로운 Solr 인스턴스가 됩니다. 새로운 디렉토리의 이름을 AuctionSearch 라고 하였다면, 다음처럼 Solr 를 시작합니다:
java -jar start.jar -Dsolr.solr.home=AuctionSearch 이 명령을 실행하신 후에, http://localhost:8983/solr/ 에 있는 admin 페이지로 갑니다. 기본 Solr 인스턴스는 index 된 문서 (document) 가 하나도 없거나 하나정도 있거나 하기 때문에, 문서를 더 추가하기 전에는 별로 할 수 있는 일이 많지는 않습니다. 아마도, 문서를 추가하시기 전에 설정을 변경하시는 일이 필요할 것입니다.

Configuring Solr

Solr 를 설정하는 것이 보통 한번에 끝나는 일이 아닙니다 - 설정을 변경하고 테스팅하는 일을 반복하게 됩니다. Solr 를 처음 설정한 후 몇개월이 지난 후에도, Solr 에 대해 그리고 또 제가 사용하는 데이터에 대해 더 많이 알게 되면서, Solr 설정을 수정하게 됩니다. 보통은 이렇게 반복적으로 설정을 수정해야 되지만, 여기서는 선형의 (역주: 한번의) 설정 과정만을 보여드릴 겁니다. section 들을 왔다갔다 하면서 읽으셔도 좋습니다. 다음의 내용들을 다루려고 합니다:
  • solr.xml Solr cores
  • schema.xml Document structure
  • solrconfig.xml Request handlers

솔라를 설정할 때, 솔라 홈 디렉토리가 어떻게 생겼고, 설정 파일들이 어디에 있는지 알고 있으면 도움이 됩니다. 아래 이미지가 이 정보들을 보여줍니다.


Solr Cores

Solr core 는 단일 index 를 관리합니다. index 는 검색할 문서들에 대한 모든 정보들의 집합입니다. 하나의 index 는 하나의 document schema 와 연결됩니다 (즉 하나의 문서 포맷만 사용할 수 있습니다). 여러개의 core 를 사용하여, 하나의 Solr 인스턴스 (하나의 서버, 하나의 admin web 페이지) 가 여러개의 index 를 사용하도록 할 수 있습니다. 경매 사이트에서는, 경매 데이터를 index 하기 위해 하나의 core 를 사용하고, 유저 데이터를 위해 또 하나의 core 를 사용할 수 있습니다. 각각의 core 마다 core directory 를 갖게 됩니다. solr.xml 를 이용하여 core 들을 설정합니다. Solr.xml 은 다음 처럼 생겼습니다:


123456
<!-- persistent="true" allows the web interface to make lasting changes to Solr. -->
<solr persistent="true" sharedlib="lib">
<cores adminpath="/admin/cores" host="${host:}"hostcontext="${hostContext:}" hostport="${jetty.port:}"zkclienttimeout="${zkClientTimeout:15000}">
<core default="true" instancedir="auctions" name="auctions">
</core></cores>
</solr>
view rawsolr.xml hosted with ❤ by GitHub

기본 solr.xml 을 바로 사용할 수 있을 때도 많습니다. 코어 이름과 디렉토리 이름을 수정할 수 있습니다.Further detailssolr.xml 을 설정하는 방법이 나와 있습니다.

Schema

Solr schema 는 정보의 기본 단위 즉 document 를 기술합니다. 각각의 Solr core 는 하나의 schema 를 가지고 있고, 따라서 document 의 한 '형태' 만을 index 합니다. document 는 여러개의 field 로 구성됩니다. 각각의 필드는 type 이 있습니다. schema 에 이 타입들이 정의되어 있고, 이 타입들이, 필드가 index 될 때 어떤 Java 클래스가 사용될지를 결정하게 됩니다. 또한 필드가 인덱스 될 때, 어떤 text 분석 (processing/digestion) 을 하게 될지도, 이 타입이 결정하게 됩니다. 예제 문서와, schema.xml 에서 관련 부분이 다음처럼 생겼습니다:


123456789
<doc>
<field name="auction_id">54432834</field>
<field name="title">Dell M2012 24" IPS Monitor</field>
<field name="category">monitors</field>
<field name="current_bid">279.95</field>
<field name="end_date">2013-01-06T09:26:04.18Z</field>
<field name="feature">IPS</field>
<field name="feature">Swivel</field>
</doc>


1234567891011121314151617181920212223
<schema name="example" version="1.5">
<fields>
<field name="_version_" type="long" indexed="true" stored="true"required="true"/>
<field name="auction_id" type="string" indexed="true" stored="true"required="true" multiValued="false" />
<field name="title" type="text_en" indexed="true" stored="true"required="true" multiValued="false" />
<field name="category" type="string" indexed="true" stored="true"required="true" multiValued="false" />
<field name="current_bid" type="currency" indexed="true" stored="true"required="true" multiValued="false" />
<field name="end_date" type="date" indexed="true" stored="true"required="true" multiValued="false" />
<field name="feature" type="string" indexed="true" stored="true"required="false" multiValued="true" />
</fields>
<uniqueKey>auction_id</uniqueKey>
<types>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="date" class="solr.TrieDateField" precisionStep="0"positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0"positionIncrementGap="0"/>
<fieldType name="text_en" class="solr.TextField"positionIncrementGap="100">
<!-- lots of details -->
</fieldType>
<fieldType name="currency" class="solr.CurrencyField" precisionStep="8"defaultCurrency="USD" currencyConfig="currency.xml" />
</types>
</schema>
view rawschema.xml hosted with ❤ by GitHub

다음은 schema.xml 의 각 부분들에 대한 설명입니다.

Fields

필드는 document 내의 한가지 정보를 기술합니다. 필드는, 이 한가지 정보를 어떤 자바 타입을 이용하여 나타낼 것인지, 이 정보를 저장할 것인지, 이 정보가 모든 문서에 반드시 포함되어야 하는지등, index 할 때 영향을 미치게 됩니다. copyFielddynamicField 두개의 특별한 필드가 있습니다.

copyField
Copy field 를 이용하여, 하나의 필드를 여러가지 방법으로 index 할 수 있습니다. 예를들어, 어떤 한 정보를 index 할때, text_enstring 두개의 필드를 이용할 수 있습니다.
dynamicField
Dynamic field 는, 어떻게 보면, Copy Field 의 반대 개념입니다: 여러개의 필드를 동일하게 처리할 수 있게 해줍니다. 패턴으로 여러개의 document 필드들을 선택할 수 있다는 점이 가장 큰 강점입니다. dynamic field 를 이용하여 문서내에서 index 하지 말아야 할 모든 필드들을 선택할 수 있습니다. index 할 때, 문서의 모든 필드를 처리하지 않으면 에러가 발생하기 때문에, 이 기능으로 index 하지 않을 필드를 알려주는 것이 중요합니다.

아래는, copy 와 dynamic 필드를 사용하는 예제입니다:

1234567891011121314
<schema name="example" version="1.5">
<fields>
<field name="title" type="text_en" indexed="true" stored="true"required="true" multiValued="false" />
<field name="category" type="string" indexed="true" stored="true"required="true" multiValued="false" />
<field name="feature" type="string" indexed="true" stored="true"required="false" multiValued="true" />
<field name="allText" type="text_en" indexed="true" stored="false"required="true" multiValued="true" />
</fields>
<copyField source="title" dest="allText" />
<copyField source="category" dest="allText" />
<copyField source="feature" dest="allText" />
<dynamicField name="*" type="ignored" multiValued="true" />
</schema>
view rawschema.xml hosted with ❤ by GitHub

Analysers, Tokenisers and Filters

Analyser
analyzer 는 필드의 텍스트를 변경하여 index 할 형태로 만듭니다. analyzer 는 하나 이상의 tokenizer 와 filter 로 이루어 집니다. analzyer 는 filter 와 tokenizer 의 조합이며, 특정이름이 없습니다. analyzer 가 정의된 필드타입으로 구분하게 됩니다.
Tokenizer
tokenizer 는 텍스트를 token 이라고 단위로 쪼갭니다. 예를들어, "Please like my blog" 이란 텍스트는, tokenizer 에 의해 (Please, like, my, blog) 이라는 4 개의 token 으로 나뉘어 질 수 있고, 다른 종류의 tokenizer 에 의해 (p, l, e, a, s, e, l, i, k, e, m, y, b, l, o, g) 로 나뉘어질 수도 있습니다.
Filter
filter 는 token 을 받아서, 변형시키고, 변형한 token 을 리턴합니다. (token 을 변형할 수도 있고, 버릴 수도 있습니다) 예를들어, 어떤 필터는 텍스트를 모두 lowercase 로 변경합니다.

analyzer 는 index 할 때와 검색시에 모두 적용될 수 있습니다. 다시 말하면, index 할 문서를 변형하는데 사용할 수도 있고, 유저가 입력한 검색어를 변형하는데 사용할 수도 있습니다.

밑에 꽤나 복잡한 analyzer 의 예가 있습니다. example Solr schema.xml 에 text_en 이라는 fieldType 에 사용되도록 정의되어 있습니다.

123456789101112131415161718192021222324252627
<fieldType name="text_en" class="solr.TextField"positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory"protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory"protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
view rawschemaPart.xml hosted with ❤ by GitHub

Schema Snares

Multivalued Fields

Multivalued 란 문서에서 한 필드에 쓰일 값들이 두 개 이상일 수 있는 경우를 일컫습니다. 예를들면, 아래의 예제 문서에서는, 제목은 항상 하나만 존재합니다. feature 필드가 multivalued 필드 입니다. 문서에 여러개의 값들을 가진 것을 보실 수 있습니다. multivalued 필드를 이용하실 때 주의할 점은, 데이터가 합쳐진다는 것입니다. 예를들어, 경매 아이템이 2 가지 feature 를 가지고 있다면, 이 두 feature 는 합쳐져서, 어느 값이 어느 이름 feature 에 해당하는지 알 수 없게 됩니다.


12345678910111213141516171819202122232425262728
<!-- What an auction might look like in its original XML form: -->
<auction>
<title>Desktop PC</title>
<feature>
<name>RAM</name>
<value>16 GB</value>
</feature>
<feature>
<name>CPU Frequency</name>
<value>4.5 GHz</value>
</feature>
</auction>
<!-- What an auction would look like as a Solr document: -->
<doc>
<field name="title">Desktop PC</field>
<field name="feature_name">RAM</field>
<field name="feature_value">16 GB</field>
<field name="feature_name">CPU Frequency</field>
<field name="feature_value">4.5 GHz</field>
</doc>
<!-- The *effect* of multivalued field flattening: -->
<doc>
<field name="title">Desktop PC</field>
<field name="feature_name">RAM CPU Frequency</field>
<field name="feature_value">16 GB 4.5 GHz</field>
</doc>
view rawschemaPart.xml hosted with ❤ by GitHub

데이터가 index 되는 것을 보면 (역주: 위 예제에서 밑에 `<doc>` 부분을 보면 될듯) 이름과 값들이 어떻게 이어져 있었던 것인지 알 수 없게 됩니다. 다른 말로 하면, 일-대-다 관계는 Solr 에서 단일 index 로 표현할 수 없습니다. (여러개의 index 와 여러개의 core 를 이용하는 복잡한 방법이 있긴 합니다). 데이터베이스 관점에서 보자면, Solr 는 모든 데이터를 하나의 테이블로 합쳐버립니다.


PolyFields

Currency 같은 polyfield 는, index 시 두개 이상의 값이 동시에 저장되어야 하는 field 입니다. curreny field 를 저장하려면, 돈의 액수와 사용된 통화 두가지를 동시에 저장해야 합니다. polyfield 는 stored=true 값을 지정해야 하며, 그렇지 않으면 에러가 발생합니다.


solrconfig.xml

solrconfig.xml 로 Solr 의 많은 설정을 변경할 수 있습니다:
  • request handlers
  • listeners (listen for requests sent to handlers)
  • admin interface
  • replication and duplication
보통, search 나 index request handler 를 추가하거나 수정할 때 solrconfig.xml 를 수정하게 됩니다. 아래 Indexing 과 Searching 섹션에서 이 두가지 경우를 다룰 것입니다.

Indexing Data

문서를 index 에 추가할 때 저는 두가지 방법을 사용하였습니다: XML 데이터를 request handler 에게 HTTP post 로 전달하는 방법과 데이터베이스로부터 데이터를 가져오는 방법을 사용하였습니다. 처음에는 데이터베이스의 데이터들을 가져오는 작업을 합니다. 이 작업이 끝난 후에는, HTTP post 를 이용해 XML 형태로 문서를 Solr 에게 보내서 index 에 추가합니다.

Importing from a Database

Data Import Handler (DIH) 를 이용하여 데이터베이스에서 데이터를 가져올 수 있습니다. DIH 를 사용하려면, 설정 파일이 필요합니다. 또 solrconfig.xml 에 request handler 를 설정하여야 합니다. 위 링크에 설정파일을 작성하는 방법이 자세히 나와 있습니다.

Posting XML

전체 데이터베이스를 Solr 로 index 한 후에, 새로이 추가할 문서들은 Solr request handler 에게 POST 방식으로 전달됩니다. SolrJ, Solr 의 Java API 가 POST 하기 위해 사용됩니다. 문서를, XML 형태로 POST 전달하기 위해 간단한 request handler 가 제공됩니다. solrconfig.xml 에 다음처럼 정의되어 있습니다:


12
<!-- in solrconfig.xml -->
<requestHandler name="/update" class="solr.UpdateRequestHandler" />

따라서, XML 을 http://localhost:8983/solr/coreName/update 에게 보내면, Solr 가 이 문서를 index 에 추가할 것입니다. 하지만, 불행히도, index 하려는 데이터를 이미 XML 형태로 가지고 있다면, 아마도 Solr 에게 보내기 전에 포맷을 변경해야 할 것입니다. 다음 두 문서를 비교해 보세요:


123456789101112131415
<!-- original XML format: -->
<auction>
<auction_id>54432834</auction_id>
<title>Dell M2012 24" IPS Monitor</title>
<category>monitors</category>
<current_bid>279.95</current_bid>
</auction>
<!-- The format Solr requires: -->
<doc>
<field name="auction_id">54432834</field>
<field name="title">Dell M2012 24" IPS Monitor</field>
<field name="category">monitors</field>
<field name="current_bid">279.95</field>
</doc>
view rawcomparison.xml hosted with ❤ by GitHub

따라서, Solr 가 원하는 형태로 XML 을 변경할 필요가 있습니다. 이를 위해 두가지 방법이 사용됩니다:

  • In Java: JAXP API 를 사용할 수 있습니다. 이 방법을 사용하면, 문서 변환을 위해 직접 코드를 작성해야 합니다. 데이터가 Java 클래스로 존재한다면, SolrJ 를 이용하여 Java 객체를 바로 index 할 수도 있습니다.
  • Use XSLT: Solr request handler 를 수정하여, XML 문서를 받았을 때, XSLT 를 사용하여 포맷을 먼저 변경하고 index 하도록 할 수도 있습니다. XML 문서 (root 가 'Auction' 인) 를 변형하기 위한 XSLT 는 다음처럼 생겼습니다:


12345678910111213141516171819202122232425262728293031323334353637383940
<?xml version="1.0" encoding="UTF-8" ?>
<!-- the 2.0 version of xsl reqires a custom processor to be used. Saxon9he is used, and is
located in Jetty's ext/ folder. This library requires Jetty to be started like so:
java -Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -jar start.jar
-->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
xmlns:err="http://www.w3.org/2005/xqt-errors"
xmlns:tm="http://api.trademe.co.nz/v1"
exclude-result-prefixes="xs xdt err fn tm">
<xsl:output method="xml" indent="yes"/>
<!-- 'Auction" is the root XML element -->
<xsl:template match="tm:Auction">
<add><doc>
<xsl:for-each select="//text()/.. intersect child::*">
<field>
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:value-of select="."/>
</field>
</xsl:for-each>
<xsl:for-each select="//text()/.. except child::*">
<field>
<xsl:attribute name="name">
<xsl:value-of select="../name()"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:value-of select="."/>
</field>
</xsl:for-each>
</doc></add>
</xsl:template>
</xsl:stylesheet>
view rawxmlToSolrDoc.xml hosted with ❤ by GitHub


Indexing Snares

Letter Case in the DIH Configuration File

DIH 설정 파일에서 table 과 row 이름들의 대소문자를 조심해야 합니다. 어떤 경우에는 문제가 안되는 경우도 있고, 어떤 경우에는 문제가 되는 경우도 있습니다. 문제가 되는 경우에는, 데이터베이스에서 사용한 똑같이 대소문자를 맞춰주어야 합니다. 그리고 설정 파일내에서도 대소문자가 일치해야 합니다.

Posted XML 에 필드가 없는 것과, DIH 가 모든 것들을 Ignored Field 로 인식하는 문제

연관이 없을 것 같은 이 두가지가, schema.xml 의 dynamic field 로 인해 연관되어 있습니다. XML 데이터를 POST 할 때, schema 파일에 있는 모든 필드가 XML 에 존재해야 합니다. XML 문서에 있는 field 중에 index 시 사용되지 않는 필드가 있으면, POST 시 에러가 발생합니다. (역주: 바로 전 문장과 딴소리..) 이를 해결하기 위해서, 문서에서 필드로 매핑되지 않은 데이터들을 모두 흡수하는 필드를 schema 에 정의할 수 있습니다. 그런데 이 필드를 정의하면 DIH 를 사용하는데 어려움이 있습니다. DIH 가 거의 모든 데이터를 이 필드로 매핑하기 때문입니다.
DIH는 row 와 field 가 같은 이름을 가지고 있으면 row->field 매핑을 하지 않아도 되는 편리한 기능을 제공하는데, 이 기능때문에 생기는 문제인지도 모르겠습니다. row->field 매핑을 일일이 하지 않으면 DIH 가 모든 row 를 dynamic field 로 연결합니다. 현재 저는, DIH 를 통해 데이터를 가져와야 할 때에는 schema.xml 을 변경해 주는 작업을 해주고 있습니다.

Searching

검색 요청은 검색어를 parse 하고 process 하는 request handler 에 의해 처리 됩니다. search handler 를 설명하는 좋은 방법은 예제를 이용하는 것입니다. 다음 예제가, 제가 사용하는 search request handler 입니다:


1234567891011121314151617
<requestHandler name="/broadQuery" class="solr.SearchHandler">
<lst name="defaults">
<str name="defType">edismax</str> <!-- The search parser to use. -->
<str name="wt">xml</str> <!-- Output type. -->
<str name="fl">auction_id title</str> <!-- The fields to list in the search response -->
<str name="qf">Title^2 Feature</str> <!-- The fields (and their weightings) to search in.-->
<str name="rows">100</str> <!-- The number of results to return. -->
<str name="pf">Title^4 Feature^2</str> <!-- Phrase field (and their weightings). Fields to search for closely located matches. -->
<str name="ps">0</str> <!-- Phrase slop. How many tokens apart must words be to be able to qualify as a phrase-->
<str name="echoParams">all</str> <!-- Print the search settings in the search results. Just a handy feature -->
<str name="mm">3<-1 5<-2 6<-40%</str>
<!-- 3>-1 5>-2 6>-40% Means: If there are 1-3 search terms, they are all required to
<!-- match. If there are 4-5 search terms, then (all - 1) must match.
If there are 5-6 search terms, then (all -2) must match
If there are >6 search terms, then (all - 40%) must match. -->
</lst>
</requestHandler>

이들 인자들은 검색 시점에 지정할 수도 있습니다; request handler 정의에 설정하는 것은, 기본값을 주는 것이라고 보면 됩니다. 이 search handler 를 사용하려면 다음 주소처럼 사용하면 됩니다:


[Assuming that 'auctions' is the name of your Solr core, and Solr is hosted on localhost]

search handler 의 설정들 중에, 주석만으로 이해하기 어려운 defType, pf, ps, mm 에 대해서 추가 설명을 하고자 합니다:

defType
defType 은 어떤 search parser 를 이용할지 설정합니다. Standard Search, DisMaxeDisMax 등이 인기있는 search parser 들입니다. eDismax 는 Standard 와 DisMax 의 기능들을 합친 것입니다: eDismax 는 Lucene Standard Query 의 query 문법을 지원합니다. 그리고 문법 에러에 매우 수용적입니다. 대부분의 경우에 eDismax 를 쓰면 무방하다고 생각합니다.
pf
pf (phase fields) 는 'phrase` 를 검색하기 위해 어떤 필드를 사용하는지 결정합니다. matching 된 단어들이 서로 붙어 있다면, 그 단어들이 phrase 를 이룬다고 생각할 수 있습니다. phrase 로 검색된 결과들이 phrase 가 없는 결과들보다 높은 점수를 갖습니다. weighting 을 줄 수도 있습니다: match 를 찾았을 때 얼마나 중요하게 match 를 여길지 정할 수 있습니다. 예를들어, title 에서 찾은 phrase 가 feature 에서 찾은 phrase 보다 높은 점수를 받을 것입니다.
ps
ps (phrase slop) 는 두 단어 사이에 몇개의 상관없는 단어들이 끼어 있어도, phrase 로 여길지를 결정하게 됩니다.

Searching from Java

Java 에서 SolrJ 를 이용하여 search 를 할 수도 있습니다. 아래 gist 는 SolrJ 를 이용하는 간단한 예제를 보여줍니다:


1234567891011121314151617181920212223242526
public class SimpleSolrSearch {
private String solrUrl = "http://192.168.1.103:8983/solr/auctions";
private SolrServer server;
public SimpleSolrSearch() {
server = new HttpSolrServer(solrUrl);
}
public Collection<Integer> search(String searchTerms, String category,BigDecimal maxBidAmount) throws SolrServerException {
SolrQuery query = new SolrQuery();
String categoryFilter = "category:"" + category + """;
query.addFilterQuery(categoryFilter);
query.addFilterQuery("current_bid:[1 TO " + maxBidAmount.doubleValue() +"]");
query.setQuery(searchTerms);
QueryResponse response = server.query(query);
SolrDocumentList documentList = response.getResults();
List<Integer> auctionIds = new ArrayList<>();
for(SolrDocument doc : documentList) {
int listingId = Integer.parseInt((String)doc.getFirstValue("auction_id"));
auctionIds.add(listingId);
}
return auctionIds;
}
}
view rawSearch.java hosted with ❤ by GitHub


Further Reading

Solr 를 사용할 때 해야할 작업들을 간단히 살펴보았습니다. 훨씬 더 많은 기능들이 있습니다: search faceting, search clustering, distributed searches, index replication 등등 말이죠. 다양한 문서들중에 저는 다음 문서들을 추천합니다:

번호 제목 글쓴이 날짜 조회 수
124 Nodes of the cluster (unhealthy)중 1/1 log-dirs are bad: 오류 해결방법 총관리자 2015.05.17 558
123 secureCRT에서 backspace키가 작동하지 않는 경우 해결방법 총관리자 2015.05.11 555
122 hbase가 기동시키는 zookeeper에서 받아드리는 ip가 IPv6로 사용되는 경우가 있는데 이를 IPv4로 강제적용하는 방법 총관리자 2015.05.08 239
121 hbase CustomFilter만들기 (0.98.X이상) 총관리자 2015.05.08 152
120 znode /hbase recursive하게 지우기 총관리자 2015.05.06 644
119 java.lang.IllegalArgumentException: Does not contain a valid host:port authority: master 오류해결방법 총관리자 2015.05.06 386
118 hadoop 2.6.0 기동(에코시스템 포함)및 wordcount 어플리케이션을 이용한 테스트 총관리자 2015.05.05 3583
117 oozie 4.1 설치 - maven을 이용한 source compile on hadoop 2.5.2 with postgresql 9.3 총관리자 2015.04.30 838
116 hive 0.13.1 설치 + meta정보는 postgresql 9.3에 저장 총관리자 2015.04.30 206
115 HBase 0.98.12(1.2.5) for hadoop2 설치-5대에 완전분산모드 (HDFS HA상테) 총관리자 2015.04.29 929
114 Hadoop - 클러스터 세팅및 기동 총관리자 2015.04.28 414
113 zookeeper 3.4.6 설치(3대) 총관리자 2015.04.28 1111
112 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable원인 총관리자 2015.04.27 313
111 bananapi 5대(ubuntu계열 리눅스)에 yarn(hadoop 2.6.0)설치하기-ResourceManager HA/HDFS HA포함, JobHistory포함 총관리자 2015.04.24 14655
110 scan의 startrow, stoprow지정하는 방법 총관리자 2015.04.08 296
109 SASL configuration failed: javax.security.auth.login.LoginException: java.lang.NullPointerException 오류 해결방법 총관리자 2015.04.02 575
108 kafka의 re-balance를 이용하여 consumer를 multi thread로 돌려서 topic의 partitions을 활용 총관리자 2015.03.31 233
107 Using The ZooKeeper CLI에서 zkCli의 위치 총관리자 2014.11.02 826
106 [번역] solr 검색 엔진 튜토리얼 총관리자 2014.10.07 414
105 solr vs elasticsearch 비교2 총관리자 2014.09.29 1256

A personal place to organize information learned during the development of such Hadoop, Hive, Hbase, Semantic IoT, etc.
We are open to the required minutes. Please send inquiries to gooper@gooper.com.

위로