프로그래밍 2015. 6. 12. 22:57

맥 뉴비인 나는.. java 버전 교체를 위해 30여분간의 삽질 후 이 글을 쓴다.

리눅스 비스무리 하기 때문에 대충 환경변수를 바꾸면 될거 같음을 예상한다. 하지만 java 실행 바이너리 위치를 모른다.


결론:

java_home 위치  = /Library/Java/JavaVirtualMachines 

해당 디렉토리 밑에 버젼 별로 설치되게 된다. 해당 버전의 home 디렉토리를 ~/.bash_profile에 등록하면 된다.


example)

vi ~/.bash_profile 

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home

위 문장 입력 후 저장 나가기

source ~/.bash_profile 


java -version 으로 확인하면 확인가능하다.


//
프로그래밍/ElasticSearch 2015. 5. 28. 14:33
Elasticsearch에서는 기본 analyzer 이외에도 따로 analyzer를 만들어서 쓸 수 있다. 
따로 custom analyzer 만들어야 할 일이 생겨 그 과정을 남기고자 한다.

1. 환경 : java, elasticsearch-1.4.6, maven
analyzer 의 구성에는 루씬에서 작동을 따르므로, filter, analyzer, tokenizer 를 각 구현해줘야한다.
밑에 클래스가 index setting 에 적용되어 filter, analyzer, tokenizer를 플러그인에 바인딩한다.
그리고 해당되는 클래스 네임으로 각각 구현해주면 된다.

public class TestAnalysisBinderProcessor extends AnalysisModule.AnalysisBinderProcessor {
    @Overrid
    public void processAnalyzers(AnalyzersBindings analyzersBindings) {
        analyzersBindings.processAnalyzer("test_analyzer", TestAnalyzerProvider.class);
    }

   @Override
    public void processTokenizers(TokenizersBindings tokenizersBindings) {
        tokenizersBindings.processTokenizer("test_tokenizer", TestTokenizerFactory.class);
    }

    @Override
    public void processTokenFilters(TokenFiltersBindings tokenFiltersBindings) {
        tokenFiltersBindings.processTokenFilter("test_filter", TestTokenFilterFactory.class);
    }
}
TestAnalyzerProvider 클래스 구현. AbstractIndexAnalyzerProvider를 상속하고 메인 analyzer클래스를 선언한다.
public class TestAnalyzerProvider extends AbstractIndexAnalyzerProvider {
    private final TestAnalyzer analyzer;
    @Inject
    public TestAnalyzerProvider(Index index, @IndexSettings Settings indexSettings, Environment env, @Assisted String name, @Assisted Settings settings) throws IOException {
        super(index, indexSettings, name, settings);
        analyzer = new TestAnalyzer(version);
    
    @Override
    public TestAnalyzer get() {
        return this.analyzer;
    }
}
filterfactory 클래스를 만들어 custom filter를 선언한다.
public class TestFilterFactory extends AbstractTokenFilterFactory {
    @Inject
    public TestFilterFactory(Index index, @IndexSettings Settings indexSettings, @Assisted String name, @Assisted Settings settings) {
        super(index, indexSettings, name, settings);
    }
    @Override
    public TokenStream create(TokenStream tokenStream) {
        return new TestFilter(tokenStream);
    }
}
custom_tokenizer를 선언하는 클래스를 만든다. 잠깐 설명하자면 루씬에서 tokenizer로 분리되어 나오는 것은 TestTokenizer에 incrementToken() 을 오버라이드 구현해서 token을 만들어 그 후 지정된 filter들이 또 다시 increamentToken 함수과정 돌면서 해당 filter 로직에 의해서 tokenstream 을 만들어 낸다.
public class TestTokenizerFactory extends AbstractTokenizerFactory {
    @Inject
    public TestTokenizerFactory(Index index, @IndexSettings Settings indexSettings, @Assisted String name, @Assisted Settings settings) {
        super(index, indexSettings, name, settings);
    }
    @Override
    public Tokenizer create(Reader reader) {
        return new TestTokenizer(reader);
    }
}
실제 메인으로 엘라스틱 바인딩프로세스에서 호출될 Analyzer 클래스를 만들어준다. TokenStreamComponents 메소드를 구현하여 토크나이져, 필터를 적용시켜 tokenStream을 만들게 된다.
기타 불용어처리를 하기 위해 이 경우 stopwordanalzyer를 기본으로 만든다.
그리고 아래에 사용되는 TestTokenizer, TestFilter 는 따로 구현을 해주어야 한다. 그것은 lucene analyzer구현과 같다.
그 lucene analyzer를 elasticsearch에 바인딩 시키는 것이다.
흐름 :
analyzer가 사용할 filter, tokenizer를 선언한다. 필터는 여러개가 들어갈 수 있다.(tokenStream의 데코레이터 패턴으로 보면된다.)
analyzer로 reader 타입으로 들어오게 되는데 이후 filter class들로 tokensteam형태로 들어가게 되고, 해당 tokenStream을 적절히(원하는 형태로) 처리한다.
public class TestAnalyzer extends StopwordAnalyzerBase {
	private Version matchVersion;
	public TestAnalyzer(Version version) throws IOException {
                // stopword(불용어)를 줄 수 있다. 아래 resource에 파일로 보관했기 때문에 아래와 같이 넣어 준다.  
		super(version, loadStopwordSet(false, TestAnalyzer.class, "stopwords.txt", "#")); 
		this.matchVersion = version;
	}	
	@Override
	protected TokenStreamComponents createComponents(String fieldName,
			Reader reader) {
		final Tokenizer source = new TestTokenizer(reader);
		TokenStream tok = new LowerCaseFilter(matchVersion, source);
	    tok = new TestFilter(tok);
	    tok = new StopFilter(matchVersion, tok, stopwords);
	    return new TokenStreamComponents(source, tok);
	}
}
아래는 TestFilter 이다. tokenizer에서 분리되어진 단어들이 분리된 정보(position, type, offset)와 함께 들어가게 된다. 루씬의 TokenFilter클래스를 상속받아
increamentToken 메소드를 재정의 하면 된다.
increamentToken() 메소드를 돌면서 tokenizer로부터 만들어진 토큰들을 받아 처리한다. 즉 필터는 각 토큰들의 상태(offset, position, type)을 다시 만들어줄 수 있다.
public class TestFilter extends TokenFilter {	
	private TypeAttribute typeAtt = addAttribute(TypeAttribute.class);   // 타입을 나타냄
	private CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);    // 토큰의 텍스트 자체를 나타냄
	private OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);  // 하이라이팅될 때 그 문자의 offset을 가리킴. es의 highlight쿼리하게 될 때 중요.
	private PositionIncrementAttribute posIncrAtt = addAttribute(PositionIncrementAttribute.class); 문자의 거리. token의 index라고 보면됨

	public TestFilter(TokenStream input) {
		super(input);
	}
	@Override
	public boolean incrementToken() throws IOException {		    		
		while(input.incrementToken()) {                   
                     termAtt.buffer(); 토큰 텍스트를 set해줌.
	             offsetAtt.setOffset(텍스트 시작위치, 텍스트 끝 위치 );
	             typeAtt.setType( 토큰 타입 );	    
	             posIncrAtt.setPositionIncrement(토큰 순서);
                }
	}
}

이클래스에서 위에서 만든 analyzer, filter, tokenizer들을 elasticesearch로 바인딩한다.
public class TestAnalyzerPlugin extends AbstractPlugin {
    @Override
    public String name() {
        return "test-analyzer";
    }
    @Override
    public String description() {
        return "test analyzer support";
    }
    public void onModule(AnalysisModule module) {
        module.addProcessor(new TestAnalysisBinderProcessor());
    }
}

적용 방법 :
main/resource/es-plugin.properties 파일을 생성 후 plugin=org.elastic.com.TestAnalyzerPlugin
입력 후 저장
이것은 ES에서 따로 설치 과정을 거치지 않고 지정된 디렉토리에서 바로 플러그인을 인식하도록 한다.
mvn package 하여 패키징한다.
elastic plugins 디렉토리 밑에 name 함수에 선언한 "test-analyze" 라는 이름으로 디렉토리를 만들고
밑에 위 소스들을 패키징한 jar를 위치시킨다

인덱스 만들시에 setting 에 아래와 같이 추가해서 인덱스를 만들어준다.
 
{
  "analysis":{
      "analyzer":{
         "test_analyzer":{
             "type":"org.elastic.com.TestAnalyzerPlugin",
             "tokenizer":"test_tokenizer",
             "filter":["trim","test_filter","lowercase"]
          }
       }
}


자바의 경우

XContentBuilder indexSettings = XContentFactory.jsonBuilder(); indexSettings.startObject() .startObject("analysis") .startObject("analyzer") .startObject("test_analyzer") .field("type","com.elastic.plugin.TestAnalyzerProvider") .field("tokenizer","test_tokenizer") .field("filter",new String[]{"lowercase","trim","test_filter"}) .endObject() .endObject() .endObject() .endObject(); CreateIndexRequestBuilder indexCreateRequest = client.admin().indices().prepareCreate("test_index_v1) .setSettings(indexSettings); indexCreateRequest.execute().actionGet();



토크나이져는 lucene기본으로 있는 whitespacetokenizer 혹은 다른 것들을 쓸 수 있다. 물론 구현체를 넣어서 사용가능(tokenizer 클래스 상속 후 increamentToken() 구현해야함)
정리를 하자면 input -> tokenizer -> tokenfilter -> tokenfilter -> tokenfilter (다수 토큰필터를 적용가능, 물론 코드상 처리순서대로 데이터에 적용됨.)
위의 흐름은 각 사이에 모두 tokenStream 형태로 교환되어 increamentToken()을 통해 문장에서 떨어진 각 단어?토큰 들에 접근이 가능하게 된다. 이런 것들을 이용하여 자체적인 비즈니스 로직이 더해진 색인어를 만들 수 있다.
예를 들면 "게임중에 음료수를 마신다." 를 whitespaceAnalyze 한 다음 형태소 분석을 통해 "게임중에"의 조사를 때고 "게임"으로 바꾼 다던지, 색인이 필요없는 것들은 불용어 처리를 하고,
용언등에 대한 처리를 더하는 등을 할 수 있다.

참고 : http://jjeong.tistory.com/818


//
프로그래밍/ElasticSearch 2015. 5. 28. 11:32

PUT /index_name { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 } }



//
프로그래밍/ElasticSearch 2015. 5. 15. 11:23
http://localhost:9201/_cluster/health?pretty=true 
위 URL처럼 해당 클러스터 노드에 쿼리 할 경우 아래 와 같은 json array 타입으로 클러스터 상태를 알 수 있다.
{
  "cluster_name" : "clustername",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 40,
  "number_of_data_nodes" : 10,
  "active_primary_shards" : 7,
  "active_shards" : 70,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0
}


//
프로그래밍/리팩토링 2015. 5. 14. 20:43

1. 중복된 코드를 줄이자.

   이것은 상속에 의해서도 구현될 수 있고, extract method 에 의해 정리될 수 도 있다. 

   많은 서브 클래스들에서 사용되는 중복된 코드는 super클래스에 정의/ 사용하므로써 중복을 줄일 수 있다. 

2. 긴 메소드

  객체를 심하게? 잘 이용된 프로그램은 해당 메소드가 어디선가 일어나는 것 같아 보이지 않고, 객체를 다른 객체로 많이 넘기는 상황? 을 볼 수 있다. 이러한 것들이 이루어지기 위해서는 메소드가 한 기능만 하도록 하고 짧아야한다. 그렇지만 메소드가 짧고 여러가지로 나눠지게 되면 다른 사람이 파악하기 어려워지는데 이럴 수록 메소드의 이름을 명확히 잘 지어내야 한다.(이거 어려운것 같다;;)



'프로그래밍 > 리팩토링' 카테고리의 다른 글

Extract Class(클래스 분리하기)  (0) 2015.10.27
//
프로그래밍 2015. 5. 7. 00:17
SELECT 
concat(table_schema,'.',table_name),   
concat(round(table_rows/1000000,2),'M') rows,   
concat(round(data_length/(1024*1024*1024),2),'G') DATA,   
concat(round(index_length/(1024*1024*1024),2),'G') idx,   
concat(round((data_length+index_length)/(1024*1024*1024),2),'G') total_size,   
round(index_length/data_length,2) idxfrac    
FROM information_schema.TABLES  
where table_name = '테이블명' ;

select table_schema "databases_name", SUM(data_length + index_length) / 1024 / 1024 "size(MB)" from information_schema.TABLES;

'프로그래밍' 카테고리의 다른 글

mysql 대소문자 비교 컬럼  (0) 2015.09.02
맥에 java 설치  (0) 2015.06.12
[maven] jar 를 Local Repository 에 추가하기  (0) 2015.05.06
maven 프로젝트생성하기  (0) 2015.05.06
저장 검색의 복잡도  (0) 2015.04.08
//
프로그래밍/ElasticSearch 2015. 5. 7. 00:02

elasticsearch query 는 보통 아래와 같은 쿼리를 많이 사용하게 되는데


------------------------------------------------

   query :{

       match / query_string:{

            analyzer: ~~~

               ~~~~~

     }

}

------------------------------------------------

{

    query : {

       bool : {

          should/must :{  [

              ~~~~~~

          ],[

               filter : { term: ~~~}

             ~~~~~~~

          ]

         }

      }

   }

}

------------------------------------------------


filter와 query 를 많이 사용하게 된다.  

filter / term 조합, query / match 조합을 사용하게 된다. filter 를 사용할시 해당 필드와 정확히 같은 내용을 찾는 것이고, query의 경우 해당 ES 인스턴스가 사용하는 analyzer에 의해서 분석된 결과 값을 보여준다. 


//
프로그래밍 2015. 5. 6. 23:40

내부적으로 사용되는 lib들은 프로젝트에서 사용하기 위해서 artifactId 등을 따로 지정해서 사용할 수 있다.

이런 library등을 jar파일로 설치한다. 설치라기보다 로컬 리파지토리로 가져온다. 

이후 pom.xml에 해당 artifactid, groupid 를 추가해서 사용할 수 있다.

maven은 로컬리파지토리에서 해당 id들을 찾은 후 외부 저장소에서 찾는 순서인듯 하다.

mvn install:install-file
  -Dfile=<path-to-file>
  -DgroupId=<group-id>
  -DartifactId=<artifact-id>
  -Dversion=<version>
  -Dpackaging=<packaging>
  -DgeneratePom=true

Where: <path-to-file>  the path to the file to load
       <group-id>      the group that the file should be registered under
       <artifact-id>   the artifact name for the file
       <version>       the version of the file
       <packaging>     the packaging of the file e.g. jar

예를 들어 test.jar 를 등록한다고 하면 

mvn install:install-file -Dfile=test.jar -DgroupId=test -DartifactId=testing -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true


'프로그래밍' 카테고리의 다른 글

맥에 java 설치  (0) 2015.06.12
mysql table 용량 보는 쿼리  (0) 2015.05.07
maven 프로젝트생성하기  (0) 2015.05.06
저장 검색의 복잡도  (0) 2015.04.08
git reset commit 살리기  (0) 2015.03.24
//
프로그래밍 2015. 5. 6. 23:33
mvn archetype:generate -DgroupId={project-packaging} 
   -DartifactId={project-name} 
   -DarchetypeArtifactId=maven-archetype-quickstart 
   -DinteractiveMode=false

1) 메이븐에서 프로젝트 위 command로 프로젝트 생성.

2) pom.xml파일에서  필요 디펜던시 추가. 

<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>

3) mvn install 로 추가된 디펜던시 로컬리파지토리로 설치.

3) mvn eclipse:eclipse 명령으로 이클립스 파일 생성하고 프로젝트 import 함.



'프로그래밍' 카테고리의 다른 글

mysql table 용량 보는 쿼리  (0) 2015.05.07
[maven] jar 를 Local Repository 에 추가하기  (0) 2015.05.06
저장 검색의 복잡도  (0) 2015.04.08
git reset commit 살리기  (0) 2015.03.24
Linux Load average에 대해서  (0) 2015.03.10
//
프로그래밍 2015. 4. 8. 18:49

자료구조 (array 에서 트리까지) 복잡도

array  o(n)

Binary search tree 

 - worst : o(n)

 - 평균 : o(log n)

balenced binary search tree(ex. rb tree)

  - worst : o(log n)

b-tree

  - worst : O(log n)

hash table

  - O(1)

linked list

 - worst : O(N) <검색시 worst>

 - 삽입삭제시 O(1)


//