slice방식이 아닌 엘라스틱서치 연동방식으로 구현해 보았다..

import React, { useRef, useEffect, useState } from 'react';
import { useNavigate } from 'react-router';
import './main.css';
import MovieItem from './MovieItem';
import Pagination from './Pagination';

function ListMovie() {
    const [movies, setMovieList] = useState([]);
    const [movieLength, setMovieLength] = useState(0);
    //const [currentPage, setCurrentPage] = useState(1);
    const [postsPerPage, setPostsPerPage] = useState(10);
    const title = useRef();
    const navigate = useNavigate();

    function getList(url) {
        fetch(url)
            .then(response => { return response.json(); })
            .then(data => {
                setMovieList(data.content);
                setMovieLength(data.totalElements);
            });
    }

    function searchTitle(url) {
        fetch(url)
            .then(response => { return response.json(); })
            .then(data => {
               
                setMovieList(data);
               
            });
    }

    useEffect(() => { getList('/findAllMovies'); }, []);

    //const indexOfLast = currentPage * postsPerPage;  // 10
    //const indexOfFirst = indexOfLast - postsPerPage; // 0
    const currentMovies = (currentPage) => {
        getList(`/findAllMovies/${currentPage}`);
    };

    return (
        <>
            <h2>영화목록</h2>
            타이틀: <input name="title" ref={title} />
            <button type='button' onClick={() => {
                //const title = title.current.value;
                if (title.current.value == '') {
                    alert('제목을 입력하세요');
                    return false;
                }
                searchTitle(`/findByTitle/${title.current.value}`)

            }}>
                조회
            </button><br/><br/>
            <button onClick={() => navigate('/addMovie')}>영화 추가</button>
            등록된 영화수: {movieLength}
            <br/><br/>
            <div style={{
                display: 'grid',
                gridTemplateRows: '1fr',
                gridTemplateColumns: '1fr 1fr 1fr 1fr'
            }}>
                {movies.map(
                    ({ id , title, price, synopsis }) => (
                        <MovieItem
                            id={id}
                            title={title}
                            price={price}
                           
                        />
                    )
                )}
            </div>
            <Pagination
                postsPerPage={postsPerPage}
                totalPosts={movieLength}
                paginate={currentMovies}></Pagination>
        </>
    )
}

export default ListMovie;

차이점은 currentPage대신에 Spring Boot에서 페이징(엘라스틱 서치 연동)하는 방식이다.

데이터가 많을 경우 이방식으로 하자.

 

Spring 소스

MovieRepository.java

package com.oraclejava.es.api.repository;

 

import java.util.List;

 

import org.springframework.data.domain.Page;

import org.springframework.data.domain.Pageable;

import org.springframework.data.domain.Sort;

import org.springframework.data.elasticsearch.annotations.Query;

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

 

import com.oraclejava.es.api.model.Movie;

 

public interface MovieRepository extends ElasticsearchRepository<Movie, String>{

 

//List<Movie> findAll(Sort sort);

Page<Movie> findAll(Pageable pageable);

 

@Query("{\"bool\": {\r\n"

+ " \"should\": [\r\n"

+ " {\r\n"

+ " \"match\": {\r\n"

+ " \"title.nori\": \"?0\"\r\n"

+ " }\r\n"

+ " },\r\n"

+ " {\r\n"

+ " \"match\": {\r\n"

+ " \"synopsis.nori\": \"?0\"\r\n"

+ " }\r\n"

+ " }\r\n"

+ " ]\r\n"

+ " }}")

List<Movie> findByTitle(String title);

}

 

 

MovieRestController.java

package com.oraclejava.es.api.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.oraclejava.es.api.model.Movie;
import com.oraclejava.es.api.repository.MovieRepository;

@RestController
public class MovieRestController {

@Autowired
private MovieRepository movieRepository;

@PostMapping("/saveMovie")
public int saveMovie(@RequestBody List<Movie> movies) {
movieRepository.saveAll(movies);
return movies.size();
}

@DeleteMapping("/deleteMovie/{id}")
public String deleteMovie(@PathVariable String id) {
movieRepository.deleteById(id);
return id;
}

@GetMapping({"/findAllMovies/{page}", "/findAllMovies"})
public Iterable<Movie> findAllMovies(@PathVariable(required = false) Integer page) {
page = (page == null) ? 1 : page;
return movieRepository.findAll(PageRequest.of(page-1, 10, Sort.by("title")));
}

@GetMapping("/findByTitle/{title}")
public List<Movie> findByTitle(@PathVariable String title) {
return movieRepository.findByTitle(title);
}

@GetMapping("/detailMovie/{id}")
public Movie detail(@PathVariable String id) {
System.out.println(id);
return movieRepository.findById(id).get();
}
}









+ Recent posts