📜 목차

알고리즘

신고 결과 받기

셀프 스터디: 검색엔진 API 구현

알고리즘

📌 new Map()

typeof new Set() // 'object'
const obj = new Map()

obj.**set(**"name", "철수" )// 데이터 삽입, 키와 value 값 설정,obj["name"] = "철수" 와 같은 결과

console.log(obj.**get**("name")) // '철수'

obj.**has**("name") // true

obj.**delete**("name") // obj.**clear**() 와 같은 결과

////////////////////////////////////////////////////

const obj = { a : 1, b : 2, c : 3 }
const obj2 = new Map()

obj2.set("a", 1)
obj2.set("b", 2)
obj2.set("c", 3)

obj2.size // 3, 객체의 크기를 가져온다.
////////////////////////////////////////////////////

const a = { "a" : 1 }
obj = new Map()
obj.set(123, "1")
obj.set( a , "2" }

obj.get(123) // '1'

////////////////////////////////////////////////////
obj = new Map()
obj.set("1", 1)
obj.set("10", 10)
obj.set("5",5)

/*
Map(3) {
'1' => 1,
'10' => 10,
'5' => 5,
__proto__: {...}
}
*/

💭 신고 결과 받기

// 프로그래머스 <https://programmers.co.kr/learn/courses/30/lessons/92334#>

// 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
// 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
// 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
// k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
// 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.
// 다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고,
//  k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.

// 이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 
// 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 
// 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.

function solution(id_list, report, k) {
  const users = {}; // 신고당한 사람이 몇번 신고를 당했는지를 저장
  const reporter = {}; // 신고한 사람이 누구를 신고했는지를 저장
  const answer = [];
// report = Array.from( new Set(report) );

  for (let i = 0; i < report.length; i++) {
    const info = report[i].split(" ");

    // 신고당한 사람의 신고 횟수 누적하기(객체에 없다면, 초기값으로 0 설정)
    if (users[info[1]] === undefined) {
        users[info[1]] = 0;
    }

    // 신고한 사람이 누구를 신고했는지를 저장(객체에 없다면, 초기값으로 []을 설정)
    if (reporter[info[0]] === undefined) {
      reporter[info[0]] = [];
    }

    if ( reporter[ info[0] ].includes( info[1] ) === false ){
        reporter[info[0]].push(info[1])
        users[ info[1] ] ++
    }  
  }
  // 정지당한 유저를 신고한 유저한테 메일 보내기
  for (let i = 0; i < id_list.length; i++) {
    const arr = reporter[id_list[i]] || []
    answer[i] = 0;

    // 신고한 사람이 몇번 신고당했는지 정보 가져오기
    for (let l = 0; l < arr.length ; l++) {
      if ( users[arr[l]] >= k) {
        answer[i]++
      }
    }
  }
  return answer;
}

function solution(id_list, report, k) {
    let users = {}          // 신고당한 사람이 몇번 신고를 당했는지 저장
    let reporter = {}       // 신고한 사람이 누구를 신고했는지 저장

    report = Array.from( new Set(report) )
    report.forEach(el => {
        const info = el.split(" ")
        if( users [ info[1] ] === undefined )
            users [ info[1] ] = 0
        if( reporter[ info[0] ] === undefined )
            reporter[ info[0] ] = []
        
        users[info[1]]++
        reporter[info[0]].push(info[1])
        
    })  
    return id_list.map( name => {
        const arr = reporter[ name ] || []
        return arr.reduce( (acc,cur) => {
            return acc + ( users[cur] >= k ? 1 : 0)
        }, 0)
    })
}


셀프 스터디: 검색엔진 API 구현

준비

fetchProducts API


// backend/elk/logstash/logstash.conf

input {
    jdbc{
        jdbc_driver_library => "/usr/share/logstash/mysql-connector-java-8.0.28.jar"
        jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
        jdbc_connection_string => "jdbc:mysql://my-database:3306/mydocker02"
        jdbc_user => "root"
        jdbc_password => "root"
        schedule => "* * * * *"
        use_column_value => true
        tracking_column => "updatedat"
        tracking_column_type => "numeric"
        last_run_metadata_path => "./LOG_update.txt"
        **statement => "select tattooId, name_tattoo, price, unix_timestamp(updatedat) as updatedat from tattoo where unix_timestamp(updatedat) > :sql_last_value order by updatedat asc"**
    }
}

output {
    elasticsearch{
        hosts => "elasticsearch:9200"
        **index => "mytattoo"**
    }
}
// tattoo.resolver.ts
...
**import { ElasticsearchService } from '@nestjs/elasticsearch'
import { Cache } from 'cache-manager'**
import { **CACHE_MANAGER**, Inject } from '@nestjs/common'

@Resolver()
export class TattooResolver {
  constructor(
    private readonly tattooService: TattooService,
    **private readonly elasticsearchService: ElasticsearchService,

    @Inject(CACHE_MANAGER)
    private readonly cacheManager: Cache**
    ) {}

	// 타투 전체 목록 조회
  @Query( ()=> [Tattoo] )
  async fetchTattoos(@Args('search') search: string){
    // 1. Redis에 해당 검색결과가 있는지 확인
    // 초기값은 undefined, 검색 이력이 없다면(=Redis에 없다면) 바로 3-1.로 넘어간다
    const resultArr = []
    const inRedis = await this.cacheManager.get(`name_tattoo:${search}`)
    const inElastic = await this.elasticsearchService.search({
      index: "mytattoo",
      query: { prefix : { "name_tattoo" : search } },
    })

    // 2. Redis에 해당 검색결과가 있다면 결과를 클라이언트에 반환    
    if(inRedis) {
      console.log("🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑")
      console.log("🛑🛑🛑🛑🛑 Redis에 있던 검색 결과를 반환합니다. 🛑🛑🛑🛑")
      console.log(`Redis 값 : ${inRedis}`)
      console.log("🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑")
      return inRedis
    }

    // 3-1. Redis에 해당 검색결과가 없다면 해당 검색어를 ElasticSearch에서 검색
    else {
      for (let i = 0 ; i < inElastic.hits.total['value']; i++){
        resultArr.push(inElastic.hits.hits[i]['_source'])
      }
      // 3-2. 조회 결과를 Redis에 저장
      // 3-3. 조회결과([Product])를 클라이언트에 반환
      await this.cacheManager.set( `name_tattoo:${search}`, inElastic , { ttl: 0 } )
      console.log("👻👻👻👻👻 ElasticSearch에 있는 결과를 가져왔습니다. 👻👻👻👻👻")
      console.log(JSON.stringify(resultArr, null, ''))
      console.log("👻👻👻👻👻 ElasticSearch에 있는 결과를 가져왔습니다. 👻👻👻👻👻")
      return resultArr      
    }    
    // console.log(JSON.stringify(inElastic, null, ' '))
    // return this.tattooService.findAll();
  }