ElasticSearch 자주 사용하는 작업: 문서 모음

13767 단어 Elasticsearch문서
[TOC]

1 새 문서


1.1 지정 id

PUT my_blog/article/1
{
  "id":1,
  "title":"elasticsearch",
  "posttime":"2017-05-01",
  "content":"elasticsearch is helpfull!"
}

반환:
{
  "_index": "my_blog",
  "_type": "article",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

버전 번호는 문서 업데이트에 따라 자동으로 증가합니다.

1.2 id를 지정하지 않음


id를 지정하지 않으면 es가 자동으로 생성되지만post만 사용할 수 있습니다.
POST my_blog/article
{
  "id":2,
  "title":"spark",
  "posttime":"2017-05-01",
  "content":"spark is helpfull!"
}

반환:
{
  "_index": "my_blog",
  "_type": "article",
  "_id": "AWagTCv8O1qbT1zqbREV",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

2 문서 가져오기


2.1 일반 획득


존재하는 문서를 가져오려면 다음과 같이 하십시오.
GET my_blog/article/1

반환:
{
  "_index": "my_blog",
  "_type": "article",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "id": 1,
    "title": "elasticsearch",
    "posttime": "2017-05-01",
    "content": "elasticsearch is helpfull!"
  }
}

존재하지 않는 문서를 가져오려면 다음과 같이 하십시오.
GET my_blog/article/2

반환:
{
  "_index": "my_blog",
  "_type": "article",
  "_id": "2",
  "found": false
}

2.2 문서의 존재 여부 테스트


HEAD를 사용하여 문서가 있는지 테스트합니다.
HEAD my_blog/article/1
200 - OK

HEAD my_blog/article/2
404 - Not Found

2.3 대량 획득


index마다 다른 유형:
GET _mget
{
  "docs":[
    {
      "_index":"my_blog",
      "_type":"article",
      "_id":1
    },
    {
      "_index":"twitter",
      "_type":"tweet",
      "_id":2
    }
  ]
}

같은 index에서 다른 유형:
GET my_blog/_mget
{
  "docs":[
    {
      "_type":"article",
      "_id":1
    },
    {
      "_type":"essay",
      "_id":2
    }
  ]
}

같은 index 같은 유형:
GET my_blog/article/_mget
{
  "docs":[
    {"_id":1},
    {"_id":2}
  ]
}

또는:
GET my_blog/article/_mget
{
  "ids":[1,2]
}

3 문서 업데이트


es 업데이트 문서의 원리는 이 문서를 먼저 찾고 낡은 문서 내용을 삭제하여 업데이트를 실행하고 업데이트가 끝난 후에 최신 문서를 인덱스하는 것입니다.
다음 문서를 먼저 추가합니다.
PUT test/type1/1
{
  "counter":1,
  "tags":["red"]
}

3.1 문서 필드 내용 업데이트


카운터의 값을 4:
POST test/type1/1/_update
{
  "script": {
    "inline": "ctx._source.counter += params.count",
    "lang": "painless",
    "params": {
      "count":4
    }
  }
}

Note1: 명령에서 inline은 실행된 스크립트이고ctx는 스크립트 언어의 실행 대상입니다.painless는es에 내장된 스크립트 언어이고params는 매개 변수 집합입니다.
Note2:ctx 대상은 _source 외에 _index, _type, _id, _version, _routing, _parent 등 필드를 방문할 수 있습니다.
tags 필드에 값을 추가합니다.
POST test/type1/1/_update
{
  "script":{
    "inline":"ctx._source.tags.add(params.tag)",
    "lang":"painless",
    "params":{
      "tag":"blue"
    }
  }
}

3.2 필드 추가 및 제거


test/type1/1에 필드name 추가:
POST test/type1/1/_update
{
  "script": {
    "inline": "ctx._source.name=\"test\""
  }
}

위의 명령도 약어로 {"script":""ctx._source.name=\"test\""}으로 쓸 수 있다
name 필드 제거:
POST test/type1/1/_update
{
  "script": {
    "inline": "ctx._source.remove(\"name\")"
  }
}

3.3 upsert 작업


문서가 존재하지 않으면upsert는 새 문서를 만들고 문서가 존재하면script 스크립트를 정상적으로 실행합니다.다음과 같습니다.
POST test/type1/2/_update
{
  "script": {
    "inline": "ctx._source.counter += params.count",
    "lang": "painless",
    "params": {
      "count":4
    }
  },
  "upsert": {
    "counter":1,
    "tag":["pink"]
  }
}

테스트/type 1/2가 존재하면count를 업데이트하고, 존재하지 않으면 필드counter와tag를 포함하는 문서를 새로 만듭니다.
반환:
{
  "_index": "test",
  "_type": "type1",
  "_id": "2",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  }
}

3.4 doc 기반 업데이트 방식


doc 방식으로 필드 내용을 업데이트하거나 새 필드를 추가할 수도 있습니다.
POST myblog/article/1/_update
{
  "doc": {
    "title":"test new title"
  }
}

POST myblog/article/1/_update
{
  "doc": {
    "new field":"this is a new field"
  }
}

4 쿼리 업데이트

POST my_blog/_update_by_query
{
  "script":{
    "inline": "ctx._source.content = params.content",
    "lang": "painless",
    "params": {
      "content":"spark is popular"
    }
  },
  "query":{
    "term": {
      "title": {
        "value": "spark"
      }
    }
  }
}

반환:
{
  "took": 33,
  "timed_out": false,
  "total": 1,
  "updated": 1,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1,
  "throttled_until_millis": 0,
  "failures": []
}

5 문서 삭제

DELETE my_blog/article/2

문서를 색인할 때 라우팅을 지정한 경우 삭제할 때 라우팅 매개변수를 추가할 수도 있습니다.
DELETE my_blog/article/2?routing=user123

Note1: 라우팅 값이 올바르지 않으면 삭제에 실패합니다.
Note2: 매핑된 경우 _routing이required로 설정되어 있고 지정한 루트 값이 없을 때 삭제 작업을 수행하면 루트 부족 이상을 던지고 이 요청을 거부합니다.

6 질의 삭제

POST my_blog/_delete_by_query
{
  "query":{
    "term": {
      "title": {
        "value": "mybatis"
      }
    }
  }
}

type에서 모든 문서를 삭제하려면 다음과 같이 하십시오.
POST my_blog/article/_delete_by_query
{
  "query":{
    "match_all":{}
  }
}

7 대량 작업


7.1 명령 형식


다음 명령을 사용합니다.
curl -XPOST 'localhost:9200/indexname/_bulk?prettry' --data-binary @accounts.json

accounts.json 파일은 다음 형식을 충족해야 합니다.
action_and_meta_data 
data 

Note1:action_and_meta_데이터 줄에서 action은 반드시 index,create,update 또는delete이어야 한다.metadata는 조작된 문서가 필요한 _index,_type_id을 가리켜야 한다.
Note2: 데이터 줄은 추가된 데이터입니다. 문서를 추가할 때 데이터 줄이 필요합니다.
Note3: 모든 줄의 끝에 줄 바꿈 문자가 있어야 합니다. 마지막 줄도 있어야 합니다. 줄 바꿈은 모든 줄을 효과적으로 구분할 수 있습니다.

7.2 문서 추가

{"index": {"_index": "my_blog"}, "_type": "article", "_id": "1"}
{"title": "blog title"}

또는
{"create": {"_index": "my_blog", "_type": "article", "_id": "1"}}
{"title": "blog title"}

id 안 써도 돼요.

7.3 문서 삭제

{"delete": {"_index": "website", "_type": "blog", "_id": "123"}}

7.4 종합 사례


인덱스 문서 요청, 문서 업데이트 요청 및 문서 삭제 요청은 다음과 같습니다.
{"delete": {"_index": "website", "_type": "blog", "_id": "123"}}

{"create": {"_index": "website", "_type": "blog", "_id": "123"}}
{"title": "blog title"}

{"index": {"_index": "website", "_type": "blog"}}
{"title": "blog title"}

{"update": {"_index": "website", "_type": "blog", "_id": "123"}}
{"doc": {"title": "blog title"}}

8 버전 제어


처음 접촉, 8.2는 무시할 수 있습니다. 8.3의 명령 조작을 이해하면 됩니다.
es가 문서 업데이트를 진행할 때 먼저 원본 문서를 읽고 원본 문서에 대해 업데이트 작업을 하고 업데이트 작업이 끝난 후에 전체 문서를 다시 인덱스합니다.

8.1 잠금 제어


여러 사용자가 동시에 같은 문서 데이터에 대해 수정 업데이트 작업을 할 가능성이 높으며, 이때 사무적 제어를 하거나 병렬 제어를 해야 한다.

8.1.1 비관적 잠금 제어


만약 스레드가 데이터를 수정하면 데이터를 잠그고, 다른 스레드가 접근하려면 현재 잠금이 풀리기를 기다려야 합니다. 이렇게 하면 같은 시간에 최대 한 개의 스레드만 데이터에 접근할 수 있습니다.전통적인 관계형 데이터베이스는 이런 자물쇠 메커니즘을 많이 사용했다. 예를 들어 줄 자물쇠, 시계 자물쇠, 읽기 자물쇠, 쓰기 자물쇠 등이다.

8.1.2 낙관적 잠금 제어


데이터 자원은 잠기지 않고 데이터 제출 작업 때만 데이터 완전성 위반 여부를 검사합니다.Elasticsearch가 사용하는 것은 바로 낙관 자물쇠 메커니즘이다. 낙관 자물쇠는 읽기 조작보다 쓰기 조작이 많은 응용 유형에 적용되어 자물쇠 비용을 줄이고 흡수량을 높일 수 있다.

8.2es의 버전 제어


기왕es가 사용하는 것이 낙관적인 자물쇠라면 어떻게 낡은 데이터가 새로운 데이터를 덮어쓰지 않을 것을 보장합니까?es에서 사용_버전을 제어합니다. 문서가 업데이트될 때마다 1.
es의 문서 버전 제어 메커니즘은 주로 내부 버전 제어와 외부 버전 제어가 있다.
  • 내부 버전 제어 메커니즘은 매번 조작 요청을 요구하며 버전 번호가 같을 때만 조작에 성공할 수 있다.
  • 외부 버전 제어는 외부 문서 버전이 내부 문서 버전보다 높을 때 업데이트에 성공하도록 요구한다.

  • 사실 데이터를 요청하든 업데이트를 요청하든 버전 번호를 휴대할 수 있습니다. 아무리 복잡해도 다음 두 가지만 기억하면 됩니다.
  • 1.데이터 가져오기 작업만 요청하면 내부 버전 제어 메커니즘이 적용되고 외부 버전 제어 메커니즘이 적용되지 않습니다. 상황은 다음과 같습니다.
  • a. 버전 번호 없음, 조작 성공:
  • b. 내부 버전 번호를 가지고 있으면 반드시 문서의 현재 버전 번호와 같아야 한다.
  • c. 외부 버전 번호를 가지고 있으면 반드시 문서의 현재 버전 번호와 같아야 한다.

  • 2.업데이트 작업의 경우 다음과 같습니다.
  • a. 버전 번호를 휴대하지 않고 조작에 성공하면 문서 버전 번호가 1이 추가됩니다.
  • b. 내부 버전 번호를 가지고 있으면 반드시 문서의 현재 버전 번호와 같고 문서 버전 번호는 1이 추가됩니다.
  • c. 외부 버전 번호를 가지고 있으면 반드시 문서의 현재 버전 번호보다 크고 문서 버전은 가지고 있는 버전 번호와 같다.


  • 버전 번호를 가지고 있는지 여부의 측면에서 이 문제를 생각할 수도 있다.
  • 1.버전 번호를 휴대하지 않고 데이터 획득과 업데이트 작업이 성공합니다.
  • 2.내부 버전 번호를 휴대하고 어떤 조작을 하든지 문서 버전 번호와 반드시 같아야 한다.
  • 3.외부 버전 번호를 가지고 데이터를 요청할 때 버전 번호가 같고 업데이트 작업할 때 버전 번호가 문서 버전 번호보다 크다.

  • 에스는 왜 이렇게 디자인합니까?사실 내부 버전 번호는es가 제공한 것이지만 실제로는 자신의 업무나 프로그램에 대한 수요도 있을 수 있다. 즉, 당신의 응용 시스템 자체가 버전 번호를 유지했다거나 어떤 메커니즘을 통해 버전 번호를 유지하고 싶다면 외부 버전 번호를 사용할 수 있다.

    8.3 명령 작업

    GET website/blog/1?version=1
    
    PUT website/blog/1?version=5&version_type=external

    9 라우팅 메커니즘


    9.1 분할 위치 계산 및 사례


    색인에 여러 개의 섹션이 있을 때, 하나의 문서를 색인합니다.es는 어떻게 문서를 어느 문서에 저장할지 결정합니까?다음과 같은 환경을 가정합니다.
    Master Node:
    shard0(primary)
    shard1 
    shard2(primary)
    
    Common Node:
    shard0
    shard1(primary)
    shard2

    es의 라우팅 메커니즘은 해시 알고리즘을 통해 같은 해시 값을 가진 문서를 같은 메인 슬라이드에 배치합니다. 방법은 다음과 같습니다.
    shard = hash(routing) % number_of_primary_shards

    만약에 우리가 문서를 추가했는데 id를 지정하지 않았다면es가 우리에게 생성한 id는 AWagTCv8O1qbT1zqbREV이고 위의 공식을 사용하면shard는 다음과 같이 해야 한다.
    shard = hash("AWagTCv8O1qbT1zqbREV") % 3

    물론 해시 함수의 실현이 반드시 필요한 것은 아니다. 우리는python에서 제공하는hash() 함수를 호출하여 위의 계산을 보여줄 수 있다.
    >>> shard = hash("AWagTCv8O1qbT1zqbREV") % 3
    >>> shard
    2

    분명히 이 문서는 섹션 2, 즉 세 번째 섹션에 저장될 것이다.
    위의 소개를 통해 알 수 있듯이 기본 루트 모드는 데이터의 평균 분포를 보장하지만routing 값을 사용자 정의하여 문서의 저장 위치를 지정할 수 있다.

    9.2es 조회 프로세스와 사용자 정의routing 값


    만약 50개의 블록이 있는 인덱스가 존재한다면, 집단에서 조회를 실행하는 과정은 다음과 같다.
  • (1) 조회 요청은 우선 집단 중의 한 노드에 접수된다.
  • (2) 이 요청을 받은 노드에서 이 검색을 이 인덱스의 모든 섹션에 방송합니다.
  • (3) 각 조각마다 검색 검색을 마치고 결과를 되돌려줍니다.
  • (4) 결과는 채널 노드에서 통합되고 정렬되며 사용자에게 되돌아온다.

  • 이러한 방송을 피하기 위해 루트 값을 사용자 정의할 수 있습니다. 다음은 사례를 들어 설명합니다.
    일반적으로 다음과 같이 문서를 추가합니다.
    PUT website/article/1
    {
        "title":"My first blog entry",
        "text":"Just trying this out...",
        "user":"user123"
    }

    조회할 때 user123의 모든 글을 조회하시기 바랍니다.
    GET website/article/_search
    {
        "query":{
            "term":{"user":"user123"}
        }
    }

    분명히 이렇게 조회하면 위의 절차에 따라 갈 것이다. 즉, 요청은 모든 섹션에 발송될 것이다. 이때 최적화를 바란다.
    사용자를 routing으로 사용하여 문서를 추가합니다.
    PUT website/article/1?routing=user123
    {
        "title":"My first blog entry",
        "text":"Just trying this out...",
        "user":"user123"
    }

    routing 값을 지정하면 뒤에 있는user123이 발표한 글(문서)은 모두 같은 섹션에 저장됩니다. 여기서 섹션 1이라고 가정하면 우리가user123이 발표한 글을 조회할 때 검색할 때routing 값을 지정하면 방송 요청에 의해 요청되지 않습니다. 요청은 섹션 1에 바로 도착합니다. 조회는 다음과 같습니다.
    GET website/article/_search?routing=user123

    Note1: 이렇게 하면 문제를 가져올 수 있다. 예를 들어user123이 수십만 편의 글을 발표했지만 다른 사용자들은 아주 적은 글만 가지고 데이터의 분배가 불균형적이다.
    Note2: 문서에 여러 개의 루트 값을 지정할 수도 있고 루트 값 사이에 쉼표로 구분할 수도 있다. (이렇게 되면 문서는 여러 개의 섹션에 분배될 수 있다. 그 조건을 만족시키는 이 몇 개의 섹션에 대해es가 어떻게 선택했는지, 어떤 알고리즘을 통해 스스로 연구할 수 있다.)

    좋은 웹페이지 즐겨찾기