어쩔 수 없는 일입니다: 문서 데이터베이스로 작업하는 경우 결국에는 JSON 문서를 검색해야 합니다.
이 튜토리얼에서는 이 Node.js 시리즈를 통해 구축해 온 Express로 구축된 기본 REST API에 Couchbase의 전체 텍스트 검색 기능을 추가합니다.
이 시리즈의 이전 게시물 Express를 사용하여 N1QL 쿼리를 생성하기 위한 기본 API를 구축했습니다..
오늘의 포스팅에서는 한 단계 더 나아가 보겠습니다. 앱에 다음과 같은 기능을 추가하여 원하는 텍스트가 포함된 JSON 문서를 찾는 방법을 알아보겠습니다. 카우치베이스 검색 API. 시작해 보겠습니다.
전체 텍스트 검색이란 무엇인가요?
전체 텍스트 검색(FTS)은 생소한 이름이지만, 대량의 텍스트 콘텐츠를 분석하는 데 중점을 둔 학술 분야에서 잘 발달된 개념입니다. 데이터베이스 영역에서는 줄여서 '검색'이라고 부르며, JSON 문서 내에서 텍스트를 찾는 데 중점을 둡니다.
애플리케이션 개발자는 검색 관련 도구를 사용해 관심 있는 데이터를 찾는 방법과 위치를 알아야 하는 SQL 쿼리를 작성하지 않고도 일치하는 항목을 찾을 수 있습니다. 전체 텍스트 검색 시나리오에서는 좀 더 정교하게 텍스트를 찾습니다.
예를 들어, 검색 시스템은 어간이라는 개념을 사용하여 어근을 이해하므로 용어의 많은 순열을 수동으로 찾을 필요가 없습니다. 마찬가지로 와일드카드, 접두사 및 퍼지 매칭 강력한 검색 시스템으로 가능합니다.
검색 색인 설정
검색 시스템 사용에는 (1) 각 문서의 텍스트를 색인/분석하는 단계와 (2) 텍스트 기반 일치 항목이 포함된 문서 목록을 요청하는 두 가지 단계가 있습니다.
인덱싱 단계 는 색인할 필드나 요소를 설명하면 시스템이 이를 추적하는 관계형/표 형식 데이터에 대한 보조 색인을 만드는 것과 유사합니다. 문서에 있는 모든 텍스트 필드를 색인하도록 시스템에 지시할 수도 있지만, 대규모 데이터 세트의 경우 프로덕션 환경에서 효율적이지 않을 수 있습니다.
쿼리 단계 (일명 검색)은 서버가 검색할 텍스트를 서버로 전송합니다. 시스템은 해당 텍스트를 색인과 비교하여 일치하는 문서 목록을 반환합니다.
전체 텍스트 검색은 간단하지만 다음과 같이 고려해야 할 옵션과 질문이 무궁무진합니다:
-
- 구문과 숫자를 처리하는 방법
- 문서에서 특정 텍스트가 있는 위치 식별하기
- 여러 언어에 걸친 텍스트 분석
사실, 이것은 그 자체로 심도 있는 주제입니다. 이 게시물에 사용된 간단한 패턴은 다음에서 설명하는 대로 모든 다른 검색 시나리오로 확장할 수 있습니다. 전체 텍스트 검색에 대한 소개.
카우치베이스 인스턴스 준비하기
이 자바스크립트 코딩 튜토리얼 시리즈를 처음 사용하는 경우에는 여행 샘플
데이터 버킷에 설명된 대로 카우치베이스 문서.
이 시리즈의 이전 글에서 사용한 스크립트를 오늘 글의 시작점으로 사용할 것입니다. Node.js 코드는 다음 위치에 포함되어 있습니다. 해당 게시물의 끝.
이 Node.js 튜토리얼을 진행하면서 더 복잡하고 유용한 REST API 애플리케이션을 구축하게 됩니다. 프로젝트의 다음 단계를 지원하는 데 필요한 검색 인덱스를 만드는 방법에 대해 자세히 알아봅시다.
기본 텍스트 검색 색인 구축
검색 색인을 만들려면 검색
탭의 카우치베이스 웹 콘솔 을 클릭하고 색인 추가
버튼을 클릭합니다.
그런 다음 인덱스에 이름을 지정할 이름을 입력하고 분석할 버킷을 선택합니다(여행 샘플
). 를 눌러 완료합니다. 색인 만들기
버튼을 클릭하여 선택 사항을 제출합니다. 선택할 수 있는 옵션은 다양하지만 오늘의 예에서는 단순성을 위해 모든 기본값을 그대로 유지합니다. 다음 애니메이션은 이러한 각 단계를 보여줍니다:
이 단계를 완료하면 웹 콘솔에서 검색 인덱스와 그 상태를 볼 수 있습니다. 처리된 문서 수 또한 확인할 수 있어야 합니다.
색인 생성 여행 샘플
데이터 버킷을 만드는 데 몇 분 정도 걸리지만, 완료되면 아래와 같이 기본 웹 사용자 인터페이스를 통해 샘플 검색 요청을 할 수 있습니다.
검색창에 간단한 용어를 입력하면 일치하는 문서 ID 목록이 반환되며, 가장 높은 순위의 일치 문서가 맨 위에 표시됩니다. 웹 콘솔에서는 이러한 ID를 클릭하여 전체 문서 텍스트를 쉽게 볼 수 있습니다.
간단한 텍스트 검색 기능 만들기
부울 연산, 퍼지 매칭 등을 통해 검색을 미세 조정할 수 있는 다양한 추가 옵션이 있습니다. 웹 콘솔에서는 간단한 쿼리 문자열
검색을 사용하면 코드에서 구현할 유형과 동일한 유형이 됩니다.
새 전체 텍스트 검색 기능을 만들려면 다음과 같이 해야 합니다:
- 검색할 문자열을 입력합니다(예: "grand").
- 사용할 검색 인덱스를 지정합니다:
여행 검색
. - 사용할 쿼리 유형을 선언합니다:
쿼리 문자열
. - 모든 부품을 함께 조립하여 서버로 보냅니다.
- 결과를 수신하여 사용자/애플리케이션에 표시합니다.
아래 다섯 줄의 JavaScript 코드는 이러한 변수를 설정하고, 함께 묶어 클러스터에 전달하고, 결과를 콘솔에 출력하는 예제입니다:
1 2 3 4 5 |
const 쿼리스트랩 = "grand"; const 검색 인덱스 = 'travelsearch'; const 문자열 쿼리 = 카우치베이스.검색 쿼리.쿼리 문자열(쿼리스트랩); const 검색 결과 = 클러스터.검색 쿼리(검색 인덱스, 문자열 쿼리); 콘솔.로그(검색 결과); |
검색어 유형을 조정하려면 다음과 같이 바꾸세요. 쿼리 문자열
를 세 번째 줄에 다른 메서드와 함께 입력합니다. 다양한 유형의 코드 샘플은 Couchbase 전체 텍스트 검색 문서.
예를 들어 날짜 범위 쿼리는 다음과 같습니다:
const dateQuery = couchbase.SearchQuery.dateRange().start(startDate).end(endDate)
다음은 기본 로직이 포함된 전체 독립 실행형 스크립트 샘플입니다. 다음 섹션의 Express REST API 예제에 이를 빌드합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
var 카우치베이스 = require("couchbase"); 비동기 함수 메인(){ var 클러스터 = new 카우치베이스.클러스터("couchbase://localhost", { 사용자 이름: "관리자", 비밀번호: "관리자" }); var 버킷 = 클러스터.버킷("travel-sample"); var 컬렉션 = 버킷.기본 컬렉션(); const 쿼리스트랩 = "grand"; const 검색 인덱스 = 'travelsearch'; const 문자열 쿼리 = 카우치베이스.검색 쿼리.쿼리 문자열(쿼리스트랩); const 검색 결과 = 기다림 클러스터.검색 쿼리(검색 인덱스, 문자열 쿼리); 콘솔.로그(검색 결과); 만약 (검색 결과.메타.상태.실패 == 0) { 검색 결과.행.forEach((행)=>{ 콘솔.로그(행); }); } } 메인(); |
코드를 더 발전시키기
예제를 계속 진행하면서 이제 빌드한 REST API 코드에 추가할 수 있습니다. 지난 주 튜토리얼.
브라우저의 URL에서 검색 요청을 보낼 수 있도록 새 Express 라우팅과 함께 코드를 추가하세요. 이 경우 경로는 다음과 같습니다: /검색/[검색어]
- 예, /검색/그랜드
.
다음은 전체 텍스트 검색 쿼리를 작성하기 위한 경로 정의입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
앱.get('/검색/:검색기간', runAsync(비동기 (req, res) => { const 쿼리스트랩 = req.매개변수.검색 기간; const 검색 인덱스 = 'travelsearch'; const 문자열 쿼리 = 카우치베이스.검색 쿼리.쿼리 문자열(쿼리스트랩); const 검색 결과 = 기다림 클러스터.검색 쿼리( 검색 인덱스, 문자열 쿼리, // 자체 객체에 옵션을 추가합니다: { 시간 초과:2000, limit:5} ).catch((e)=>{콘솔.로그(e); throw e;}); 만약 (검색 결과.메타.상태.실패 == 0) { res.json(검색 결과); 검색 결과.행.forEach((행)=>{ 콘솔.로그(행); }) } })) |
문서 가져오기, N1QL 쿼리 및 검색 경로를 포함한 전체 작동 REST API 코드를 보려면 아래를 클릭하세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
var 앱 = require('express')(); var 카우치베이스 = require("couchbase"); 비동기 함수 메인() { 앱.get('/get/:docid', runAsync(비동기 (req, res) => { var docid = req.매개변수.docid; var docjson = 기다림 getDoc(docid, 함수(err, 결과){ res.json(결과.콘텐츠) }); res.json(docjson.콘텐츠); })); 앱.get('/쿼리/:도시명', runAsync(비동기 (req, res) => { var 도시 이름 = req.매개변수.도시 이름; var 쿼리스트랩 = `SELECT 유형, 이름, 도시 FROM `여행-샘플` WHERE city = $CITY;` var 매개변수 = { 매개변수: { CITY: 도시 이름}} 기다림 클러스터.쿼리(쿼리스트랩, 매개변수, 함수(err, 결과){ res.json(결과) }) })); 앱.get('/검색/:검색기간', runAsync(비동기 (req, res) => { const 쿼리스트랩 = req.매개변수.검색 기간; const 검색 인덱스 = 'travelsearch'; const 문자열 쿼리 = 카우치베이스.검색 쿼리.쿼리 문자열(쿼리스트랩); const 검색 결과 = 기다림 클러스터.검색 쿼리( 검색 인덱스, 문자열 쿼리, // 자체 객체에 옵션을 추가합니다: {시간 초과:2000, limit:5} ).catch((e)=>{콘솔.로그(e); throw e;}); 만약 (검색 결과.메타.상태.실패 == 0) { res.json(검색 결과); 검색 결과.행.forEach((행)=>{ 콘솔.로그(행); }) } })) 앱.듣기(3000, () => 콘솔.로그('포트 3000에서 수신 중')); 함수 runAsync (콜백) { 반환 함수 (req, res, 다음) { 콜백(req, res, 다음) .catch(다음) } } var 클러스터 = new 카우치베이스.클러스터("couchbase://localhost", { 사용자 이름: "관리자", 비밀번호: "관리자" }); var 버킷 = 클러스터.버킷("travel-sample"); var 컬렉션 = 버킷.기본 컬렉션(); var getDoc = 비동기 (키) => { var 결과 = 기다림 컬렉션.get(키); 콘솔.로그(결과) 반환 결과 } } 메인(); |
검색 쿼리 REST API 실행
포트 3000의 웹 브라우저에서 검색 경로를 통해 애플리케이션에 액세스합니다: http://localhost:3000/search/grand
.
검색 결과가 여기에 표시되며 일치하는 문서 ID 목록과 일치하는 문서의 순위 점수가 포함됩니다:
1 2 3 4 5 6 7 8 9 10 |
{"행":[{"index":"travelsearch_1bf0c4c01d25b582_4c1c5584","id":"landmark_21813","score":1.063667683545401,"sort":["_score"]}, {"index":"travelsearch_1bf0c4c01d25b582_4c1c5584","id":"airport_7057","score":1.016530994468649,"sort":["_score"]}, {"index":"travelsearch_1bf0c4c01d25b582_4c1c5584","id":"airport_4063","score":1.0098211451111556,"sort":["_score"]}, {"index":"travelsearch_1bf0c4c01d25b582_4c1c5584","id":"airport_3442","score":1.0098211451111556,"sort":["_score"]}, {"index":"travelsearch_1bf0c4c01d25b582_4c1c5584","id":"airport_6448","score":1.0032424768865669,"sort":["_score"]}], "meta":{"status":{"total":1,"실패":0,"성공":1},"요청":{"query":{"query":"grand"},"size":5,"from":0,"하이라이트":null, "fields":null,"facets":null,"설명":false, "sort":["-_score"],"includeLocations":false, "search_after":null,"search_before":null}, "조회수":[],"total_hits":169,"max_score":1.063667683545401,"취하다":208427,"facets":null}} |
검색 결과에는 총 조회 수/매치 수, 실행 시간 등을 보여주는 유용한 메타데이터도 포함되어 있습니다.
결론
검색 기반 애플리케이션에서 Couchbase를 사용할 수 있는 기회는 무궁무진합니다.
다양한 유형의 검색어와 기타 검색 옵션을 사용할 수 있으므로 아직 배울 것이 더 많습니다. 다음은 여러분이 고려해야 할 몇 가지 시작점입니다:
-
- 문서를 읽고 다른 유형의 검색 쿼리.
- 완료 Node.js 및 Couchbase 인증 과정.
- 다음을 수행하십시오. 무료 온라인 아키텍트 인증 과정 전체 텍스트 검색 등을 다루는
이것으로 Node.js와 Couchbase로 개발하기 시리즈를 마무리합니다. 앞으로도 자바스크립트와 함께하는 여정에 행운을 빕니다!
나머지 Node.js + Couchbase 방법 시리즈도 확인해 보세요: