

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon OpenSearch Service를 사용하여 Amazon Neptune에서 전체 텍스트 검색
<a name="full-text-search"></a>

Neptune은 [Amazon OpenSearch Service(OpenSearch Service)](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/)와 통합되어 Gremlin 및 SPARQL 쿼리 모두에서 전체 텍스트 검색을 지원합니다.

[엔진 릴리스 1.3.0.0](engine-releases-1.3.0.0.md)부터 Amazon Neptune은 Gremlin 및 SPARQL 쿼리에서 전체 텍스트 검색을 위해 [Amazon OpenSearch Service Serverless](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless.html)를 사용할 수 있도록 지원합니다.

**참고**  
Amazon OpenSearch Service와 통합할 때 Neptune은 Elasticsearch 버전 7.1 이상이 필요하며, OpenSearch 2.3, 2.5 이상 버전과 함께 사용할 수 있습니다. Neptune은 [OpenSearch Serverless](full-text-search-serverless.md)와도 호환됩니다.

[OpenSearch 데이터를 위한 Neptune 데이터 모델](full-text-search-model.md)에 따라 채워진 기존 OpenSearch Service 클러스터와 함께 Neptune을 사용할 수 있습니다. 또는 AWS CloudFormation 스택을 사용하여 Neptune과 연결된 OpenSearch Service 도메인을 생성할 수 있습니다.

**중요**  
여기에 설명된 Neptune에서 OpenSearch로의 복제 프로세스는 빈 노드를 복제하지 않습니다. 이는 유의해야 할 중요한 제한 사항입니다.  
또한 OpenSearch 클러스터에서 [세분화된 액세스 제어](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html)를 활성화한 경우 Neptune 데이터베이스에서도 [IAM 인증을 활성화](iam-auth-enable.md)해야 합니다.

![\[Neptune 오픈 검색 스트림 폴러 아키텍처 레이아웃입니다.\]](http://docs.aws.amazon.com/ko_kr/neptune/latest/userguide/images/poller-architecture.PNG)


**Topics**
+ [Amazon Neptune에서 OpenSearch로 복제](full-text-search-cfn-setup.md)
+ [OpenSearch Serverless로 복제](full-text-search-serverless.md)
+ [세분화된 액세스 제어(FGAC)가 활성화된 OpenSearch 클러스터에서 쿼리](full-text-search-fgac.md)
+ [Neptune 전체 텍스트 검색 쿼리에서 Apache Lucene 쿼리 구문 사용](full-text-search-lucene.md)
+ [OpenSearch 데이터를 위한 Neptune 데이터 모델](full-text-search-model.md)
+ [Neptune 전체 텍스트 검색 파라미터](full-text-search-parameters.md)
+ [Amazon Neptune의 비문자열 OpenSearch 인덱싱](full-text-search-non-string-indexing.md)
+ [Amazon Neptune에서 전체 텍스트 검색 쿼리 실행](full-text-search-query-execution.md)
+ [Neptune에서 전체 텍스트 검색을 사용하는 샘플 SPARQL 쿼리](full-text-search-sparql-examples.md)
+ [Gremlin 쿼리에서 Neptune 전체 텍스트 검색 사용](full-text-search-gremlin.md)
+ [Neptune 전체 텍스트 검색 문제 해결](streams-consumer-troubleshooting.md)

# Amazon Neptune에서 OpenSearch로 복제
<a name="full-text-search-cfn-setup"></a>

Amazon Neptune은 Amazon OpenSearch Service(OpenSearch Service)를 사용하여 Gremlin 및 SPARQL 쿼리에서 전체 텍스트 검색을 지원합니다. AWS CloudFormation 스택을 사용하여 OpenSearch Service 도메인을 Neptune에 연결할 수 있습니다. CloudFormation 템플릿은 Neptune-to-OpenSearch 복제를 제공하는 스트림 소비자 애플리케이션 인스턴스를 생성합니다.

시작하기 전에 소스로 사용할 스트림이 활성화된 기존 Neptune DB 클러스터와 복제 대상으로 사용할 OpenSearch Service 도메인이 필요합니다.

Neptune DB 클러스터가 있는 VPC에서 Lambda에 의해 액세스할 수 있는 기존 대상 OpenSearch Service 도메인이 이미 있는 경우 템플릿에서 해당 도메인을 사용할 수 있습니다. 그렇지 않으면 새로 만들어야 합니다.

**참고**  
생성하는 OpenSearch 클러스터 및 Lambda 함수는 Neptune DB 클러스터와 동일한 VPC에 있어야 하며, OpenSearch 클러스터는 인터넷 모드가 아닌 VPC 모드에서 구성되어야 합니다.

새로 만든 Neptune 인스턴스를 활용하여 OpenSearch Service와 함께 사용하는 것이 좋습니다. 데이터가 이미 들어 있는 기존 인스턴스를 사용하는 경우 쿼리하기 전에 OpenSearch Service 데이터 동기화를 수행해야 합니다. 그렇지 않으면 데이터 불일치가 발생할 수 있습니다. 이 GitHub 프로젝트는 [Neptune을 OpenSearch로 내보내기](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch)(https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch)에서 동기화를 수행하는 방법의 예를 제공합니다.

**중요**  
Amazon OpenSearch Service와 통합할 때 Neptune은 Elasticsearch 버전 7.1 이상이 필요하며, OpenSearch 2.3, 2.5 및 향후 호환 가능한 Opensearch 버전과 함께 사용할 수 있습니다.

**참고**  
[엔진 릴리스 1.3.0.0](engine-releases-1.3.0.0.md)부터 Amazon Neptune은 Gremlin 및 SPARQL 쿼리에서 전체 텍스트 검색을 위해 [Amazon OpenSearch Service Serverless](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless.html)를 사용할 수 있도록 지원합니다.

**Topics**
+ [AWS CloudFormation 템플릿을 사용하여 Neptune-to-OpenSearch 복제 시작](full-text-search-cfn-create.md)
+ [기존 Neptune 데이터베이스에서 전체 텍스트 검색 활성화](full-text-search-cfn-enabling.md)
+ [스트림 폴러 업데이트](full-text-search-cfn-update-poller.md)
+ [스트림 폴러 프로세스 비활성화 및 재활성화](full-text-search-using-pausing-poller.md)

# AWS CloudFormation 템플릿을 사용하여 Neptune-to-OpenSearch 복제 시작
<a name="full-text-search-cfn-create"></a>

## 리전별 CloudFormation 스택 시작
<a name="full-text-search-cfn-by-region"></a>

아래 각 CloudFormation 템플릿은 특정 AWS 리전에 스트림 소비자 애플리케이션 인스턴스를 생성합니다. CloudFormation 콘솔을 사용하여 해당 스택을 시작하려면 사용하려는 AWS 리전에 따라 다음 표의 **스택 시작** 버튼 중 하나를 선택합니다.


| 리전 | 보기 | Designer에서 보기 | 시작 | 
| --- | --- | --- | --- | 
| 미국 동부(버지니아 북부) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=us-east-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 미국 동부(오하이오) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=us-east-2&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 미국 서부(캘리포니아 북부) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=us-west-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=us-west-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=us-west-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 미국 서부(오리건) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=us-west-2&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 캐나다(중부) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=us-west-2&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ca-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ca-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 남아메리카(상파울루) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=sa-east-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=sa-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=sa-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 유럽(스톡홀름) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=eu-north-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=eu-north-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=eu-north-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 유럽(아일랜드) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=eu-west-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 유럽(런던) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=eu-west-2&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=eu-west-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=eu-west-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 유럽(파리) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=eu-west-3&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=eu-west-3#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=eu-west-3#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 유럽(스페인) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=eu-south-2&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=eu-south-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=eu-south-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 유럽(프랑크푸르트) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=eu-central-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| Middle East (Bahrain) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=me-south-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=me-south-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=me-south-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 중동(UAE) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=me-central-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=me-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=me-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 이스라엘(텔아비브) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=il-central-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=il-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=il-central-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아프리카(케이프타운) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=af-south-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=af-south-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=af-south-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아시아 태평양(홍콩) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=ap-east-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ap-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ap-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아시아 태평양(도쿄) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=ap-northeast-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아시아 태평양(서울) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=ap-northeast-2&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-2#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아시아 태평양(싱가포르) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=ap-southeast-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아시아 태평양(자카르타) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=ap-southeast-3&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-3#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ap-southeast-3#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 아시아 태평양(뭄바이) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.aws.amazon.com/cloudformation/designer/home?region=ap-south-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.aws.amazon.com/cloudformation/home?region=ap-south-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.aws.amazon.com/cloudformation/home?region=ap-south-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 중국(베이징) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.amazonaws.cn/cloudformation/designer/home?region=cn-north-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.amazonaws.cn/cloudformation/home?region=cn-north-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.amazonaws.cn/cloudformation/home?region=cn-north-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| 중국(닝샤) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.amazonaws.cn/cloudformation/designer/home?region=cn-northwest-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.amazonaws.cn/cloudformation/home?region=cn-northwest-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.amazonaws.cn/cloudformation/home?region=cn-northwest-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| AWS GovCloud(미국 서부) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.amazonaws-us-gov.com/cloudformation/designer/home?region=us-gov-west-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.amazonaws-us-gov.com/cloudformation/home?region=us-gov-west-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.amazonaws-us-gov.com/cloudformation/home?region=us-gov-west-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 
| AWS GovCloud(미국 동부) | [보기](https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [Designer에서 보기](https://console.amazonaws-us-gov.com/cloudformation/designer/home?region=us-gov-east-1&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json) | [https://console.amazonaws-us-gov.com/cloudformation/home?region=us-gov-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json](https://console.amazonaws-us-gov.com/cloudformation/home?region=us-gov-east-1#/stacks/new?stackName=NeptuneQuickStart&templateURL=https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json)  | 

**스택 생성** 페이지에서 **다음**을 선택합니다.

## 생성 중인 새 OpenSearch 스택에 대한 세부 정보 추가
<a name="full-text-search-cfn-stack-details"></a>

**스택 세부 정보 지정** 페이지에서는 전체 텍스트 검색 설정을 제어하는 데 사용할 수 있는 속성 및 파라미터를 제공합니다.

**스택 이름** -  생성 중인 새 CloudFormation 스택의 이름입니다. 대개 기본값(`NeptuneStreamPoller`)을 사용합니다.

**파라미터**에서 다음을 제공합니다.

**스트림 소비자가 실행되는 VPC의 네트워크 구성**
+ **`VPC`** –  폴링 Lambda 함수가 실행될 VPC의 이름을 제공합니다.
+ **`List of Subnet IDs`** –  네트워크 인터페이스가 설정된 서브넷입니다. Neptune 클러스터에 해당하는 서브넷을 추가합니다.
+ **`List of Security Group Ids`** –  소스 Neptune DB 클러스터에 대한 쓰기 인바운드 액세스 권한을 부여하는 보안 그룹의 ID를 제공합니다.
+ **`List of Route Table Ids`** –  아직 Amazon DynamoDB 엔드포인트가 없는 경우 Neptune VPC에서 엔드포인트를 생성할 때 필요합니다. 서브넷과 연결된 라우팅 테이블 ID를 쉼표로 분리한 목록을 제공해야 합니다.
+ **`Require to create Dynamo DB VPC Endpoint`** –  기본값이 `true`인 부울 값입니다. VPC에 DynamoDB 엔드포인트를 이미 생성한 경우에만 이를 `false`로 변경하면 됩니다.
+ **`Require to create Monitoring VPC Endpoint`** –  기본값이 `true`인 부울 값입니다. VPC에 모니터링 엔드포인트를 이미 생성한 경우에만 이를 `false`로 변경하면 됩니다.

**스트림 폴러**
+ **`Application Name`** –  이 설정은 대개 기본값(`NeptuneStream`)으로 둡니다. 다른 이름을 사용하는 경우 고유한 이름이어야 합니다.
+ **`Memory size for Lambda Poller`** –  Lambda 폴러 함수에 사용 가능한 메모리 크기를 설정하는 데 사용됩니다. 기본값은 2,048MB입니다.
+ **`Lambda Runtime`** –  Neptune 스트림에서 항목을 검색하는 Lambda 함수에서 사용되는 언어입니다. `python3.9` 또는 `java8`로 설정할 수 있습니다.
+ **`S3 Bucket having Lambda code artifacts`** –  다른 S3 버킷에서 로드하는 사용자 지정 Lambda 폴링 함수를 사용하지 않는 경우 비워둡니다.
+ **`S3 Key corresponding to Lambda Code artifacts`** –  사용자 지정 Lambda 폴링 함수를 사용하지 않는 경우 비워둡니다.
+ **`StartingCheckpoint`** –  스트림 폴러의 시작 체크포인트입니다. 기본값은 `0:0`이며, Neptune 스트림의 시작 부분부터 쓸 수 있음을 의미합니다.
+ **`StreamPollerInitialState`** –  폴러의 초기 상태입니다. 기본값은 `ENABLED`이며, 전체 스택 생성이 완료되는 즉시 스트림 복제가 시작됩니다.
+ **`Logging level for Lambda`** –  이 설정은 대개 기본값(`INFO`)으로 둡니다.
+ **`Managed Policies for Lambda Execution`** –  일반적으로 사용자 지정 Lambda 폴링 함수를 사용하지 않는 경우 비워둡니다.
+ **`Stream Records Handler`** –  일반적으로 Neptune 스트림의 레코드에 사용자 지정 핸들러를 사용하지 않는 경우 비워둡니다.
+ **`Maximum records Fetched from Stream`** –  이 파라미터를 사용하여 성능을 조정할 수 있습니다. 기본값(`100`)으로 시작하는 것이 좋습니다. 허용되는 최대값은 10,000입니다. 숫자가 높을수록 스트림에서 레코드를 읽는 데 필요한 네트워크 호출은 감소하지만 레코드를 처리하는 데 더 많은 메모리가 필요합니다.
+ **`Max wait time between two Polls (in Seconds)`** –  Neptune 스트림을 폴링하기 위해 Lambda 폴러가 호출되는 빈도를 결정합니다. 지속적으로 폴링하는 경우 이 값을 0으로 설정합니다. 최대값은 3,600초(1시간)입니다. 기본값(60초)으로 시작하는 것이 좋습니다(그래프 데이터의 변경 속도에 따라 달라짐).
+ **`Maximum Continuous polling period (in Seconds)`** –  Lambda 폴링 함수에 대한 제한 시간을 설정하는 데 사용됩니다. 이 값은 5초에서 900초 사이여야 합니다. 기본값(600초)으로 시작하는 것이 좋습니다.
+ **`Step Function Fallback Period`** –  장애를 복구하기 위해 Step Function이 Amazon CloudWatch Events를 통해 호출될 때까지 폴러가 대기할 step-function-fallback-period 단위 개수입니다. 기본값(5분)으로 시작하는 것이 좋습니다.
+ **`Step Function Fallback Period Unit`** –  위의 `Step Function Fallback Period`(분, 시간, 일)를 측정하는 데 사용되는 시간 단위입니다. 대개 기본값(분)이면 충분합니다.
+ **`Enable/disable creation of Elastic Search Mappings by Lambda`** -  스트림 폴러에 의한 Elastic Search 매핑의 자동 관리를 활성화/비활성화하는 플래그입니다. 탄력적 검색 매핑은 Neptune과 탄력적 검색 데이터 유형 간의 변환에 매우 중요합니다. 이는 Elastic Search 인덱스의 모든 매핑을 직접 수동으로 제어하려는 고급 사용자만 비활성화해야 합니다. 기본값은 `true`입니다.
+ **`Data replication scope`** –  노드와 엣지 둘 다 또는 노드만 OpenSearch로 복제할지 여부를 결정합니다(Gremlin 엔진 데이터에만 적용). 일반적으로 기본값(All)으로 시작하는 것이 좋습니다.
+ **`Ignore OpenSearch missing document error`** –  OpenSearch에서 누락된 문서 오류를 무시할 수 있는지 여부를 결정하는 플래그입니다. 누락된 문서 오류는 거의 발생하지 않지만, 무시하지 않으면 수동으로 개입해야 합니다. 일반적으로 기본값(`True`)으로 시작하는 것이 좋습니다.
+ **`Enable Non-String Indexing`** –  문자열 콘텐츠가 없는 필드의 인덱싱을 활성화하거나 비활성화하는 플래그입니다. 이 플래그를 `true`로 설정하면 OpenSearch에서 문자열이 아닌 필드가 인덱싱되고, `false`로 설정하면 문자열 필드만 인덱싱됩니다. 기본값은 `true`입니다.
+ **`Properties to exclude from being inserted into OpenSearch`** –  OpenSearch 인덱싱에서 제외할 속성 또는 조건부 키를 쉼표로 구분한 목록입니다. 이 CFN 파라미터 값을 비워두면 모든 속성 키가 인덱싱됩니다.
+ **`Datatypes to exclude from being inserted into OpenSearch`** –  OpenSearch 인덱싱에서 제외할 속성 또는 조건부 데이터 유형을 쉼표로 구분한 목록입니다. 이 CFN 파라미터 값을 비워두면 OpenSearch 데이터 유형으로 안전하게 변환할 수 있는 모든 속성 값이 인덱싱됩니다.

**Neptune 스트림**
+ **`Endpoint of source Neptune Stream`** –  (*필수*) 2가지 형식 중 하나를 취합니다.
  + **`https://your DB cluster:port/propertygraph/stream`**(또는 별칭 `https://your DB cluster:port/pg/stream`).
  + `https://your DB cluster:port/sparql/stream`
+ **`Neptune Query Engine`** –  Gremlin 또는 SPARQL을 선택합니다.
+ **`Is IAM Auth Enabled?`** –  Neptune DB 클러스터가 IAM 인증을 사용하는 경우 이 파라미터를 `true`로 설정합니다.
+ **`Neptune Cluster Resource Id`** –  Neptune DB 클러스터가 IAM 인증을 사용하는 경우 이 파라미터를 클러스터 리소스 ID로 설정합니다. 리소스 ID가 클러스터 ID와 동일하지 않습니다. 그 대신, `cluster-` 뒤에 28개의 영숫자 문자가 오는 형식을 사용합니다. Neptune 콘솔의 **클러스터 세부 정보**에서 찾을 수 있습니다.

**대상 OpenSearch 클러스터**
+ **`Endpoint for OpenSearch service`** –  (필수) VPC에서 OpenSearch 서비스를 위한 엔드포인트를 제공합니다.
+ **`Number of Shards for OpenSearch Index`** –  일반적으로 기본값(5)으로 시작하는 것이 좋습니다.
+ **`Number of Replicas for OpenSearch Index`** –  일반적으로 기본값(1)으로 시작하는 것이 좋습니다.
+ **`Geo Location Fields for Mapping`** –  지리 위치 필드를 사용하는 경우 여기에 속성 키가 나열됩니다.

**경보**
+ **`Require to create Cloud watch Alarm`** –  새 스택에 CloudWatch 경보를 생성하려면 이 필드를 `true`로 설정합니다.
+ **`SNS Topic ARN for Cloudwatch Alarm Notifications`**   –   CloudWatch 경보 알림을 전송해야 하는 SNS 주제 ARN입니다(경보가 활성화된 경우에만 필요).
+ **`Email for Alarm Notifications`** –  경보 알림을 전송해야 하는 이메일 주소입니다(경보가 활성화된 경우에만 필요).

경보 알림 대상으로는 SNS만 추가하거나, 이메일만 추가하거나, SNS와 이메일을 모두 추가할 수 있습니다.

## CloudFormation 템플릿 실행
<a name="full-text-search-cfn-complete"></a>

이제 다음과 같이 Neptune 스트림 소비자 애플리케이션 인스턴스를 프로비저닝하는 프로세스를 완료할 수 있습니다.

1.  CloudFormation의 **스택 세부 정보 지정** 페이지에서 **다음을** 선택합니다.

1. **옵션** 페이지에서 **다음**을 선택합니다.

1. **검토** 페이지에서 첫 번째 확인란을 선택하여 CloudFormation 이 IAM 리소스를 생성하는 것을 승인합니다. 두 번째 확인란을 선택하여 새 스택에 대해 `CAPABILITY_AUTO_EXPAND`를 승인합니다.
**참고**  
`CAPABILITY_AUTO_EXPAND`는 사전 검토 없이 스택을 생성할 경우 매크로가 확장됨을 명시적으로 승인합니다. 사용자는 실제로 스택을 생성하기 전에 매크로를 통한 변경 사항을 검토할 수 있도록 처리된 템플릿에서 변경 세트를 생성하는 경우가 많습니다. 자세한 내용은 API 참조의 CloudFormation [CreateStack](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html) *AWS CloudFormation API 작업을 참조*하세요.

   그런 다음 **생성**을 선택합니다.

# 기존 Neptune 데이터베이스에서 전체 텍스트 검색 활성화
<a name="full-text-search-cfn-enabling"></a>

 이는 기존 Amazon Neptune 데이터베이스에서 전체 텍스트 검색을 활성화하기 위해 확립된 접근 방식입니다. 쓰기 워크로드를 일시 중지할 수 있는지 여부에 따라 단계가 약간 다를 수 있습니다. 이 설명서에서는 쓰기를 일시 중지할 수 있는 경우와 일시 중지할 수 없는 경우의 두 시나리오에 대한 권장 단계를 간략하게 설명합니다. 여기에는 Neptune 스트림 활성화, 데이터베이스 복제본 생성, OpenSearch 도메인에 데이터 동기화, 지속적 업데이트 설정이 포함됩니다. 이 지침은 AWS 서비스 및 오픈 소스 도구를 활용하여 프로세스를 간소화하고 가동 중지 시간을 최소화합니다.

## 쓰기 워크로드를 일시 중지할 수 있는 경우
<a name="full-text-search-cfn-enabling-with-pause"></a>

기존 Neptune 데이터베이스에서 전체 텍스트 검색을 활성화하는 가장 좋은 방법은 쓰기 워크로드를 일시 중지할 수 있는 경우 일반적으로 다음과 같습니다. 복제본을 생성하고, 클러스터 파라미터를 사용하여 스트림을 활성화하고, 모든 인스턴스를 다시 시작해야 합니다. 복제본 생성은 비교적 빠른 작업이므로, 필요한 가동 중지 시간이 제한됩니다.

필수 단계는 다음과 같습니다.

1. 데이터베이스의 모든 쓰기 워크로드를 중지합니다.

1. 데이터베이스에서 스트림을 활성화합니다([Neptune 스트림 활성화](streams-using-enabling.md) 참조).

1. 데이터베이스의 복제본을 생성합니다([Neptune의 데이터베이스 복제](manage-console-cloning.md) 참조).

1. 쓰기 워크로드를 재개합니다.

1. Github의 [export-neptune-to-elasticsearch](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch) 도구를 사용하여 복제된 데이터베이스를 OpenSearch 도메인으로 한 번에 동기화할 수 있습니다.

1. 사용 중인 리전의 [CloudFormation 템플릿](https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-cfn-create.html#full-text-search-cfn-by-region)을 이용하여 지속적인 업데이트로 원본 데이터베이스에서 동기화를 시작할 수 있습니다. 템플릿에서 구성을 변경할 필요가 없습니다.

1. 복제된 데이터베이스와 `export-neptune-to-elasticsearch` 도구에 대해 생성된 CloudFormation 스택을 삭제합니다.

**참고**  
Opensearch Serverless에서 [export-neptune-to-elasticsearch](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch)를 사용하는 경우 데이터를 성공적으로 복제하려면 [export-neptune-to-elasticsearch](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch) Cloudformation 스택에서 `LambdaExecutionRole` 생성된를 [Opensearch 데이터 액세스 정책에](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-data-access.html) 추가해야 합니다.

## 쓰기 워크로드를 일시 중지할 수 없는 경우
<a name="full-text-search-cfn-enabling-without-pause"></a>

데이터베이스의 쓰기 워크로드를 일시 중단할 여유가 없는 경우 위의 권장 접근 방식보다 가동 중지 시간이 훨씬 적지만, 신중하게 수행해야 하는 전략을 취해야 합니다.

1. 데이터베이스에서 스트림을 활성화합니다([Neptune 스트림 활성화](streams-using-enabling.md) 참조).

1. 데이터베이스의 복제본을 생성합니다([Neptune의 데이터베이스 복제](manage-console-cloning.md) 참조).

1. 스트림 API 엔드포인트에 대해 다음과 같은 종류의 명령을 실행하여 복제된 데이터베이스의 스트림에서 최신 `eventID`를 가져옵니다(자세한 내용은 [Neptune 스트림 REST API 호출](streams-using-api-call.md) 참조).

   ```
   curl "https://(your neptune endpoint):(port)/(propertygraph or sparql)/stream?iteratorType=LATEST"
   ```

   응답에서 `lastEventId` 객체의 `commitNum` 및 `opNum` 필드 값을 기록해 둡니다.

1. Github의 [export-neptune-to-elasticsearch](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch) 도구를 사용하여 복제된 데이터베이스를 OpenSearch 도메인으로 한 번에 동기화할 수 있습니다.

1. 사용 중인 리전의 [CloudFormation 템플릿](https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-cfn-create.html#full-text-search-cfn-by-region)을 이용하여 지속적인 업데이트로 원본 데이터베이스에서 동기화를 시작합니다.

   스택을 생성하는 동안 다음과 같이 변경하세요. 스택 세부 정보 페이지의 **파라미터** 섹션에서 앞서 기록한 `commitNum` 및 `opNum` 값을 사용하여 `StartingCheckpoint` 필드의 값을 **commitNum**:**opnum**으로 설정합니다.

1. 복제된 데이터베이스와 `export-neptune-to-elasticsearch` 도구에 대해 생성된 CloudFormation 스택을 삭제합니다.

# 스트림 폴러 업데이트
<a name="full-text-search-cfn-update-poller"></a>

 다음 정보는 AWS 관리 콘솔을 사용하여 스트림 폴러를 최신 Lambda 아티팩트로 업데이트하는 데 필요한 단계를 간략하게 설명합니다.

## 최신 Lambda 아티팩트로 스트림 폴러를 업데이트하려면
<a name="full-text-search-cfn-update-poller-lambda"></a>

다음과 같이 최신 Lambda 코드 아티팩트로 스트림 폴러를 업데이트할 수 있습니다.

1. 에서 기본 상위 CloudFormation 스택으로 AWS Management Console이동하여 CloudFormation 선택합니다.

1. 스택의 **업데이트** 옵션을 선택합니다.

1. **현재 템플릿 교체**를 선택합니다.

1. 템플릿 소스에서 **Amazon S3 URL**을 선택하고 다음 S3 URL을 입력합니다.

   ```
   https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json
   ```

1.  CloudFormation 파라미터를 변경하지 않고 **다음을** 선택합니다.

1. **스택 업데이트**를 선택합니다.

스택이 이제 Lambda 아티팩트를 최신 아티팩트로 업데이트합니다.

## 사용자 지정 필드를 지원하도록 스트림 폴러 확장
<a name="full-text-search-using-custom-fields"></a>

현재 스트림 폴러는 사용자 지정 필드를 처리하기 위한 사용자 지정 코드를 작성하도록 쉽게 확장할 수 있습니다. 자세한 내용은 블로그 게시물 [Neptune 스트림을 사용하여 그래프 변경 사항 캡처](https://aws.amazon.com/blogs/database/capture-graph-changes-using-neptune-streams/)에 설명되어 있습니다.

**참고**  
OpenSearch에서 사용자 지정 필드를 추가할 때는 새 필드를 조건자의 내부 객체로 추가해야 합니다([Neptune 전체 텍스트 검색 데이터 모델](full-text-search-model.md) 참조).

# 스트림 폴러 프로세스 비활성화 및 재활성화
<a name="full-text-search-using-pausing-poller"></a>

**주의**  
스트림 폴러 프로세스를 비활성화할 때는 주의하세요\$1 스트림 만료 기간보다 오래 프로세스를 일시 중지하면 데이터 손실이 발생할 수 있습니다. 기본 기간은 7일이지만, 엔진 버전 [1.2.0.0](engine-releases-1.2.0.0.md)부터 사용자 지정 스트림 만료 기간을 최대 90일까지 설정할 수 있습니다.

# 스트림 폴러 프로세스 비활성화(일시 중지)
<a name="full-text-search-pause-poller"></a>

1. 에 로그인 AWS Management Console 하고 [https://console.aws.amazon.com/events/](https://console.aws.amazon.com/events/) Amazon EventBridge 콘솔을 엽니다.

1. 탐색 창에서 **규칙**을 선택합니다.

1. 스트림 폴러를 설정하는 데 사용한 CloudFormation 템플릿에서 이름이 **애플리케이션 이름으로** 제공한 이름을 포함하는 규칙을 선택합니다.

1. **비활성화**를 선택합니다.

1. [https://console.aws.amazon.com/states/](https://console.aws.amazon.com/states/)에서 Step Functions 콘솔을 엽니다.

1. 스트림 폴러 프로세스에 해당하는 실행 중인 Step Function을 선택합니다. 다시 말하지만, 해당 단계 함수의 이름에는 스트림 폴러를 설정하는 데 사용한 CloudFormation 템플릿에 **애플리케이션 이름으로** 제공한 이름이 포함됩니다. 함수 실행 상태별로 필터링하여 **실행 중인** 함수만 볼 수 있습니다.

1. **중지**를 선택합니다.

# 스트림 폴러 프로세스 재활성화
<a name="full-text-search-re-enable-poller"></a>

1. 에 로그인 AWS Management Console 하고 [https://console.aws.amazon.com/events/](https://console.aws.amazon.com/events/) Amazon EventBridge 콘솔을 엽니다.

1. 탐색 창에서 **규칙**을 선택합니다.

1. 스트림 폴러를 설정하는 데 사용한 CloudFormation 템플릿에서 이름이 **애플리케이션 이름으로** 제공한 이름을 포함하는 규칙을 선택합니다.

1. **활성화**를 선택합니다. 지정된 스케줄 간격을 기반으로 하는 이벤트 규칙이 이제 Step Function의 새 실행을 트리거합니다.

# OpenSearch Serverless로 복제
<a name="full-text-search-serverless"></a>

[엔진 릴리스 1.3.0.0](engine-releases-1.3.0.0.md)부터 Amazon Neptune은 Gremlin 및 SPARQL 쿼리에서 전체 텍스트 검색을 위해 [Amazon OpenSearch Service Serverless](https://docs.aws.amazon.com//opensearch-service/latest/developerguide/serverless.html)를 사용할 수 있도록 지원합니다. OpenSearch Serverless를 사용하려면 Neptune 데이터베이스 클러스터에서 [IAM 인증을 활성화](https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth-enable.html)해야 합니다. IAM 인증이 비활성화된 Neptune 데이터베이스 클러스터는 OpenSearch Serverless에서 지원되지 않습니다.

## 폴러 AWS Lambda 함수에 필요한 변경 사항
<a name="full-text-changes-required"></a>

OpenSearch Serverless로 복제하는 경우 Lambda 스트림 폴러 실행 역할을 OpenSearch Serverless 컬렉션의 데이터 액세스 정책에 추가합니다. Lambda 스트림 폴러 실행 역할에 대한 ARN의 형식은 다음과 같습니다.

```
arn:aws:iam::(account ID):role/stack-name-NeptuneOSReplication-NeptuneStreamPollerExecu-(uuid)
```

## 대량 가져오기 유틸리티에 필요한 변경 사항
<a name="full-text-changes-bulk-import"></a>

 [export-neptune-to-elasticsearch](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch)를 사용하여 기존 데이터를 OpenSearch Serverless와 동기화하는 경우 CloudFormation 스택의 `LambdaExecutionRole`을 OpenSearch Serverless 컬렉션의 데이터 액세스 정책에 추가합니다. `LambdaExecutionRole`의 ARN 형식은 다음과 같습니다.

```
arn:aws:iam::012345678901:role/stack-name-LambdaExecutionRole-(id)
```

자세한 내용은 [Amazon OpenSearch Serverless를 위한 데이터 액세스 제어](https://docs.aws.amazon.com//opensearch-service/latest/developerguide/serverless-data-access.html)를 참조하세요.

## Neptune 쿼리에 사용되는 IAM 역할에 필요한 변경 사항
<a name="full-text-IAM"></a>

Neptune 데이터베이스에 연결하는 데 사용되는 IAM 엔터티(사용자 또는 역할)에는 Neptune과 OpenSearch Serverless 컬렉션 모두에 대한 권한이 있어야 합니다. 즉, 사용자 또는 역할에 다음과 같은 OpenSearch Serverless 정책이 연결되어 있어야 합니다.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowOpenSearchServerlessAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "aoss:APIAccessAll",
      "Resource": "arn:aws:aoss:us-east-1:111122223333:collection/collection-id"
    }
  ]
}
```

------

자세한 내용은 [Amazon Neptune의 데이터에 액세스하기 위한 사용자 지정 IAM 정책문 생성](iam-data-access-policies.md)를 참조하세요.

# 세분화된 액세스 제어(FGAC)가 활성화된 OpenSearch 클러스터에서 쿼리
<a name="full-text-search-fgac"></a>

OpenSearch 클러스터에서 [세분화된 액세스 제어](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html)를 활성화한 경우 Neptune 데이터베이스에서도 [IAM 인증을 활성화](iam-auth-enable.md)해야 합니다.

Neptune 데이터베이스에 연결하는 데 사용되는 IAM 엔터티(사용자 또는 역할)에는 Neptune과 OpenSearch 클러스터 모두에 대한 권한이 있어야 합니다. 즉, 사용자 또는 역할에 다음과 같은 OpenSearch Service 정책이 연결되어 있어야 합니다.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowFullTextSearchAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:root"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-east-1:111122223333:domain/domain-name/*"
    }
  ]
}
```

------

자세한 내용은 [Amazon Neptune의 데이터에 액세스하기 위한 사용자 지정 IAM 정책문 생성](iam-data-access-policies.md)를 참조하세요.

# Neptune 전체 텍스트 검색 쿼리에서 Apache Lucene 쿼리 구문 사용
<a name="full-text-search-lucene"></a>

OpenSearch는 query\$1string 쿼리에 [Apache Lucene 구문](https://lucene.apache.org/core/8_9_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description) 사용을 지원합니다. 이는 쿼리에서 여러 필터를 전달하는 데 특히 유용합니다.

Neptune은 중첩 구조를 사용하여 OpenSearch 문서에 속성을 저장합니다([Neptune 전체 텍스트 검색 데이터 모델](full-text-search-model.md) 참조). Lucene 구문을 사용할 때는 이 중첩된 모델의 속성에 대한 전체 경로를 사용해야 합니다.

다음은 Gremlin 예제입니다.

```
g.withSideEffect("Neptune#fts.endpoint", "es_endpoint")
 .withSideEffect("Neptune#fts.queryType", "query_string")
 .V()
 .has("*", "Neptune#fts predicates.name.value:\"Jane Austin\" AND entity_type:Book")
```

다음은 SPARQL 예제입니다.

```
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
  neptune-fts:config neptune-fts:endpoint 'http://localhost:9200 (http://localhost:9200/)' .
  neptune-fts:config neptune-fts:queryType 'query_string' .
  neptune-fts:config neptune-fts:query "predicates.\\*foaf\\*name.value:Ronak AND predicates.\\*foaf\\*surname.value:Sh*" .
  neptune-fts:config neptune-fts:field '*' .
  neptune-fts:config neptune-fts:return ?res .
}
```

# OpenSearch 데이터를 위한 Neptune 데이터 모델
<a name="full-text-search-model"></a>

Amazon Neptune에서는 통합 JSON 문서 구조를 사용하여 SPARQL 및 Gremlin 데이터 둘 모두 OpenSearch Service에 저장합니다. OpenSearch의 각 문서는 엔터티에 해당하며 해당 엔터티에 대한 모든 관련 정보를 저장합니다. Gremlin의 경우 버텍스 및 엣지가 엔터티로 간주되므로, 해당 OpenSearch 문서에 버텍스, 레이블 및 속성에 대한 정보가 있습니다. SPARQL의 경우 주체가 엔터티로 간주될 수 있으므로, 해당 OpenSearch 문서에 한 문서의 모든 조건자-객체 페어에 대한 정보가 있습니다.

**참고**  
Neptune에서 OpenSearch로의 복제 구현은 문자열 데이터만 저장합니다. 하지만 다른 데이터 유형을 저장하도록 수정할 수 있습니다.

통합 JSON 문서 구조는 다음과 같습니다.

```
{
  "entity_id": "Vertex Id/Edge Id/Subject URI",
  "entity_type": [List of Labels/rdf:type object value],
  "document_type": "vertex/edge/rdf-resource"
  "predicates": {
    "Property name or predicate URI": [
      {
        "value": "Property Value or Object Value",
        "graph": "(Only for Sparql) Named Graph Quad is present"
        "language": "(Only for Sparql) rdf:langString"
      },
      {
        "value": "Property Value 2/ Object Value 2",
      }
    ]
  }
}
```

****
+ `entity_id` – 문서를 나타내는 엔터티 고유 ID입니다.
  + SPARQL의 경우, 이는 주체 URI입니다.
  + Gremlin의 경우, 이는 `Vertex_ID` 또는 `Edge_ID`입니다.
+ `entity_type` – 버텍스 또는 엣지에 대한 하나 이상의 레이블 또는 주체에 대한 0개 이상의 `rdf:type` 조건자 값을 나타냅니다.
+ `document_type` – 현재 문서가 버텍스, 엣지 또는 rdf-리소스를 나타내는지 여부를 지정하는 데 사용됩니다.
+ `predicates` – Gremlin의 경우, 버텍스 또는 엣지에 대한 속성 및 값을 저장합니다. SPARQL의 경우, 조건자-객체 페어를 저장합니다.

  속성 이름은 OpenSearch에서 `properties.name.value` 형식을 따릅니다. 쿼리하려면 해당 양식으로 이름을 지정해야 합니다.
+ `value ` – Gremlin에 대한 속성 값 또는 SPARQL에 대한 객체 값입니다.
+ `graph` – SPARQL에 대한 명명된 그래프입니다.
+ `language` – SPARQL의 `rdf:langString` 리터럴에 대한 언어 태그입니다.

## 샘플 SPARQL OpenSearch 문서
<a name="full-text-search-model-sparql-example"></a>

**Data**

```
@prefix dt:   <http://example.org/datatype#> .
@prefix ex:   <http://example.org/> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

ex:simone   rdf:type     ex:Person                    ex:g1
ex:michael  rdf:type     ex:Person                    ex:g1
ex:simone   ex:likes     "spaghetti"                  ex:g1

ex:simone   ex:knows     ex:michael                   ex:g2   # Not stored in ES
ex:simone   ex:likes     "spaghetti"                  ex:g2
ex:simone   ex:status    "La vita è un sogno"@it      ex:g2

ex:simone   ex:age       "40"^^xsd:int                DG      # Not stored in ES
ex:simone   ex:dummy     "testData"^^dt:newDataType   DG      # Not stored in ES
ex:simone   ex:hates     _:bnode                              # Not stored in ES
_:bnode     ex:means     "coding"                     DG      # Not stored in ES
```

**문서**

```
{
  "entity_id": "http://example.org/simone",
  "entity_type": ["http://example.org/Person"],
  "document_type": "rdf-resource"
  "predicates": {
    "http://example.org/likes": [
      {
        "value": "spaghetti",
        "graph": "http://example.org/g1"
      },
      {
        "value": "spaghetti",
        "graph": "http://example.org/g2"
      }
    ]
    "http://example.org/status": [
      {
        "value": "La vita è un sogno",
        "language": "it"       // Only present for rdf:langString
      }
    ]
  }
}
```

```
{
  "entity_id" : "http://example.org/michael",
  "entity_type" : ["http://example.org/Person"],
  "document_type": "rdf-resource"
}
```

## 샘플 Gremlin OpenSearch 문서
<a name="full-text-search-model-gremlin-example"></a>

**Data**

```
# Vertex 1
simone   label    Person       <== Label
simone   likes    "spaghetti"  <== Property
simone   likes    "rice"       <== Property
simone   age      40           <== Property

# Vertex 2
michael  label    Person       <== Label

# Edge 1
simone  knows     michael      <== Edge
e1      updated  "2019-07-03"  <== Edge Property
e1      through  "company"     <== Edge Property
e1      since     10           <== Edge Property
```

** 문서**

```
{
  "entity_id": "simone",
  "entity_type": ["Person"],
  "document_type": "vertex",
  "predicates": {
    "likes": [
      {
        "value": "spaghetti"
      },
      {
        "value": "rice"
      }
    ]
  }
}
```

```
{
  "entity_id" : "michael",
  "entity_type" : ["Person"],
  "document_type": "vertex"
}
```

```
{
  "entity_id": "e1",
  "entity_type": ["knows"],
  "document_type": "edge"
  "predicates": {
    "through": [
      {
        "value": "company"
      }
    ]
  }
}
```

# Neptune 전체 텍스트 검색 파라미터
<a name="full-text-search-parameters"></a>

Amazon Neptune은 Gremlin과 SPARQL 모두에서 전체 텍스트 OpenSearch 쿼리를 지정하기 위해 다음 파라미터를 사용합니다.
+ **`queryType`**   –   (*필수*) OpenSearch 쿼리 유형입니다. (쿼리 유형 목록은 [OpenSearch 설명서](https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html)를 참조하세요.) Neptune에서는 다음 OpenSearch 쿼리 유형을 지원합니다.
  + [simple\$1query\$1string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html)   –   제한적이지만, 내결함성 Lucene 구문을 사용하는 파서를 통해 제공된 쿼리 문자열을 기준으로 문서를 반환합니다. 이것이 기본 쿼리 유형입니다.

    이 쿼리는 특수 연산자를 기준으로 간단한 구문을 사용하여 제공된 쿼리 문자열을 구문 분석하고 단어로 분할합니다. 그런 다음 쿼리는 일치하는 문서를 반환하기 전에 각 단어를 개별적으로 분석합니다.

    구문이 `query_string` 쿼리보다 제한적이지만 `simple_query_string` 쿼리는 잘못된 구문에 대한 오류를 반환하지 않습니다. 대신에 쿼리 문자열의 잘못된 부분을 무시합니다.
  + [match](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html)   –   `match` 쿼리는 퍼지 일치 옵션을 포함하여 전체 텍스트 검색을 수행하기 위한 표준 쿼리입니다.
  + [prefix](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html)   –   제공된 필드에서 특정 접두사가 포함된 문서를 반환합니다.
  + [fuzzy](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html)   –   Levenshtein 편집 거리로 측정한 검색 단어와 유사한 단어가 포함된 문서를 반환합니다.

    편집 거리는 한 단어를 다른 단어로 바꾸는 데 필요한 한 문자의 변경 횟수입니다. 이러한 변경에는 다음 사항이 포함될 수 있습니다.
    + 문자 변경(예: box를 fox로 수정)
    + 문자 제거(예: black을 lack으로 수정)
    + 문자 삽입(예: sic을 sick으로 수정)
    + 인접한 두 문자 전치(예: act를 cat으로 수정)

    유사한 단어를 찾기 위해 fuzzy 쿼리는 지정된 편집 거리 내에서 검색 단어의 가능한 모든 변형 및 확장 집합을 만든 다음 각 변형에 대해 정확히 일치하는 항목을 반환합니다.
  + [term](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html)   –   지정된 필드 중 하나에서 지정된 단어와 정확히 일치하는 항목이 포함된 문서를 반환합니다.

    `term` 쿼리를 사용하여 가격, 제품 ID 또는 사용자 이름과 같은 정확한 값을 기준으로 문서를 찾을 수 있습니다.
**주의**  
텍스트 필드에서는 term 쿼리를 사용하지 마십시오. 기본적으로 OpenSearch는 분석의 일부로 텍스트 필드의 값을 변경하므로, 텍스트 필드 값과 정확히 일치하는 항목을 찾기가 어려울 수 있습니다.  
텍스트 필드 값을 검색하려면 match 쿼리를 대신 사용합니다.
  + [query\$1string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html)   –   엄격한 구문(Lucene 구문)을 사용하는 파서를 통해 제공된 쿼리 문자열을 기준으로 문서를 반환합니다.

    이 쿼리는 AND 또는 NOT과 같은 연산자를 기준으로 구문을 사용하여 제공된 쿼리 문자열을 구문 분석하고 분할합니다. 그런 다음 쿼리는 일치하는 문서를 반환하기 전에 각 분할된 텍스트를 개별적으로 분석합니다.

    `query_string` 쿼리를 사용하여 와일드카드 문자, 여러 필드에서 검색 등을 포함하는 복잡한 검색을 만들 수 있습니다. 다목적 쿼리이지만 엄격하며 쿼리 문자열에 잘못된 구문이 포함되어 있으면 오류를 반환합니다.
**주의**  
잘못된 구문에 대해 오류를 반환하므로 검색 상자에서 `query_string` 쿼리를 사용하지 않는 것이 좋습니다.  
쿼리 구문을 지원할 필요가 없는 경우 `match` 쿼리 사용을 고려합니다. 쿼리 구문의 기능이 필요한 경우 덜 엄격한 `simple_query_string` 쿼리를 사용합니다.
+ **`field`**   –   검색을 실행할 OpenSearch의 필드입니다. 이는 `queryType` 및 `simple_query_string`과 마찬가지로 `query_string`이 허용하는 경우에만 생략할 할 수 있으며, 이 경우 검색은 모든 필드에 대해 이루어집니다. Gremlin에서는 암시적입니다.

  `simple_query_string` 및 `query_string`과 마찬가지로 쿼리가 허용하는 경우 여러 필드를 지정할 수 있습니다.
+ **`query`**   –   (*필수*) OpenSearch에 대해 실행할 쿼리입니다. 이 필드의 내용은 queryType에 따라 달라질 수 있습니다. queryTypes마다 다른 구문을 사용합니다(예: `Regexp`). Gremlin에서 `query`는 암시적입니다.
+ **`maxResults`**   –   반환할 최대 결과 수입니다. 기본값은 `index.max_result_window` OpenSearch 설정(기본값: 10,000)입니다. `maxResults` 파라미터는 이보다 작은 수를 지정할 수 있습니다.
**중요**  
`maxResults`를 OpenSearch `index.max_result_window` 값보다 높은 값으로 설정하고 `index.max_result_window` 결과보다 더 많이 검색하려고 시도하면 `Result window is too large` 오류가 발생하여 OpenSearch가 실패합니다. 하지만 Neptune에서는 이러한 경우 오류를 전파하지 않고 정상적으로 처리합니다. `index.max_result_window` 결과보다 더 많이 가져오려고 시도하는 경우 이 점에 유의하십시오.
+ **`minScore`**   –   검색 결과를 반환해야 하는 최소 점수입니다. 결과 점수에 대한 설명은 [OpenSearch 관련성 설명서](https://www.elastic.co/guide/en/elasticsearch/guide/current/scoring-theory.html)를 참조하세요.
+ **`batchSize`**   –   Neptune은 데이터를 항상 배치(batch)로 가져옵니다(기본 배치 크기: 100). 이 파라미터를 사용하여 성능을 조정할 수 있습니다. 배치 크기는 `index.max_result_window` OpenSearch 설정(기본값: 10,000)을 초과할 수 없습니다.
+ **`sortBy`**   –   OpenSearch에서 반환된 결과를 다음 중 하나로 정렬할 수 있는 선택적 파라미터입니다.
  + *문서의 특정 문자열 필드*   –  

    예를 들어 SPARQL 쿼리에서 다음을 지정할 수 있습니다.

    ```
        neptune-fts:config neptune-fts:sortBy foaf:name .
    ```

    유사한 Gremlin 쿼리에서 다음을 지정할 수 있습니다.

    ```
        .withSideEffect('Neptune#fts.sortBy', 'name')
    ```
  + *문서의 특정 비문자열 필드(`long`, `double` 등)*   –  

    비문자열 필드를 정렬할 때는 필드 이름에 `.value`를 추가하여 문자열 필드와 구분해야 합니다.

    예를 들어 SPARQL 쿼리에서 다음을 지정할 수 있습니다.

    ```
        neptune-fts:config neptune-fts:sortBy foaf:name.value .
    ```

    유사한 Gremlin 쿼리에서 다음을 지정할 수 있습니다.

    ```
        .withSideEffect('Neptune#fts.sortBy', 'name.value')
    ```
  + `score`   –   일치 점수를 기준으로 정렬합니다(기본값).

    `sortOrder` 파라미터가 있지만 `sortBy`는 없는 경우 결과는 `score`에 지정된 순서대로 `sortOrder`에 의해 정렬됩니다.
  + `id`   –   SPARQL 주체 URI나 Gremlin 버텍스 또는 엣지 ID를 의미하는 ID를 기준으로 정렬합니다.

    예를 들어 SPARQL 쿼리에서 다음을 지정할 수 있습니다.

    ```
        neptune-fts:config neptune-fts:sortBy 'Neptune#fts.entity_id' .
    ```

    유사한 Gremlin 쿼리에서 다음을 지정할 수 있습니다.

    ```
        .withSideEffect('Neptune#fts.sortBy', 'Neptune#fts.entity_id')
    ```
  + `label`   –   레이블을 기준으로 정렬합니다.

    예를 들어 SPARQL 쿼리에서 다음을 지정할 수 있습니다.

    ```
        neptune-fts:config neptune-fts:sortBy 'Neptune#fts.entity_type' .
    ```

    유사한 Gremlin 쿼리에서 다음을 지정할 수 있습니다.

    ```
        .withSideEffect('Neptune#fts.sortBy', 'Neptune#fts.entity_type')
    ```
  + `doc_type`   –   문서 유형(즉 SPARQL 또는 Gremlin)을 기준으로 정렬합니다.

    예를 들어 SPARQL 쿼리에서 다음을 지정할 수 있습니다.

    ```
        neptune-fts:config neptune-fts:sortBy 'Neptune#fts.document_type' .
    ```

    유사한 Gremlin 쿼리에서 다음을 지정할 수 있습니다.

    ```
        .withSideEffect('Neptune#fts.sortBy', 'Neptune#fts.document_type')
    ```

  기본적으로 OpenSearch 결과는 정렬되지 않으며 순서는 비결정적입니다. 즉 동일한 쿼리는 실행될 때마다 다른 순서로 항목을 반환할 수 있습니다. 이러한 이유로 결과 집합이 `max_result_window`보다 크면 쿼리가 실행될 때마다 상당히 다른 전체 결과 하위 집합이 반환될 수 있습니다. 그러나 정렬하면 다양한 실행의 결과를 더 직접적으로 비교할 수 있습니다.

  `sortOrder` 파라미터가 `sortBy`를 수반하지 않으면 최대값에서 최소값 순으로 정렬하는 내림차순(`DESC`)이 사용됩니다.
+ **`sortOrder`**   –   OpenSearch 결과를 최소값에서 최대값 순으로 또는 최대값에서 최소값 순(기본값)으로 정렬할지 지정할 수 있는 선택적 파라미터입니다.

****
  + `ASC`   –   오름차순(최소값에서 최대값 순으로 정렬).
  + `DESC`   –   내림차순(최대값에서 최소값 순으로 정렬).

    이것은 `sortBy` 파라미터가 없지만 `sortOrder`가 지정되지 않은 경우 사용되는 기본값입니다.

  `sortBy`와 `sortOrder` 둘 다 없는 경우 OpenSearch 결과는 정렬되지 않도록 기본 설정됩니다.

# Amazon Neptune의 비문자열 OpenSearch 인덱싱
<a name="full-text-search-non-string-indexing"></a>

Amazon Neptune의 비문자열 OpenSearch 인덱싱을 사용하면 스트림 폴러를 이용하여 조건자에 대한 비문자열 값을 OpenSearch에 복제할 수 있습니다. 그러면 해당 OpenSearch 매핑 또는 데이터 유형으로 안전하게 변환할 수 있는 모든 조건자 값이 OpenSearch에 복제됩니다.

새 스택에서 비문자열 인덱싱을 활성화하려면 CloudFormation 템플릿의 `Enable Non-String Indexing` 플래그를 `true`로 설정해야 합니다. 이것이 기본 설정입니다. 비문자열 인덱싱을 지원하도록 기존 스택을 업데이트하려면 아래 [기존 스택 업데이트](full-text-search-non-string-indexing-update.md)를 참조하세요.

**참고**  
**`1.0.4.2`** 이전 버전의 엔진에서는 비문자열 인덱싱을 활성화하지 않는 것이 좋습니다.
여러 필드와 일치하는 필드 이름에 정규식을 사용하는 OpenSearch 쿼리(일부는 문자열 값을 포함하고 일부는 비문자열 값 포함)를 사용하면 오류가 발생하여 실패합니다. Neptune의 전체 텍스트 검색 쿼리가 해당 유형인 경우에도 마찬가지입니다.
비문자열 필드를 정렬할 때는 필드 이름에 '.value'를 추가하여 문자열 필드와 구분해야 합니다.

**Contents**
+ [비문자열 인덱싱을 지원하도록 기존 Neptune 전체 텍스트 검색 스택 업데이트](full-text-search-non-string-indexing-update.md)
+ [Neptune 전체 텍스트 검색에서 인덱싱되는 필드 필터링](full-text-search-non-string-indexing-filters.md)
  + [속성 또는 조건자 이름을 기준으로 필터링](full-text-search-non-string-indexing-filters.md#full-text-search-non-string-indexing-filters-name)
  + [속성 또는 조건자 값 유형을 기준으로 필터링](full-text-search-non-string-indexing-filters.md#full-text-search-non-string-indexing-filters-datatype)
+ [SPARQL 및 Gremlin 데이터 유형을 OpenSearch에 매핑](full-text-search-non-string-indexing-mapping.md)
+ [데이터 매핑 검증](full-text-search-data-validation.md)
+ [Neptune의 비문자열 OpenSearch 쿼리 샘플](full-text-search-non-string-examples.md)
  + [나이가 30세 이상이고 이름이 'Si'로 시작하는 모든 버텍스를 가져옵니다.](full-text-search-non-string-examples.md#full-text-search-non-string-example-1)
  + [나이가 10\$150세이고 이름이 'Ronka'와 비슷하게 일치하는 모든 노드를 가져옵니다.](full-text-search-non-string-examples.md#full-text-search-non-string-example-2)
  + [지난 25일 이내의 타임스탬프가 있는 모든 노드를 가져옵니다.](full-text-search-non-string-examples.md#full-text-search-non-string-example-3)
  + [특정 연도 및 월에 해당하는 타임스탬프가 있는 모든 노드를 가져옵니다.](full-text-search-non-string-examples.md#full-text-search-non-string-example-4)

# 비문자열 인덱싱을 지원하도록 기존 Neptune 전체 텍스트 검색 스택 업데이트
<a name="full-text-search-non-string-indexing-update"></a>

이미 Neptune 전체 텍스트 검색을 사용하고 있는 경우 비문자열 인덱싱을 지원하기 위해 수행해야 하는 단계는 다음과 같습니다.

1. **스트림 폴러 Lambda 함수를 중지합니다.** 이렇게 하면 내보내기 중에 새 업데이트가 복사되지 않습니다. Lambda 함수를 간접적으로 호출하는 클라우드 이벤트 규칙을 비활성화하여 이 작업을 수행하세요.
   + AWS Management Console에서 CloudWatch로 이동합니다.
   + **규칙**을 선택합니다.
   + Lambda 스트림 폴러 이름이 있는 규칙을 선택합니다.
   + 규칙을 일시적으로 비활성화하려면 **비활성화**를 선택합니다.

1. **OpenSearch에서 현재 Neptune 인덱스를 삭제합니다.** 다음 `curl` 쿼리를 사용하여 OpenSearch 클러스터에서 `amazon_neptune` 인덱스를 삭제하세요.

   ```
   curl -X DELETE "your OpenSearch endpoint/amazon_neptune"
   ```

1. **Neptune에서 OpenSearch로 일회성 내보내기를 시작합니다.** 이 시점에서 새 OpenSearch 스택을 설정하여 내보내기를 수행하는 폴러가 새 아티팩트를 선택할 수 있도록 하는 것이 가장 좋습니다.

   [여기 GitHub]( https://github.com/awslabs/amazon-neptune-tools/blob/master/export-neptune-to-elasticsearch/readme.md)에 나열된 단계에 따라 Neptune 데이터를 OpenSearch로 한 번 내보내는 작업을 시작하세요.

1. **기존 스트림 폴러의 Lambda 아티팩트를 업데이트합니다.** OpenSearch로 Neptune 데이터를 성공적으로 내보낸 후 다음 단계를 수행하세요.
   + AWS Management Console에서 CloudFormation으로 이동합니다.
   + 기본 상위 CloudFormation 스택을 선택합니다.
   + 스택의 **업데이트** 옵션을 선택합니다.
   + **옵션에서 현재 템플릿 교체**를 선택합니다.
   + 템플릿 소스에서 **Amazon S3 URL**을 선택합니다.
   + Amazon S3 URL의 경우 다음과 같이 입력합니다.

     ```
     https://aws-neptune-customer-samples.s3.amazonaws.com/neptune-stream/neptune_to_elastic_search.json
     ```
   + CloudFormation 파라미터를 변경하지 않고 **다음**을 선택합니다.
   + **스택 업데이트**를 선택합니다. CloudFormation에서는 스트림 폴러의 Lambda 코드 아티팩트를 최신 아티팩트로 대체합니다.

1. **스트림 폴러를 다시 시작합니다.** 적절한 CloudWatch 규칙을 활성화하여 이를 수행하세요.
   + AWS Management Console에서 CloudWatch로 이동합니다.
   + **규칙**을 선택합니다.
   + Lambda 스트림 폴러 이름이 있는 규칙을 선택합니다.
   + **활성화**를 선택합니다.

# Neptune 전체 텍스트 검색에서 인덱싱되는 필드 필터링
<a name="full-text-search-non-string-indexing-filters"></a>

CloudFormation 템플릿 세부 정보에는 OpenSearch 인덱싱에서 제외할 속성이나 조건부 키 또는 데이터 유형을 지정할 수 있는 2개의 필드가 있습니다.

## 속성 또는 조건자 이름을 기준으로 필터링
<a name="full-text-search-non-string-indexing-filters-name"></a>

`Properties to exclude from being inserted into Elastic Search Index`로 이름이 지정된 옵션 CloudFormation 템플릿 파라미터를 사용하여 OpenSearch 인덱싱에서 제외할 속성 또는 조건부 키를 쉼표로 구분된 목록으로 제공할 수 있습니다.

예를 들어, 이 파라미터를 `bob`으로 설정한다고 가정해 보겠습니다.

```
"Properties to exclude from being inserted into Elastic Search Index" : bob
```

이 경우 다음 Gremlin 업데이트 쿼리의 스트림 레코드는 인덱스로 이동하지 않고 삭제됩니다.

```
g.V("1").property("bob", "test")
```

마찬가지로, 파라미터를 `http://my/example#bob`과 같이 설정할 수 있습니다.

```
"Properties to exclude from being inserted into Elastic Search Index" : http://my/example#bob
```

이 경우 다음 SPARQL 업데이트 쿼리의 스트림 레코드는 인덱스로 이동하지 않고 삭제됩니다.

```
PREFIX ex: <http://my/example#>
INSERT DATA { ex:s1 ex:bob "test"}.
```

이 CloudFormation 템플릿 파라미터에 아무것도 입력하지 않으면 제외되지 않은 모든 속성 키가 인덱싱됩니다.

## 속성 또는 조건자 값 유형을 기준으로 필터링
<a name="full-text-search-non-string-indexing-filters-datatype"></a>

`Datatypes to exclude from being inserted into Elastic Search Index`로 이름이 지정된 옵션 CloudFormation 템플릿 파라미터를 사용하여 OpenSearch 인덱싱에서 제외할 속성 또는 조건부 값 데이터 유형을 쉼표로 구분된 목록으로 제공할 수 있습니다.

SPARQL의 경우 전체 XSD 유형 URI를 나열할 필요 없이 데이터 유형 토큰만 나열하면 됩니다. 나열할 수 있는 유효한 데이터 유형 토큰은 다음과 같습니다.
+ `string`
+ `boolean`
+ `float`
+ `double`
+ `dateTime`
+ `date`
+ `time`
+ `byte`
+ `short`
+ `int`
+ `long`
+ `decimal`
+ `integer`
+ `nonNegativeInteger`
+ `nonPositiveInteger`
+ `negativeInteger`
+ `unsignedByte`
+ `unsignedShort`
+ `unsignedInt`
+ `unsignedLong`

Gremlin의 경우 나열할 수 있는 유효한 데이터 유형은 다음과 같습니다.
+ `string`
+ `date`
+ `bool`
+ `byte`
+ `short`
+ `int`
+ `long`
+ `float`
+ `double`

예를 들어, 이 파라미터를 `string`으로 설정한다고 가정해 보겠습니다.

```
"Datatypes to exclude from being inserted into Elastic Search Index" : string
```

이 경우 다음 Gremlin 업데이트 쿼리의 스트림 레코드는 인덱스로 이동하지 않고 삭제됩니다.

```
g.V("1").property("myStringval", "testvalue")
```

마찬가지로, 파라미터를 `int`과 같이 설정할 수 있습니다.

```
"Datatypes to exclude from being inserted into Elastic Search Index" : int
```

이 경우 다음 SPARQL 업데이트 쿼리의 스트림 레코드는 인덱스로 이동하지 않고 삭제됩니다.

```
PREFIX ex: <http://my/example#>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
INSERT DATA { ex:s1 ex:bob "11"^^xsd:int }.
```

이 CloudFormation 템플릿 파라미터에 아무것도 입력하지 않으면 값을 동등한 OpenSearch 항목으로 안전하게 변환할 수 있는 모든 속성이 인덱싱됩니다. 나열된 유형 중 쿼리 언어에서 지원되지 않는 유형은 무시됩니다.

# SPARQL 및 Gremlin 데이터 유형을 OpenSearch에 매핑
<a name="full-text-search-non-string-indexing-mapping"></a>

OpenSearch의 새로운 데이터 유형 매핑은 속성 또는 객체에서 사용되는 데이터 유형을 기반으로 생성됩니다. 일부 필드에는 다양한 유형의 값이 포함되어 있기 때문에 초기 매핑에는 필드의 일부 값이 제외될 수 있습니다.

Neptune 데이터 유형은 다음과 같이 OpenSearch 데이터 유형에 매핑됩니다.


| SPARQL 유형 | Gremlin 유형 | OpenSearch 유형 | 
| --- | --- | --- | 
|  `XSD:int` `XSD:unsignedInt` `XSD:integer` `XSD:byte` `XSD:unsignedByte` `XSD:short` `XSD:unsignedShort` `XSD:long` `XSD:unsignedLong`  |  `byte` `short` `int` `long`  | `long` | 
|  `XSD:float` `XSD:double` `XSD:decimal`  |  `float` `double`  | `double` | 
| `XSD:boolean` | `bool` | `boolean` | 
|  `XSD:datetime` `XSD:date`  | `date` | `date` | 
|  `XSD:string` `XSD:time`  | `string` | `text` | 
| *사용자 지정 데이터 유형* | *N/A* | `text` | 
| *기타 데이터 유형* | *N/A* | `text` | 

예를 들어, 다음과 같은 Gremlin 업데이트 쿼리를 실행하면 'newField'에 대한 새 매핑이 OpenSearch에 `{ "type" : "double" }` 이름으로 추가됩니다.

```
g.V("1").property("newField" 10.5)
```

마찬가지로, 다음과 같은 SPARQL 업데이트 쿼리를 실행하면 'ex:byte'에 대한 새 매핑이 OpenSearch에 `{ "type" : "long" }` 이름으로 추가됩니다.

```
PREFIX ex: <http://my/example#>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>

INSERT DATA { ex:test ex:byte "123"^^xsd:byte }.
```

**참고**  
보시다시피, Neptune에서 OpenSearch로 매핑된 항목은 결국 Neptune과 OpenSearch에서 데이터 유형이 다르게 나타날 수 있습니다. 하지만 OpenSearch에는 Neptune에 있는 항목의 데이터 유형을 기록하는 명시적인 텍스트 필드인 'datatype'이 있습니다.

# 데이터 매핑 검증
<a name="full-text-search-data-validation"></a>



데이터는 다음 프로세스를 사용하여 Neptune에서 OpenSearch로 복제됩니다.
+ 해당 필드에 대한 매핑이 OpenSearch에 이미 있는 경우:
  + 데이터 검증 규칙을 사용하여 데이터를 기존 매핑으로 안전하게 변환할 수 있는 경우 해당 필드를 OpenSearch에 저장하세요.
  + 그렇지 않은 경우 해당 스트림 업데이트 레코드를 삭제합니다.
+ 해당 필드에 대한 기존 매핑이 없는 경우 Neptune에서 필드의 데이터 유형에 해당하는 OpenSearch 데이터 유형을 찾습니다.
  + 데이터 검증 규칙을 사용하여 필드 데이터를 OpenSearch 데이터 유형으로 안전하게 변환할 수 있는 경우 새로운 매핑과 필드 데이터를 OpenSearch에 저장하세요.
  + 그렇지 않은 경우 해당 스트림 업데이트 레코드를 삭제합니다.

값은 Neptune 유형이 아닌 동일한 OpenSearch 유형이나 기존 OpenSearch 매핑을 기준으로 검증됩니다. 예를 들어, `"123"^^xsd:int`의 값 `"123"`에 대한 검증은 `int` 유형이 아닌 `long` 유형을 기준으로 이루어집니다.

Neptune은 모든 데이터를 OpenSearch에 복제하려고 시도하지만, OpenSearch의 데이터 유형이 Neptune의 데이터 유형과 완전히 다른 경우가 있습니다. 이런 상황에서는 OpenSearch에서 레코드를 인덱싱하지 않고 건너뛰기도 합니다.

예를 들어, Neptune에서는 한 속성에 유형이 다른 여러 값이 있을 수 있지만, OpenSearch의 필드는 인덱스 전체에서 유형이 같아야 합니다.

디버그 로그를 활성화하면 Neptune에서 OpenSearch로 내보내는 동안 삭제된 레코드를 볼 수 있습니다. 디버그 로그 항목의 예는 다음과 같습니다.

```
Dropping Record : Data type not a valid Gremlin type 
<Record>
```

데이터 유형은 다음과 같이 검증됩니다.
+ **`text`**   –   Neptune의 모든 값을 OpenSearch의 텍스트에 안전하게 매핑할 수 있습니다.
+ **`long`**   –   OpenSearch 매핑 유형이 긴 경우 Neptune 데이터 유형에 대한 다음 규칙이 적용됩니다(아래 예에서는 `"testLong"`에 `long` 매핑 유형이 있다고 가정).
  + `boolean`   –   유효하지 않아 변환할 수 없으며, 해당 스트림 업데이트 레코드가 삭제됩니다.

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      "testLong" : true.
      "testLong" : false.
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testLong" : "true"^^xsd:boolean
      ":testLong" : "false"^^xsd:boolean
    ```
  + `datetime`   –   유효하지 않아 변환할 수 없으며, 해당 스트림 업데이트 레코드가 삭제됩니다.

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      ":testLong" :  datetime('2018-11-04T00:00:00').
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testLong" : "2016-01-01"^^xsd:date
    ```
  + `float`, `double` 또는 `decimal`   –   Neptune의 값이 64비트에 속할 수 있는 정수이면 유효하며 OpenSearch에 long으로 저장됩니다. 그러나 소수 부분이 있거나, `NaN` 또는 `INF`이거나, 9,223,372,036,854,775,807보다 크거나, -9,223,372,036,854,775,808보다 작은 경우에는 유효하지 않으며 해당 스트림 업데이트 레코드가 삭제됩니다.

    유효한 Gremlin의 예는 다음과 같습니다.

    ```
      "testLong" :  145.0.
      ":testLong" :  123
      ":testLong" :  -9223372036854775807
    ```

    유효한 SPARQL의 예는 다음과 같습니다.

    ```
      ":testLong" : "145.0"^^xsd:float
      ":testLong" :  145.0
      ":testLong" : "145.0"^^xsd:double
      ":testLong" : "145.0"^^xsd:decimal
      ":testLong" : "-9223372036854775807"
    ```

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      "testLong" :  123.45
      ":testLong" :  9223372036854775900
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testLong" :  123.45
      ":testLong" :  9223372036854775900
      ":testLong" : "123.45"^^xsd:float
      ":testLong" : "123.45"^^xsd:double
      ":testLong" : "123.45"^^xsd:decimal
    ```
  + `string`   –   Neptune의 값이 64비트 정수에 포함될 수 있는 정수의 문자열 표현인 경우 유효하며 OpenSearch에서 `long`으로 변환됩니다. 다른 모든 문자열 값은 Elasticseearch `long` 매핑에 사용할 수 없으며, 해당 스트림 업데이트 레코드는 삭제됩니다.

    유효한 Gremlin의 예는 다음과 같습니다.

    ```
      "testLong" :  "123".
      ":testLong" :  "145.0"
      ":testLong" :  "-9223372036854775807"
    ```

    유효한 SPARQL의 예는 다음과 같습니다.

    ```
      ":testLong" : "145.0"^^xsd:string
      ":testLong" : "-9223372036854775807"^^xsd:string
    ```

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      "testLong" :  "123.45"
      ":testLong" :  "9223372036854775900"
      ":testLong" :  "abc"
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testLong" : "123.45"^^xsd:string
      ":testLong" : "abc"
      ":testLong" : "9223372036854775900"^^xsd:string
    ```
+ **`double`**   –   OpenSearch 매핑 유형이 `double`인 경우 다음 규칙이 적용됩니다(여기서는 OpenSearch에서 'testDouble' 필드에 `double` 매핑이 있는 것으로 가정).
  + `boolean`   –   유효하지 않아 변환할 수 없으며, 해당 스트림 업데이트 레코드가 삭제됩니다.

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      "testDouble" : true.
      "testDouble" : false.
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testDouble" : "true"^^xsd:boolean
      ":testDouble" : "false"^^xsd:boolean
    ```
  + `datetime`   –   유효하지 않아 변환할 수 없으며, 해당 스트림 업데이트 레코드가 삭제됩니다.

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      ":testDouble" :  datetime('2018-11-04T00:00:00').
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testDouble" : "2016-01-01"^^xsd:date
    ```
  + 부동 소수점 `NaN` 또는 `INF`   –   SPARQL의 값이 부동 소수점 `NaN` 또는 `INF`인 경우 유효하지 않으며, 해당 스트림 업데이트 레코드가 삭제됩니다.

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
    "  :testDouble" : "NaN"^^xsd:float
      ":testDouble" : "NaN"^^double
      ":testDouble" : "INF"^^double
      ":testDouble" : "-INF"^^double
    ```
  + 숫자 또는 숫자 문자열   –   Neptune의 값이 `double`로 안전하게 표현할 수 있는 숫자의 숫자 문자열 표현 또는 기타 숫자인 경우 유효하며, OpenSearch에서 `double`로 변환됩니다. 다른 모든 문자열 값은 OpenSearch `double` 매핑에 사용할 수 없으며, 해당 스트림 업데이트 레코드는 삭제됩니다.

    유효한 Gremlin의 예는 다음과 같습니다.

    ```
      "testDouble" :  123
      ":testDouble" :  "123"
      ":testDouble" :  145.67
      ":testDouble" :  "145.67"
    ```

    유효한 SPARQL의 예는 다음과 같습니다.

    ```
      ":testDouble" :  123.45
      ":testDouble" :  145.0
      ":testDouble" : "123.45"^^xsd:float
      ":testDouble" : "123.45"^^xsd:double
      ":testDouble" : "123.45"^^xsd:decimal
      ":testDouble" : "123.45"^^xsd:string
    ```

    유효하지 않은 Gremlin의 예는 다음과 같습니다.

    ```
      ":testDouble" :  "abc"
    ```

    유효하지 않은 SPARQL의 예는 다음과 같습니다.

    ```
      ":testDouble" : "abc"
    ```
+ **`date`**   –   OpenSearch 매핑 유형이 `date`인 경우 Neptune `date` 및 `dateTime` 값이 유효하며, `dateTime` 형식으로 성공적으로 구문 분석할 수 있는 모든 문자열 값도 유효합니다.

  Gremlin 또는 SPARQL의 유효한 예는 다음과 같습니다.

  ```
    Date(2016-01-01)
    "2016-01-01" "
    2003-09-25T10:49:41"
    "2003-09-25T10:49"
    "2003-09-25T10"
    "20030925T104941-0300"
    "20030925T104941"
    "2003-Sep-25" "
    Sep-25-2003"
    "2003.Sep.25"
    "2003/09/25"
    "2003 Sep 25" "
    Wed, July 10, '96"
    "Tuesday, April 12, 1952 AD 3:30:42pm PST"
    "123"
    "-123"
    "0"
    "-0"
    "123.00"
    "-123.00"
  ```

  유효하지 않은 예는 다음과 같습니다.

  ```
    123.45
    True
    "abc"
  ```

# Neptune의 비문자열 OpenSearch 쿼리 샘플
<a name="full-text-search-non-string-examples"></a>

Neptune은 현재 OpenSearch 범위 쿼리를 직접 지원하지 않습니다. 하지만 다음 샘플 쿼리에서 볼 수 있듯이 Lucene 구문과 query-type="query\$1string"을 사용하면 동일한 효과를 얻을 수 있습니다.

## 나이가 30세 이상이고 이름이 'Si'로 시작하는 모든 버텍스를 가져옵니다.
<a name="full-text-search-non-string-example-1"></a>

Gremlin에서:

```
g.withSideEffect('Neptune#fts.endpoint', 'http://your-es-endpoint')
 .withSideEffect("Neptune#fts.queryType", "query_string")
 .V().has('*', 'Neptune#fts predicates.age.value:>30 && predicates.name.value:Si*');
```

SPARQL에서:

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://localhost:9200' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query "predicates.\\*foaf\\*age.value:>30 AND predicates.\\*foaf\\*name.value:Si*" .
    neptune-fts:config neptune-fts:field '*' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

여기서는 간결성을 위해 전체 URI 대신 `"\\*foaf\\*age`가 사용됩니다. 이 정규 표현식은 URI에서 `foaf` 및 `age`가 있는 모든 필드를 검색합니다.

## 나이가 10\$150세이고 이름이 'Ronka'와 비슷하게 일치하는 모든 노드를 가져옵니다.
<a name="full-text-search-non-string-example-2"></a>

Gremlin에서:

```
g.withSideEffect('Neptune#fts.endpoint', 'http://your-es-endpoint')
 .withSideEffect("Neptune#fts.queryType", "query_string")
 .V().has('*', 'Neptune#fts predicates.age.value:[10 TO 50] AND predicates.name.value:Ronka~');
```

SPARQL에서:

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://localhost:9200' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query "predicates.\\*foaf\\*age.value:[10 TO 50] AND predicates.\\*foaf\\*name.value:Ronka~" .
    neptune-fts:config neptune-fts:field '*' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## 지난 25일 이내의 타임스탬프가 있는 모든 노드를 가져옵니다.
<a name="full-text-search-non-string-example-3"></a>

Gremlin에서:

```
g.withSideEffect('Neptune#fts.endpoint', 'http://your-es-endpoint')
 .withSideEffect("Neptune#fts.queryType", "query_string")
 .V().has('*', 'Neptune#fts predicates.timestamp.value:>now-25d');
```

SPARQL에서:

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://localhost:9200' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query "predicates.\\*foaf\\*timestamp.value:>now-25d~" .
    neptune-fts:config neptune-fts:field '*' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## 특정 연도 및 월에 해당하는 타임스탬프가 있는 모든 노드를 가져옵니다.
<a name="full-text-search-non-string-example-4"></a>

Gremlin에서 Lucene 구문으로 [날짜 수학 표현식](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/common-options.html#date-math) 사용(2020년 12월 기준):

```
g.withSideEffect('Neptune#fts.endpoint', 'http://your-es-endpoint')
 .withSideEffect("Neptune#fts.queryType", "query_string")
 .V().has('*', 'Neptune#fts predicates.timestamp.value:>2020-12');
```

Gremlin의 대안:

```
g.withSideEffect('Neptune#fts.endpoint', 'http://your-es-endpoint')
 .withSideEffect("Neptune#fts.queryType", "query_string")
 .V().has('*', 'Neptune#fts predicates.timestamp.value:[2020-12 TO 2021-01]');
```

# Amazon Neptune에서 전체 텍스트 검색 쿼리 실행
<a name="full-text-search-query-execution"></a>

전체 텍스트 검색을 포함하는 쿼리에서 Neptune은 전체 텍스트 검색 호출을 쿼리의 다른 부분보다 앞에 두려고 시도합니다. 이렇게 하면 OpenSearch에 대한 호출 수가 줄어들어, 대부분의 경우에서 성능이 크게 향상됩니다. 그러나 이는 반드시 지켜야만 하는 엄격한 규칙이 아닙니다. 예를 들어, 전체 텍스트 검색 호출보다 `PatternNode` 또는 `UnionNode`가 먼저 오는 경우가 있습니다.

`Person`의 인스턴스가 100,000개 있는 데이터베이스에 대한 다음과 같은 Gremlin 쿼리를 생각해 봅니다.

```
g.withSideEffect('Neptune#fts.endpoint', 'your-es-endpoint-URL')
 .hasLabel('Person')
 .has('name', 'Neptune#fts marcello~');
```

단계가 나타나는 순서대로 이 쿼리가 실행되면 100,000개의 솔루션이 OpenSearch로 유입되어 수백 개의 OpenSearch 호출이 발생합니다. 실제로 Neptune은 OpenSearch를 먼저 호출한 후 결과를 Neptune 결과와 조인합니다. 대부분의 경우에서 이 작업은 원래 순서로 쿼리를 실행할 때보다 훨씬 빠릅니다.

[noReordering 쿼리 힌트](gremlin-query-hints-noReordering.md)를 사용하여 이렇게 쿼리 단계 실행 순서가 변경되는 것을 방지할 수 있습니다.

```
g.withSideEffect('Neptune#fts.endpoint', 'your-es-endpoint-URL')
 .withSideEffect('Neptune#noReordering', true)
 .hasLabel('Person')
 .has('name', 'Neptune#fts marcello~');
```

이 두 번째 경우에는 `.hasLabel`단계가 먼저 실행되고 `.has('name', 'Neptune#fts marcello~')`단계가 두 번째로 실행됩니다.

이번에는 동일한 종류의 데이터에 대한 SPARQL 쿼리를 생각해보십시오.

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT ?person WHERE {
  ?person rdf:type foaf:Person .
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:query 'mike' .
    neptune-fts:config neptune-fts:return ?person .
  }
}
```

이 경우에도 Neptune이 쿼리의 `SERVICE` 부분을 먼저 실행한 다음 결과를 `Person` 데이터와 조인합니다. [joinOrder 쿼리 힌트](sparql-query-hints-joinOrder.md)를 사용하여 이 동작을 억제할 수 있습니다.

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
PREFIX hint: <http://aws.amazon.com/neptune/vocab/v01/QueryHints#>
SELECT ?person WHERE {
  hint:Query hint:joinOrder "Ordered" .
  ?person rdf:type foaf:Person .
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:query 'mike' .
    neptune-fts:config neptune-fts:return ?person .
  }
}
```

두 번째 쿼리에서도 해당 부분이 쿼리에 나타나는 순서대로 실행됩니다.

**참고**  
 인덱스를 직접 쿼리하는 대신 인덱스에 대한 Opensearch 별칭을 쿼리하면 잘못된 결과가 발생할 수 있습니다. 별칭이 아닌 Opensearch 인덱스를 직접 쿼리해야 합니다.

# Neptune에서 전체 텍스트 검색을 사용하는 샘플 SPARQL 쿼리
<a name="full-text-search-sparql-examples"></a>

다음은 Amazon Neptune에서 전체 텍스트 검색을 사용하는 몇 가지 샘플 SPARQL 쿼리입니다.

## SPARQL 일치 쿼리 예
<a name="full-text-search-sparql-match"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:queryType 'match' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:query 'michael' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL 접두사 쿼리 예
<a name="full-text-search-sparql-prefix"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:queryType 'prefix' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:query 'mich' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL 퍼지 쿼리 예
<a name="full-text-search-sparql-fuzzy"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:queryType 'fuzzy' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:query 'mikael' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL 용어 쿼리 예
<a name="full-text-search-sparql-term"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:queryType 'term' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:query 'Dr. Kunal' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL query\$1string 쿼리 예
<a name="full-text-search-sparql-query_string"></a>

이 쿼리는 여러 필드를 지정합니다.

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ OR rondelli' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:field foaf:surname .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL simple\$1query\$1string 쿼리 예
<a name="full-text-search-sparql-simple"></a>

다음 쿼리는 와일드카드('\$1') 문자를 사용하여 필드를 지정합니다.

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint.com' .
    neptune-fts:config neptune-fts:queryType 'simple_query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ | rondelli' .
    neptune-fts:config neptune-fts:field '*' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL 문자열 필드별 정렬 쿼리 예
<a name="full-text-search-sparql-sort-by-field"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ | rondelli' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:sortOrder 'asc' .
    neptune-fts:config neptune-fts:sortBy foaf:name .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL 비문자열 필드별 정렬 쿼리 예
<a name="full-text-search-sparql-sort-by-field"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ | rondelli' .
    neptune-fts:config neptune-fts:field foaf:name.value .
    neptune-fts:config neptune-fts:sortOrder 'asc' .
    neptune-fts:config neptune-fts:sortBy dc:date.value .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL ID별 정렬 쿼리 예
<a name="full-text-search-sparql-sort-by-id"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ | rondelli' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:sortOrder 'asc' .
    neptune-fts:config neptune-fts:sortBy 'Neptune#fts.entity_id' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL 레이블별 정렬 쿼리 예
<a name="full-text-search-sparql-sort-by-label"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ | rondelli' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:sortOrder 'asc' .
    neptune-fts:config neptune-fts:sortBy 'Neptune#fts.entity_type' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL doc\$1type별 정렬 쿼리 예
<a name="full-text-search-sparql-sort-by-doc-type"></a>

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'mikael~ | rondelli' .
    neptune-fts:config neptune-fts:field foaf:name .
    neptune-fts:config neptune-fts:sortOrder 'asc' .
    neptune-fts:config neptune-fts:sortBy 'Neptune#fts.document_type' .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

## SPARQL에서 Lucene 구문을 사용하는 예
<a name="full-text-search-sparql-lucene-syntax"></a>

Lucene 구문은 OpenSearch의 `query_string` 쿼리에만 지원됩니다.

```
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX neptune-fts: <http://aws.amazon.com/neptune/vocab/v01/services/fts#>
SELECT * WHERE {
  SERVICE neptune-fts:search {
    neptune-fts:config neptune-fts:endpoint 'http://your-es-endpoint' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:queryType 'query_string' .
    neptune-fts:config neptune-fts:query 'predicates.\\foaf\\name.value:micheal AND predicates.\\foaf\\surname.value:sh' .
    neptune-fts:config neptune-fts:field ‘’ .
    neptune-fts:config neptune-fts:return ?res .
  }
}
```

# Gremlin 쿼리에서 Neptune 전체 텍스트 검색 사용
<a name="full-text-search-gremlin"></a>

`NeptuneSearchStep`을 사용하면 Neptune 단계로 변환되지 않는 Gremlin 순회 부분에 대한 전체 텍스트 검색 쿼리를 사용할 수 있습니다. 예를 들어 다음과 같은 쿼리를 고려해 보십시오.

```
g.withSideEffect("Neptune#fts.endpoint", "your-es-endpoint-URL")
  .V()
      .tail(100)
      .has("name", "Neptune#fts mark*")            <== # Limit the search on name
```

이 쿼리는 Neptune에서 다음의 최적화된 순회로 변환됩니다.

```
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .], {estimatedCardinality=INFINITY}
        }, annotations={path=[Vertex(?1):GraphStep], maxVarId=4}
    },
    NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: [NeptuneTailGlobalStep(100), NeptuneTinkerpopTraverserConverterStep, NeptuneSearchStep {
    JoinGroupNode {
        SearchNode[(idVar=?3, query=mark*, field=name) . project ask .], {endpoint=your-OpenSearch-endpoint-URL}
    }
    JoinGroupNode {
        SearchNode[(idVar=?3, query=mark*, field=name) . project ask .], {endpoint=your-OpenSearch-endpoint-URL}
    }
}]
```

다음은 air-routes 데이터에 대한 Gremlin 쿼리의 예입니다.

## 대소문자 구분하지 않는 Gremlin basic `match` 쿼리
<a name="full-text-search-gremlin-basic-match"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'match')
  .V().has("city","Neptune#fts dallas")

==>v[186]
==>v[8]
```

## Gremlin `match` 쿼리
<a name="full-text-search-gremlin-match"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'match')
  .V().has("city","Neptune#fts southampton")
     .local(values('code','city').fold())
     .limit(5)

==>[SOU, Southampton]
```

## Gremlin `fuzzy` 쿼리
<a name="full-text-search-gremlin-fuzzy"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .V().has("city","Neptune#fts allas~").values('city').limit(5)

==>Dallas
==>Dallas
==>Walla Walla
==>Velas
==>Altai
```

## Gremlin `query_string` fuzzy 쿼리
<a name="full-text-search-gremlin-query_string-fuzzy"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'query_string')
  .V().has("city","Neptune#fts allas~").values('city').limit(5)

==>Dallas
==>Dallas
```

## Gremlin `query_string` 정규식 쿼리
<a name="full-text-search-gremlin-query_string-regex"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'query_string')
  .V().has("city","Neptune#fts /[dp]allas/").values('city').limit(5)

==>Dallas
==>Dallas
```

## Gremlin hybrid 쿼리
<a name="full-text-search-gremlin-hybrid"></a>

이 쿼리는 동일한 쿼리에서 Neptune 내부 인덱스와 OpenSearch 인덱스를 사용합니다.

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .V().has("region","GB-ENG")
      .has('city','Neptune#fts L*')
      .values('city')
      .dedup()
      .limit(10)

==>London
==>Leeds
==>Liverpool
==>Land's End
```

## 간단한 Gremlin 전체 텍스트 검색 예
<a name="full-text-search-gremlin-example"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .V().has('desc','Neptune#fts regional municipal')
      .local(values('code','desc').fold())
      .limit(100)

==>[HYA, Barnstable Municipal Boardman Polando Field]
==>[SPS, Sheppard Air Force Base-Wichita Falls Municipal Airport]
==>[ABR, Aberdeen Regional Airport]
==>[SLK, Adirondack Regional Airport]
==>[BFD, Bradford Regional Airport]
==>[EAR, Kearney Regional Airport]
==>[ROT, Rotorua Regional Airport]
==>[YHD, Dryden Regional Airport]
==>[TEX, Telluride Regional Airport]
==>[WOL, Illawarra Regional Airport]
==>[TUP, Tupelo Regional Airport]
==>[COU, Columbia Regional Airport]
==>[MHK, Manhattan Regional Airport]
==>[BJI, Bemidji Regional Airport]
==>[HAS, Hail Regional Airport]
==>[ALO, Waterloo Regional Airport]
==>[SHV, Shreveport Regional Airport]
==>[ABI, Abilene Regional Airport]
==>[GIZ, Jizan Regional Airport]
==>[USA, Concord Regional Airport]
==>[JMS, Jamestown Regional Airport]
==>[COS, City of Colorado Springs Municipal Airport]
==>[PKB, Mid Ohio Valley Regional Airport]
```

## `query_string`과 '\$1' 및 '-' 연산자를 사용하는 Gremlin 쿼리
<a name="full-text-search-gremlin-query_string-plus-minus"></a>

`query_string` 쿼리 유형은 기본 `simple_query_string` 유형보다 훨씬 엄격하지만 보다 정확한 쿼리가 가능합니다. 아래의 첫 번째 쿼리는 `query_string`을 사용하고, 두 번째 쿼리는 기본값인 `simple_query_string`을 사용합니다.

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'query_string')
 . V().has('desc','Neptune#fts +London -(Stansted|Gatwick)')
      .local(values('code','desc').fold())
      .limit(10)

==>[LHR, London Heathrow]
==>[YXU, London Airport]
==>[LTN, London Luton Airport]
==>[SEN, London Southend Airport]
==>[LCY, London City Airport]
```

아래 예제의 `simple_query_string`이 어떻게 '\$1'및 '-'연산자를 자동으로 무시하는지 살펴보십시오.

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .V().has('desc','Neptune#fts +London -(Stansted|Gatwick)')
      .local(values('code','desc').fold())
      .limit(10)

==>[LHR, London Heathrow]
==>[YXU, London Airport]
==>[LGW, London Gatwick]
==>[STN, London Stansted Airport]
==>[LTN, London Luton Airport]
==>[SEN, London Southend Airport]
==>[LCY, London City Airport]
==>[SKG, Thessaloniki Macedonia International Airport]
==>[ADB, Adnan Menderes International Airport]
==>[BTV, Burlington International Airport]
```

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'query_string')
  .V().has('desc','Neptune#fts +(regional|municipal) -(international|bradford)')
      .local(values('code','desc').fold())
      .limit(10)

==>[CZH, Corozal Municipal Airport]
==>[MMU, Morristown Municipal Airport]
==>[YBR, Brandon Municipal Airport]
==>[RDD, Redding Municipal Airport]
==>[VIS, Visalia Municipal Airport]
==>[AIA, Alliance Municipal Airport]
==>[CDR, Chadron Municipal Airport]
==>[CVN, Clovis Municipal Airport]
==>[SDY, Sidney Richland Municipal Airport]
==>[SGU, St George Municipal Airport]
```

## `AND` 및 `OR` 연산자를 사용하는 Gremlin `query_string` 쿼리
<a name="full-text-search-gremlin-query_string-AND-OR"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'query_string')
  .V().has('desc','Neptune#fts (St AND George) OR (St AND Augustin)')
      .local(values('code','desc').fold())
      .limit(10)

==>[YIF, St Augustin Airport]
==>[STG, St George Airport]
==>[SGO, St George Airport]
==>[SGU, St George Municipal Airport]
```

## Gremlin `term` 쿼리
<a name="full-text-search-gremlin-term"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'term')
  .V().has("SKU","Neptune#fts ABC123DEF9")
      .local(values('code','city').fold())
      .limit(5)

==>[AUS, Austin]
```

## Gremlin `prefix` 쿼리
<a name="full-text-search-gremlin-prefix"></a>

```
g.withSideEffect("Neptune#fts.endpoint",
                 "your-OpenSearch-endpoint-URL")
  .withSideEffect('Neptune#fts.queryType', 'prefix')
  .V().has("icao","Neptune#fts ka")
      .local(values('code','icao','city').fold())
      .limit(5)

==>[AZO, KAZO, Kalamazoo]
==>[APN, KAPN, Alpena]
==>[ACK, KACK, Nantucket]
==>[ALO, KALO, Waterloo]
==>[ABI, KABI, Abilene]
```

## Neptune Gremlin에서 Lucene 구문 사용
<a name="full-text-search-gremlin-lucene"></a>

Neptune Gremlin에서는 Lucene 쿼리 구문을 사용하여 매우 강력한 쿼리를 작성할 수도 있습니다. Lucene 구문은 OpenSearch의 `query_string` 쿼리에만 지원됩니다.

다음 데이터를 가정합니다.

```
g.addV("person")
        .property(T.id, "p1")
        .property("name", "simone")
        .property("surname", "rondelli")

g.addV("person")
        .property(T.id, "p2")
        .property("name", "simone")
        .property("surname", "sengupta")

g.addV("developer")
        .property(T.id, "p3")
        .property("name", "simone")
        .property("surname", "rondelli")
```

`queryType`이 `query_string`일 때 호출되는 Lucene 구문을 사용하여 다음과 같이 이름과 성으로 이 데이터를 검색할 수 있습니다.

```
g.withSideEffect("Neptune#fts.endpoint", "es_endpoint")
    .withSideEffect("Neptune#fts.queryType", "query_string")
    .V()
    .has("*", "Neptune#fts predicates.name.value:simone AND predicates.surname.value:rondelli")

==> v[p1], v[p3]
```

위의 `has()` 단계에서 이 필드는 `"*"`로 대체됩니다. 실제로 거기에 배치된 모든 값은 쿼리 내에서 액세스하는 필드에 의해 재정의됩니다. `predicates.name.value,`를 사용하여 이름 필드에 액세스할 수 있습니다. 이것이 바로 이 데이터 모델을 구성하는 방법이기 때문입니다.

다음과 같이 이름, 성 및 레이블로 검색할 수 있습니다.

```
g.withSideEffect("Neptune#fts.endpoint", getEsEndpoint())
    .withSideEffect("Neptune#fts.queryType", "query_string")
    .V()
    .has("*", "Neptune#fts predicates.name.value:simone AND predicates.surname.value:rondelli AND entity_type:person")

==> v[p1]
```

레이블은 데이터 모델이 구조화되는 방식이므로 `entity_type`를 사용하여 액세스됩니다.

중첩 조건을 포함할 수도 있습니다.

```
g.withSideEffect("Neptune#fts.endpoint", getEsEndpoint())
    .withSideEffect("Neptune#fts.queryType", "query_string")
    .V()
    .has("*", "Neptune#fts (predicates.name.value:simone AND predicates.surname.value:rondelli AND entity_type:person) OR predicates.surname.value:sengupta")

==> v[p1], v[p2]
```

## 최신 TinkerPop 그래프 삽입
<a name="full-text-search-gremlin-modern-tinkerpop-graph"></a>

```
g.addV('person').property(T.id, '1').property('name', 'marko').property('age', 29)
 .addV('personr').property(T.id, '2').property('name', 'vadas').property('age', 27)
 .addV('software').property(T.id, '3').property('name', 'lop').property('lang', 'java')
 .addV('person').property(T.id, '4').property('name', 'josh').property('age', 32)
 .addV('software').property(T.id, '5').property('name', 'ripple').property('lang', 'java')
 .addV('person').property(T.id, '6').property('name', 'peter').property('age', 35)

g.V('1').as('a').V('2').as('b').addE('knows').from('a').to('b').property('weight', 0.5f).property(T.id, '7')
 .V('1').as('a').V('3').as('b').addE('created').from('a').to('b').property('weight', 0.4f).property(T.id, '9')
 .V('4').as('a').V('3').as('b').addE('created').from('a').to('b').property('weight', 0.4f).property(T.id, '11')
 .V('4').as('a').V('5').as('b').addE('created').from('a').to('b').property('weight', 1.0f).property(T.id, '10')
 .V('6').as('a').V('3').as('b').addE('created').from('a').to('b').property('weight', 0.2f).property(T.id, '12')
 .V('1').as('a').V('4').as('b').addE('knows').from('a').to('b').property('weight', 1.0f).property(T.id, '8')
```

## 문자열 필드별 정렬 값 예
<a name="full-text-search-gremlin-sort-by-string"></a>

```
g.withSideEffect("Neptune#fts.endpoint", "your-OpenSearch-endpoint-URL")
 .withSideEffect('Neptune#fts.queryType', 'query_string')
 .withSideEffect('Neptune#fts.sortOrder', 'asc')
 .withSideEffect('Neptune#fts.sortBy', 'name')
 .V().has('name', 'Neptune#fts marko OR vadas OR ripple')
```

## 비문자열 필드별 정렬 값 예
<a name="full-text-search-gremlin-sort-by-non-string"></a>

```
g.withSideEffect("Neptune#fts.endpoint", "your-OpenSearch-endpoint-URL")
 .withSideEffect('Neptune#fts.queryType', 'query_string')
 .withSideEffect('Neptune#fts.sortOrder', 'asc')
 .withSideEffect('Neptune#fts.sortBy', 'age.value')
 .V().has('name', 'Neptune#fts marko OR vadas OR ripple')
```

## ID 필드별 정렬 값 예
<a name="full-text-search-gremlin-sort-by-id"></a>

```
g.withSideEffect("Neptune#fts.endpoint", "your-OpenSearch-endpoint-URL")
.withSideEffect('Neptune#fts.queryType', 'query_string')
.withSideEffect('Neptune#fts.sortOrder', 'asc')
.withSideEffect('Neptune#fts.sortBy', 'Neptune#fts.entity_id')
.V().has('name', 'Neptune#fts marko OR vadas OR ripple')
```

## 레이블 필드별 정렬 값 예
<a name="full-text-search-gremlin-sort-by-label"></a>

```
g.withSideEffect("Neptune#fts.endpoint", "your-OpenSearch-endpoint-URL")
 .withSideEffect('Neptune#fts.queryType', 'query_string')
 .withSideEffect('Neptune#fts.sortOrder', 'asc')
 .withSideEffect('Neptune#fts.sortBy', 'Neptune#fts.entity_type')
 .V().has('name', 'Neptune#fts marko OR vadas OR ripple')
```

## `document_type` 필드별 정렬 값 예
<a name="full-text-search-gremlin-sort-by-document_type"></a>

```
g.withSideEffect("Neptune#fts.endpoint", "your-OpenSearch-endpoint-URL")
 .withSideEffect('Neptune#fts.queryType', 'query_string')
 .withSideEffect('Neptune#fts.sortOrder', 'asc')
 .withSideEffect('Neptune#fts.sortBy', 'Neptune#fts.document_type')
 .V().has('name', 'Neptune#fts marko OR vadas OR ripple')
```

# Neptune 전체 텍스트 검색 문제 해결
<a name="streams-consumer-troubleshooting"></a>

**참고**  
OpenSearch 클러스터에서 [세분화된 액세스 제어](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html)를 활성화한 경우 Neptune 데이터베이스에서도 [IAM 인증을 활성화](iam-auth-enable.md)해야 합니다.

Neptune에서 OpenSearch로의 복제 관련 문제를 진단하려면 폴러 Lambda 함수에 대한 CloudWatch Logs를 참조하세요. 이러한 로그는 스트림에서 읽은 레코드 수와 OpenSearch에 성공적으로 복제된 레코드 수에 대한 세부 정보를 제공합니다.

또한 `LoggingLevel` 환경 변수를 변경하여 Lambda 함수의 LOGGING 수준을 변경할 수도 있습니다.

**참고**  
`LoggingLevel`을 `DEBUG`로 설정하면 StreamPoller를 통해 Neptune에서 OpenSearch로 데이터를 복제하면서 삭제된 스트림 레코드 및 각 레코드가 삭제된 이유와 같은 추가 세부 정보를 볼 수 있습니다. 이는 누락된 레코드가 있는 경우 유용할 수 있습니다.

Neptune 스트림 소비자 애플리케이션은 문제를 진단하는 데 도움이 될 수 있는 CloudWatch의 2가지 지표를 게시합니다.
+ `StreamRecordsProcessed` – 애플리케이션에서 시간 단위당 처리된 레코드 수입니다. 애플리케이션 실행 속도를 추적하는 데 도움이 됩니다.
+ `StreamLagTime` – 처리 중인 스트림 레코드의 현재 시간과 커밋 시간 간의 시간 차이(밀리초)입니다. 이 지표는 소비자 애플리케이션이 얼마나 지연되고 있는지 보여줍니다.

또한 복제 프로세스와 관련된 모든 지표는 CloudWatch 템플릿을 사용하여 애플리케이션을 인스턴스화할 때 제공된 `ApplicationName`과 동일한 이름으로 CloudWatch의 대시보드에 표시됩니다.

또한 폴링이 연속해서 두 번 이상 실패할 때마다 트리거되는 CloudWatch 경보를 만들도록 선택할 수도 있습니다. 애플리케이션을 인스턴스화할 때 `CreateCloudWatchAlarm` 필드를 `true`로 설정하여 이를 수행할 수 있습니다. 그런 다음 경보가 트리거될 때 알림을 받을 이메일 주소를 지정합니다.

## 스트림에서 레코드를 읽는 동안 실패한 프로세스 문제 해결
<a name="streams-consumer-troubleshooting-reads"></a>

스트림에서 레코드를 읽는 동안 프로세스가 실패할 경우 다음 사항을 갖추고 있는지 확인합니다.
+ 스트림이 클러스터에서 활성화되었습니다.
+ Neptune 스트림 엔드포인트가 다음과 같이 올바른 형식입니다.
  + Gremlin 또는 openCypher의 경우: `https://your cluster endpoint:your cluster port/propertygraph/stream` 또는 그 별칭, `https://your cluster endpoint:your cluster port/pg/stream` 
  + SPARQL의 경우: `https://your cluster endpoint:your cluster port/sparql/stream`

  
+ DynamoDB 엔드포인트가 VPC에 대해 구성되었습니다.
+ 모니터링 엔드포인트가 VPC 서브넷에 대해 구성되었습니다.

## OpenSearch에 데이터를 쓰는 동안 실패한 프로세스 문제 해결
<a name="streams-consumer-troubleshooting-writes"></a>

OpenSearch에 레코드를 쓰는 동안 프로세스가 실패할 경우 다음 사항을 갖추고 있는지 확인합니다.
+ Elasticsearch 버전이 7.1 이상이거나 OpenSearch 2.3 이상입니다.
+ OpenSearch는 VPC의 폴러 Lambda 함수에서 액세스할 수 있습니다.
+ OpenSearch에 연결된 보안 정책은 인바운드 HTTP/HTTPS 요청을 허용합니다.

## 기존 복제 설정에서 Neptune과 OpenSearch 간의 동기화 불능 문제 해결
<a name="streams-consumer-troubleshooting-sync-issues"></a>

`ExpiredStreamException` 또는 데이터 손상으로 인해 Neptune 데이터베이스와 OpenSearch 도메인 간에 동기화 불능 문제가 발생하는 경우 아래 단계를 통해 Neptune 데이터베이스와 OpenSearch 도메인을 최신 데이터와 다시 동기화할 수 있습니다.

이 접근 방식은 OpenSearch 도메인의 모든 데이터를 삭제하고 Neptune 데이터베이스의 현재 상태에서 다시 동기화하므로, Neptune 데이터베이스에서 데이터를 다시 로드할 필요가 없습니다.

1. [스트림 폴러 프로세스 비활성화(일시 중지)](full-text-search-pause-poller.md)에 설명된 대로 복제 프로세스를 비활성화합니다.

1. 다음 명령을 사용하여 OpenSearch 도메인에서 Neptune 인덱스를 삭제합니다.

   ```
   curl -X DELETE "(your OpenSearch endpoint)/amazon_neptune"
   ```

1. 데이터베이스의 복제본을 생성합니다([Neptune의 데이터베이스 복제](manage-console-cloning.md) 참조).

1. 스트림 API 엔드포인트에 대해 다음과 같은 종류의 명령을 실행하여 복제된 데이터베이스의 스트림에서 최신 `eventID`를 가져옵니다(자세한 내용은 [Neptune 스트림 REST API 호출](streams-using-api-call.md) 참조).

   ```
   curl "https://(your neptune endpoint):(port)/(propertygraph or sparql)/stream?iteratorType=LATEST"
   ```

   응답에서 `lastEventId` 객체의 `commitNum` 및 `opNum` 필드 값을 기록해 둡니다.

1. Github의 [export-neptune-to-elasticsearch](https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch) 도구를 사용하여 복제된 데이터베이스를 OpenSearch 도메인으로 한 번에 동기화할 수 있습니다.

1. 복제 스택에 대한 DynamoDB 표로 이동합니다. 테이블의 이름은 CloudFormation 템플릿에 지정한 **애플리케이션 이름**(기본값은 `NeptuneStream`)이며 접미사가 `-LeaseTable` 붙습니다. 즉, 기본 표 이름은 `NeptuneStream-LeaseTable`입니다.

   표에는 행이 하나만 있어야 하므로, 스캔하여 표 행을 탐색할 수 있습니다. 위에 기록해 둔 `commitNum` 및 `opNum` 값을 사용하여 다음과 같이 변경하세요.
   + 표의 `checkpoint` 필드 값을 `commitNum`에 대해 기록해 둔 값으로 변경합니다.
   + 표의 `checkpointSubSequenceNumber` 필드 값을 `opNum`에 대해 기록해 둔 값으로 변경합니다.

1. [스트림 폴러 프로세스 재활성화](full-text-search-re-enable-poller.md)에 설명된 대로 복제 프로세스를 다시 활성화합니다.

1. 복제된 데이터베이스와 `export-neptune-to-elasticsearch` 도구에 대해 생성된 CloudFormation 스택을 삭제합니다.