안녕하세요

MongoDB - Search Index: 이진탐색으로 게시물 찾기 본문

스터디/코딩애플

MongoDB - Search Index: 이진탐색으로 게시물 찾기

sakuraop 2023. 1. 6. 04:39

이진탐색으로 게시물 찾기

1. 이진탐색이 어떤거죠?

id가 1~100의 게시물이 있다면 ,

50이상인지 확인 >
75이상인지 확인 >
87이상인지 확인...

이렇게 범위를 절반으로 좁혀나가며 찾는 방식으로
순서대로 정렬되어있는 경우에 이용 가능합니다.

id는 보면 순서대로 정렬이 되어있지만, 
제목은 정렬이 되어있지 않기 때문에 이를 정렬해야 이진탐색을 이용할 수 있습니다.

그러기 위해서는 이 제목을 정렬된 collection으로 만들어야 합니다.

원본을 수정하는 것이 아니라. 문자열로 정렬된 사본을 만드는 것입니다.
indexing: 정렬된 collection 사본을 만드는 것

 

 

 

2. Text Indexing을 해봅시다.

게시물 정렬을 직접 하는 것이 아니라 DB에서 기능을 지원해줍니다.

indexing을 하길 원하는 collection에서 에서 indexes를 클릭합니다.

 

 

Create Index 버튼을 클릭합니다.

 

 

"키이름": "정렬타입" 을 설정해줍니다.

문자정렬: "text"

숫자정렬: 1 (아니면 -1)

 

 

 

review > create 버튼 누르면 생성됩니다.

 

 

 

3. Text Indexing을 통해 정렬된 게시물들로 검색해봅시다.

app.get("/search", (요청, 응답) => {
  const 검색어 = 요청.query.value;
  db.collection("post").find({ $text: { $search: 요청.query.value } }).toArray((에러, 결과) => {
      응답.render("searchList.ejs", { searchResult: 결과 });
    });
});
이렇게 하면 됩니다.
그런데 MongoDB 텍스트는 띄어쓰기 기준으로 문자들을 구분하기 때문에 한글 친화적이지 않습니다.

검색 결과가 어절로 정확하게 검색되어야 하므로 원하는 결과가 나오지 않을 확률이 높습니다.

 

 

해결책 (text index 쓰지 마셈)

1. 일부분만 찾아라.

최근 게시물 중 1000개만 찾기,

작성된 지 7일 이하 게시물 등등

 

2. nGram이라 하여 두글자씩 text index를 만들기

한마디로 text index를 다른 방법으로 구현하는 것입니다.

 

3. search index 를 쓰자

 

 

 

 

4. search index로 한글친화적인 검색기능 구현하기

Search 찾아서 Create Search Index 버튼 누릅니다.

 

 

index 이름 정하고 collection을 선택합니다.

 

 

Refine 이라는 버튼 찾아 클릭하고 korean 설정 찾아서 해줍니다. 

~을 ~를 같은 조사를 없애 한글 친화적인 검색 결과를 얻어낼 수 있습니다.

 

 

생성하기 버튼 누르고 기다리면 아래와 같은 index가 생성됩니다.

(DB용량을 차지하므로 필요할 때만 사용합니다.)

 

 

aggregate 라는 메서드를 이용하는데, 형식이 정해져 있습니다.

app.get("/search", (요청, 응답) => {
  const 검색조건 = [
    {
      $search: {
        index: "인덱스이름",
        text: {
          query: 요청.query.value,
          path: "제목", // 여러가지 조건을 찾고 싶으면 ['제목', '날짜']
        },
      },
    },
    // 정렬기능
    { $sort: { _id: 1 } },
    // 표시할 최대 갯수
    { $limit: 5 },
  ];
  db.collection("post").aggregate(검색조건).toArray((에러, 결과) => {
      응답.render("searchList.ejs", { searchResult: 결과 });
    });
});

app.get("/search", (요청, 응답) => {
  const 검색조건 = [{
      $search: {
        index: "인덱스이름",
        text: {
          query: 요청.query.value,
          path: "제목",
        },},},
    // 정렬기능
    { $sort: { _id: 1 } },
    // 표시할 최대 갯수
    { $limit: 5 },
  ];
  db.collection("post").aggregate(검색조건).toArray((에러, 결과) => {
      응답.render("searchList.ejs", { searchResult: 결과 });
    });
});

 

 

 

 

5. 검색 해봅시다.

 

 

"밥" 검색해보면

"밥잘먹기"는 안나오고

"밥 잘 먹기"는 나옵니다.

 

"먹기" 검색해보면 둘다 나옵니다.

 

그런 알고리즘 인가 봅니다.