반응형

몽고 DB에서 Aggreate를 통해 쿼리를 전달시 특정 컬렉션을 생성하는 이슈가 있었는데,

몬스태쉬가 자꾸 해당 컬렉션을 가져오면서 엘라스틱에도 데이터를 넣는 상태를 확인 할 수 있었다.

추후 용량등 문제가 발생할 수 있을것이라 판단이 되었고 특정 형태로 생성되는 컬렉션의 이벤트는 감지하지 않도록 설정하고 싶어졌다.

 

monstache 설정 파일인 config.toml 파일에 옵션으로 아래의 설정을 하면 특정 컬렉션의 이벤트를 감지하지 않도록 설정 할 수 있다.

https://rwynn.github.io/monstache-site/config/#namespace-exclude-regex

 

Configuration - Monstache

From here you can search these documents. Enter your search terms below.

rwynn.github.io

namespace-exclude-regex 

공식 홈페이지 설명과 같이 몽고DB에 삽입, 수정, 삭제가 일어나도 해당 정규식으로 설정된 컬렉션은 바라보지 않도록 설정할때 해당 옵션을 사용하는것으로 보인다. 아래 설정을 통해 실제 적용에 성공하였다.😁

 

config.toml

namespace-exclude-regex = '^데이터베이스명.tmp*'
direct-read-dynamic-exclude-regex = '^데이터베이스명.tmp*'

(해당 데이터베이스에 tmp로 시작하는 컬렉션은 바라보지 않도록 설정)

 

 

 

반응형
반응형

text filed에서 검색어 입력시 검색이 되었다고 가정하고, 각 쿼리 메소드마다 동작하는 방식의 차이가 있어서 정리를 해봅니다.

약 2천개의 데이터만 넣어두고 간단하게 테스트를 진행해보았으며, 검색 필드명은 description이였습니다.

Query DSL

Elasticsearch

REST API

[

POST

,HEADER : { Content-Type : application/json }

,BODY: {raw: }

]

result

match

{
  "query": {
    "match": {
      "description": "are not"
    }
  }
}

total : 680

description 필드에 “are”, “not”이 포함된 문서를 검색합니다. match에 여러개의 검색어를 넣게 되면 or 조건으로 검색됩니다.

“are”, “not” 둘 중 하나라도 포함되면 검색됨

desc: are ... ~~ In getProcessRecordLocked(o)

desc: not ... some web.. ~ (o)

match

{
  "query": {
    "match": {
      "description": {
        "query": "are not",
        "operator": "and"
      }
    }
  }
}

total: 63

or 조건절로 검색되는 현상을 막기위해서 operator 옵션을 사용하여 and절로 검색할 수 있습니다.

“are” 도 있고 “not” 도 존재하는 text field를 조사합니다.

desc: are ... ~~ in getProcessReco... (x)

desc: are ... ~~ interaction is not needed...(o)

match_phrase

{
  "query": {
    "match_phrase": {
      "description": {
        "query": "are not",
        "slop": 1
      }
    }
  }
}

total: 23

정확하게 are not으로 작성된 text field를 검색합니다.

 

desc: are ... ~~ interaction is not needed...(x)

desc: .... isolated apps are not handled (o)

 

regexp

{
  "query": {
    "bool": {
      "must" : [
        {"regexp": {
          "description": ".*are.*"
        }},
        {"regexp": {
          "description": ".*not.*"
        }}
      ]
    }
  }
}

total: 107

얼핏보면 match and와 비슷해보이지만 결과가 다릅니다. 정규식이기 때문에 단어라인이 포함만 되어도 동작합니다.

 

desc: these details are obtained from...

vectors. NOTE: some of ...~ (o)

반응형
반응형

 

Query DSL Elasticsearch REST API [
 POST
 ,HEADER : { Content-Type : application/json }
 ,BODY: {raw: }
]
RDB
match_all {
  "query": {
    "match_all":{}
  }
}
select * from table
match {
  "query": {
    "match": { "필드명": "값" }
  }
}
select * from table
where 필드명= “값
bool,
match,
match_not
{
  "query": {
    "bool": {
      "must": [
        { "match": { "필드명": "" }
        }
      ],
      "must_not": [
        { "match": { "addressSiGunGu" : "강남구" }}
      ]
    }
  }
}
select * from table
where 필드명1 = “값1
and 필드명2 != “값2
range {
  "query": {
    "range": {
      "필드명": {
        "gte": "2021-03-07",
       
"lte": "2021-03-20",
       
"format": "yyyy-MM-dd"
      }
    }
  }
}
select * from table
where 필드명 between '값1' and '값2'
* range 관련 기본타입이 string인 경우 text field로 인식되어 정상적으로 검색이 안됨. 이런 경우 index로 바꿔주고 검색을 할 수 있음변환처리 아래 URL 참조
myhappyman.tistory.com/223?category=966871
sort
(몽고 db에서 string으로 처리되어 elasticSearch에서 text filed로 인식되면 sort가 불가능함)
{
  "sort": [
    { "필드명" : "desc" },
    "_score"
  ],
  "query": {
    "match_all":{}
  }
}
select * from table
order by 필드명 desc
regexp {
  "query": {
    "regexp":{
      "필드명": ".*값.*"
    }
  }
}
like문과 유사하지만 완전 다름
. : 모든 문자열을 뜻한다.  * : 0개 이상의 자리수를 갖는 문자열
0개 이상의 모든 문자열을 찾는 쿼리

 

 

단순 총 리스트의 개수 가져오기

GET /<target>/_count

반응형
반응형

Elasticsearch Rest API 형태로 데이터를 조회하기 위해 쿼리를 던지는데, 기존 몽고 DB 필드가 모두 string 형태라 elasticsearch로 넘어오면서 text field로 인식되면서 range를 통해 조건 검색이 안되는 모습을 보였다.

 

해당 필드를 검색되도록 변경하기 위해 mapping 쿼리를 처리해보았는데, 아래처럼 에러가 발생했다.

>PUT http://118.37.186.231:9200/egoviot.usercollection

{
  "mappings": {
    "egoviot.usercollection": {
      "properties": {
        "accessDate": {
          "type":   "date",
          "format": "yyyy-MM-dd"
        }
      }
    }
  }
}

"type": "resource_already_exists_exception"

"reason": "index [egoviot.usercollection/J42yGfwSSOWqNj3bLk5W_g] already exists",

 

결론은 존재하는 index가 이미 존재해서 변경이 불가하다였다.

 

특정 필드 데이터값을 변경하고, 아래와 같이 reindex를 처리하였다.

>POST http://주소값/_reindex

{
	"source": {     
		"index": "egoviot.usercollection"
	},   
	"dest": {     
		"index": "egoviot.usercollection2"
	}
}

 

이후 변경된 인덱스를 통해 조회하면 정상적으로 조회되는 모습을 볼 수 있다.

>POST http://주소값/egoviot.usercollection2/_search

{
  "query": {
    "range": {
      "accessDate": {
        "gte": "2021-03-07",
        "lte": "2021-03-20"
      }
    }
  }
}

 조회가 된다!

반응형
반응형

팀원끼리 몇 일간에 삽질끝에 설정이 완료되어 내용을 공유해보고자 합니다.

다들 몽고만 써보고 도커나 엘라스틱서치는 써본적이 없었고 이번에 환경 구성을 위해 도커를 사용하면서 엘라스틱서치와 몽고DB 레플리카셋 설정을 시작해보았습니다.

 

 

엘라스틱서치와 몽고 DB 환경 구성하기

(OS는 CentOs에서 진행되었으며, 먼저 docker와 docker-compose가 설치되어 있어야 합니다.)

 

몽고 DB와 엘라스틱서치 환경 구성을 위해서는 몽고 DB를 레플리카셋으로 구성해야하는데, (안정성때문이라고 합니다.) 이를 위해 몽고DB간에 연결을 위한 이미지를 먼저 docker-compse를 통해 생성해야 합니다.

 

setup-rspl 이미지 생성하기

파일구성

 

docker-compose.yml

version: '4'
services:
  mongo1:
    image: "mongo"
    ports:
      - "27020:27017"
    volumes:
      - /home/psw/mongodb/mongo1:/home/psw/data
    networks:
      - mongo-networks
    command: mongod --replSet replication
  mongo2:
    image: "mongo"
    ports:
      - "27021:27017"
    volumes:
      - /home/psw/mongodb/mongo2:/home/psw/data
    networks:
      - mongo-networks
    command: mongod --replSet replication
    depends_on:
      - mongo1
  mongo3:
    image: "mongo"
    ports:
      - "27022:27017"
    volumes:
      - /home/psw/mongodb/mongo3:/home/psw/data
    networks:
      - mongo-networks
    command: mongod --replSet replication
    depends_on:
      - mongo2
  mongosetup:
    image: "setup-rspl"
    depends_on:
      - mongo1
    networks:
      - mongo-networks

networks:
  mongo-networks:
    driver: bridge

 

replicaSet.js

config = {
  _id: "replication",
  members: [
    { _id: 0, host: "mongo1:27017" },
    { _id: 1, host: "mongo2:27017" },
    { _id: 2, host: "mongo3:27017" }
  ],
}

rs.initiate(config)

rs.conf()

 

setup.sh

#!/bin/bash

sleep 10 | echo Sleeping

mongo mongodb://mongo1:27017 replicaSet.js

 

Dockerfile

FROM mongo

WORKDIR /usr/src
RUN mkdir configs
WORKDIR /usr/src/configs

COPY replicaSet.js .
COPY setup.sh .

RUN chmod +x ./setup.sh

CMD ["./setup.sh"]

여기까지 세팅이 되었다면 Dockerfile이 있는 위치에서 이미지를 생성한다.

> docker build -t setup-rspl .

 

위 명령어를 날리면 이미지가 생성됩니다.

docker build -t setup-rspl .

 

Elasticsearch + 몽고DB + Monstache 환경구성하기

먼저 만들고 있던 디렉토리 상위로 올라와서 docker-compose.yml과 config, elasticsearch 디렉토리를 구성합니다.

구성할 환경

 

config내부에는 monstache설정파일이 위치하며, elasticsearch디렉토리에는 data디렉토리가 존재하고 비워둡니다.(필요없어보이긴한다...)

아래처럼 다시 환경 구성을 시작합니다.

 

docker-compose.yml

version: "3"

services:
  elasticsearch:
    restart: always
    image: docker.elastic.co/elasticsearch/elasticsearch:6.8.14
    ports:
      - "9200:9200"
      - "9300:9300"
    environment:
      - ES_JAVA_OPTS=-Xms2048m -Xmx2048m
      - discovery.type=single-node
    healthcheck:
      test: "wget -q -O - http://localhost:9200/_cat/health"
      interval: 1s
      timeout: 30s
      retries: 300
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./elasticsearch/data:/home/psw/elasticsearch/data
    networks:
      - monstache-network

  kibana:
    restart: always
    image: docker.elastic.co/kibana/kibana:6.8.14
    expose:
      - 5601
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch
    environment:
      - SERVER_PORT=5601
      - SERVER_NAME=kibana.example.org
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    networks:
      - monstache-network

  monstache:
    restart: always
    image: rwynn/monstache:rel5
    command: -f /home/monstache.config.toml &
    volumes:
      - /home/psw/config/monstache.config.toml:/home/monstache.config.toml
    depends_on:
      - elasticsearch
      - mongo1
      - mongo2
      - mongo3
    links:
      - elasticsearch
    ports:
      - "8080:8080"
    networks:
      - monstache-network

  mongo1:
    image: "mongo"
    ports:
      - "27020:27017"
    volumes:
      - /home/psw/mongodb/mongo1:/home/psw/data
    networks:
      - monstache-network
    command: mongod --replSet replication
  mongo2:
    image: "mongo"
    ports:
      - "27021:27017"
    volumes:
      - /home/psw/mongodb/mongo2:/home/psw/data
    networks:
      - monstache-network
    command: mongod --replSet replication
    depends_on:
      - mongo1
  mongo3:
    image: "mongo"
    ports:
      - "27022:27017"
    volumes:
      - /home/psw/mongodb/mongo3:/home/psw/data
    networks:
      - monstache-network
    command: mongod --replSet replication
    depends_on:
      - mongo2
  mongosetup:
    image: "setup-rspl"
    depends_on:
      - mongo1
    networks:
      - monstache-network

networks:
  monstache-network:
    driver: bridge

 

/config/monstache.config.toml

mongo-url = "mongodb://mongo1:27017,mongo2:27017,mongo3:27017/test?replicaSet=replication"
elasticsearch-urls = ["http://elasticsearch:9200"]
elasticsearch-max-conns = 4
elasticsearch-max-seconds = 5
elasticsearch-max-bytes = 8000000
dropped-collections = false
dropped-databases = false

namespace-regex = "^test"
direct-read-namespaces = ["book","log"]

환경 구성이 완료되면 docker-compose를 통해 서비스를 시작합니다.

> docker-compose up -d

 

-d는 백그라운드로 구동하겠다는 뜻입니다.

  • docker-compose 명령어 정리
docker-compse up 설정된 서비스 컨테이너를 생성 및 시작
docker-compose down 설정된 서비스 컨테이너 덩어리를 삭제(제거)
docker-compose start 설정된 서비스 컨테이너 구동
docker-compose stop 설정된 컨테이너 멈춤

서비스를 종료하고자 할때는 위에 명령어를 적어놨지만 stop으로 종료하고, 완전히 정보를 날리고자 할때는 down으로 컨테이너를 제거할 수 있다.(down은 데이터가 소멸된다. remove효과)

 

 

> docker ps

명령어를 통해 서비스들이 잘 올라왔는지 확인해봅니다.

docker를 설치하면서 시각화 서비스인 포트테이너가 있다면 웹에서 확인해도 좋다. 설정이 잘 못되어 정상적으로 올라오지 않은 경우 쉽게 로그 확인이 가능합니다.

▲ 포트테이너를 통해 확인한 서비스중인 컨테이너 리스트
▲ 동작중인 컨테이너의 로그를 확인 할 수 있다.

 

동작 확인하기

엘라스틱서치까지 healthy로 올라오면 postman이나 브라우저를 통해 9200으로 데이터를 확인해봅니다.

 

처음에는 DB에 데이터가 없을텐데 접속정보의 mongo1로 접속하여 데이터를 삽입해봅니다.

test 데이터베이스를 생성하고, book Collections에 간단하게 두 줄을 넣어봤습니다.

 

 

자 데이터를 넣었으니 조회가 되는지 확인해보겠습니다~

▲ GET > http://IP:PORT/_cat/indices?v

_cat/indices를 통해 엘라스틱서치에 등록된 index정보 리스트를 볼 수 있습니다.

test.book이 추가된 걸 볼 수 있네요.

 

 

특정 인덱스의 데이터 전체 검색

전체 검색을 해보겠습니다.

▲ GET > http://IP:PORT/test.book/_search  index/_search를 통해 검색

 

 

특정 인덱스의 특정 컬럼 조회

이번엔 특정 데이터를 받아보겠습니다.

▲ GET > http://IP:PORT/test.book/_search?q=name:"왜 나는 너를 사랑하는가"

 

 

like 검색해보기

이번에는 like문 검색방법입니다.

POST 방식으로 요청하고 body안에 raw형태로 아래의 형태로 전송을 해봅니다.

  • POST method
  • Headers : Content-Type : application/json
  • Body :
{
  "query" : {
      "bool": {
        "must": {
          "wildcard": {
            "name": "*나는*"
          }
        }
      }
  }
}

 

▲ POST > http://IP:PORT/test.book/_search

 

잘 검색된다!




  

반응형
  1. Favicon of https://lucky7th.tistory.com ****7**** 2021.11.18 17:37 신고

    안녕하세요! 저는 엘라스틱서치 공홈에서 튜토리얼? 정도만 봤는데요
    엘라스틱 자체에도 index로 데이터가 저장되는 걸로 알고 있었는데 몽고를 따로 연결하신 이유가 있을까요??
    (아니면 죄송합니닷! ㅜㅜ)

    • Favicon of https://myhappyman.tistory.com Park.S.W 2021.11.18 17:44 신고

      올해 진행한 프로젝트 구성상 많은 db들이 들어갔었는데 몽고 DB에 데이터를 특정 팀에서 넣어주고 저희는 그걸 검색엔진에 달아주는 구조라서 이런식으로 구성했었습니다!

    • Favicon of https://lucky7th.tistory.com ****7**** 2021.11.19 09:21 신고

      답변 감사합니다 ㅎㅎ

반응형

데이터 제어하기

엘라스틱서치에 데이터를 넣고 조회해보기 전에 저장 구조를 먼저 파악해야합니다.

기존의 RDB와는 용어가 조금 다릅니다.

브라우저에서 http를 통해 확인한것 처럼 http프로토콜을 통해 데이터를 삽입하거나 조회, 수정, 삭제 CRUD 작업을 할 수 있습니다. 사이트중에 http통신을 지원하는 사이트를 통해 진행하거나 크롬 확장앱인 Postman등을 사용하시면 되겠습니다. (물론 자바나 언어로 짜셔도 됩니다!)

 

먼저 포맷은 요청하는 아래처럼 맞춰주셔야 합니다.

http:// IP : port / Index / Type / id값

ex) http://localhost:9200/test/dog/1

 

 

데이터 삽입하기(PUT)

 

제가 키우고 있는 강아지의 정보를 넣어봤습니다.

 

PUT으로 전송을 하면 아래와 같이 생성 및 여러가지 정보를 응답 받을 수 있습니다.

result에는 created라고 값이 들어간 것을 볼 수 있습니다.

인덱스값으로 test가 입력되었습니다.

타입값으로 dog가 입력되었습니다.

 

한번 더 전송해보겠습니다.

 

값 추가하기(PUT)

이번에는 result에 updated라고 나오는것을 볼 수 있습니다. 맨끝은 id값인데 최초에 create되면서 추가된 ggome데이터가 삭제되고 gamja 데이터로 수정되었기 때문입니다.

 

이런 현상을 방지하기 위해 dog위치에 _create를 넣어서 전송하게 되면 에러코드를 반환하여 수정되는 것을 방지 할 수 있습니다.

 

 

데이터 조회(GET)

GET을 통해 도큐먼트의 내용을 가져옵니다.

GET http://localhost:9200/test/dog/1

GET http://localhost:9200/test/dog/2

 

 

삭제하기(DELETE)

DELETE 메서드를 통해 요청하면 됩니다.

도큐먼트나 인덱스 단위로 삭제가 가능합니다.

 

도큐먼트 삭제하기

DELETE http://localhost:9200/test/dog/1

먼저 id값이1이던 gamja 데이터를 삭제했습니다. 결과로 deleted를 받았습니다.

 

데이터 조회시 found속성에 false가 나오면서 찾을 수 없다는 결과를 받았습니다.

 

인덱스 전체 삭제하기

DELETE http://localhost:9200/test

acknowledged속성이 true값으로 전달 받고 이후에 조회시에는  found속성의 false값이 아닌 index자체를 찾을 수 없다는 결과와 함께 404에러코드를 받습니다.

 

 

수정하기(POST)

post는 PUT메서드와 같이 삽입하는 기능처럼 유사하게 동작하지만 id값을 자동으로 생성시킵니다.

PUT처럼 result속성에 created로 받았지만 id가 랜덤으로 들어간 것을 볼 수 있습니다.

 

_update

수정하는 방법은 아래와 같습니다.

인덱스/_update/id

해당 명령 형태를 통해 업데이트가 가능합니다. 해당 방법을 통해 수정시 변경할 필드명의 속성 값만 넣어주면 들어간 속성만 변경이 되며 지정자로 "doc"이 꼭 있어야합니다.

 

변경된 name값을 확인 할 수 있습니다.

반응형
반응형

Elasticsearch?

검색엔진을 만들어야 할 상황을 대비하여 엘라스틱서치를 사용해보기로 했습니다.

엘라스틱서치는 일단 무료이며 모든 유형의 데이터를 분석 및 검색해주는 엔진으로 Apache Lucene을 기반으로 구축되었습니다.

빠른 속도를 통해 데이터를 수집, 분석, 시각화를 도와주는 도구입니다. 넷플리스, 마이크로소프트 등의 큰 기업들도 사용하고 있는것을 볼 수 있습니다.

 

다음으로 윈도우에 설치하고 간단하게 컨셉과 사용법을 알아보겠습니다.

 

설치하고 동작시키기

다운로드

먼저 설치를 위해 공식홈페이지로 이동합니다.

 

www.elastic.co/kr/downloads/elasticsearch

 

Free and Open Search: The Creators of Elasticsearch, ELK & Kibana | Elastic

Elasticsearch can also be installed from our package repositories using apt or yum, or installed on Windows using an MSI installer package. See Repositories in the Guide.

www.elastic.co

원하는 버전을 다운로드 받습니다. 

 

설치하기

다운로드 받으면 zip파일이 나오는데 압축을 해제하고 bin폴더의 elasticsearch.bat를 구동합니다.

정상적으로 구동되면 브라우저를 열고 localhost:9200으로 접속해봅니다.

 

이것으로 엘라스틱서치를 간단하게 설치하고 구동된 모습을 볼 수 있습니다.

반응형