2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Elasticsearch > Reactivesearchでいい感じの検索SPAを作るをやってみた

Last updated at Posted at 2020-10-06

Reactivesearch v3でいい感じの検索SPAを30分ぐらいで作る - Qiita

を参考に自分の環境でやってみたメモです。

install react app

npx create-react-app steam-search
cd steam-search

@appbaseio/reactivesearchを入れます。

yarn add @appbaseio/reactivesearch

起動

yarn start

起動が確認できたらsrc/App.jsを変更します。

src/App.js
import React, {Component} from 'react';
import {DataSearch, ReactiveBase, ReactiveList, ResultList, SelectedFilters} from '@appbaseio/reactivesearch';
import './App.css';

const { ResultListWrapper } = ReactiveList;

class App extends Component {
    render() {
        return (
            <div className="main-container">
                <ReactiveBase
                    app="steam-search"
                    url="http://localhost:9200"
                    credentials="elastic:changeme"
                >
                    <DataSearch
                        componentId="title"
                        dataField={["ResponseName"]}
                        queryFormat="and"
                    />
                    <SelectedFilters/>
                    <ReactiveList
                        componentId="resultLists"
                        dataField="ResponseName"
                        size={10}
                        pagination={true}
                        react={{
                            "and": ["title"]
                        }}
                    >
                        {({data}) => (
                            <ResultListWrapper>
                                {
                                    data.map(item => (
                                        <ResultList key={item._id}>
                                            <ResultList.Content>
                                                <ResultList.Title
                                                    dangerouslySetInnerHTML={{
                                                        __html: item.ResponseName
                                                    }}
                                                />
                                            </ResultList.Content>
                                        </ResultList>
                                    ))
                                }
                            </ResultListWrapper>
                        )}
                    </ReactiveList>
                </ReactiveBase>
            </div>
        );
    }
}

export default App;
  • appをElasticsearchに作ったIndex名に変更します。
    app="steam-search"
  • 認証を設定してなければ、credentials="elastic:changeme" の行ごと削除します。

以下の画面に変わったらOK。 変わらない場合には下段のCORSを参照して下さい
スクリーンショット 2020-10-06 17.39.20.png

CORS

画面が真っ白の場合にはCORSの設定がうまく行ってない可能性があります。

スクリーンショット 2020-10-06 17.35.50.png

from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

その場合には、elasticsearchの設定ファイルelasticsearch.yml
に追加します。

elasticsearch.yml
http.cors.enabled: true
http.cors.allow-origin: "*"

最終形

詳しい内容はReactivesearch v3でいい感じの検索SPAを30分ぐらいで作る - Qiita
を見ていただくとして、以下のように変更します。

app.js

import React, {Component} from 'react';
import {DataSearch, ReactiveBase, ReactiveList, ResultList, SelectedFilters} from '@appbaseio/reactivesearch';
import './App.css';
import './SteamSearch.css'

const {ResultListWrapper} = ReactiveList;

class App extends Component {
    render() {
        return (
            <div className="main-container">
                <ReactiveBase
                    app="steam-search" ← ElasticsearchのIndex名にする
                    url="http://localhost:9200"
                    credentials="elastic:changeme" ←  認証がなければ削除する
                    theme={
                        {
                            typography: {
                                fontFamily: 'Arial, Helvetica, sans-serif',
                                fontSize: '16px',
                            },
                            colors: {
                                titleColor: '#c7d5e0',
                                textColor: '#c7d5e0',
                                backgroundColor: '#212121',
                                primaryColor: '#2B475E',
                            }
                        }
                    }
                >
                    <DataSearch
                        componentId="title"
                        dataField={["ResponseName"]}
                        queryFormat="and"
                        placeholder="enter search term"
                        showIcon={false}
                        title="Steam Search"
                        className="data-search"
                        innerClass={{
                            input: 'input',
                            list: 'list',
                        }}
                    />
                    <SelectedFilters/>
                    <ReactiveList
                        componentId="resultLists"
                        dataField="ResponseName"
                        size={25}
                        pagination={true}
                        react={{
                            "and": ["title"]
                        }}
                        sortOptions={[
                            {label: "Best Match", dataField: "_score", sortBy: "desc"},
                            {label: "Lowest Price", dataField: "PriceInitial", sortBy: "asc"},
                            {label: "Highest Price", dataField: "PriceInitial", sortBy: "desc"},
                        ]}
                        className="result-list"
                        innerClass={{
                            resultsInfo: "resultsInfo",
                            resultStats: "resultStats",
                        }}
                    >
                        {({data}) => (
                            <ResultListWrapper>
                                {
                                    data.map(item => (
                                        <ResultList
                                            key={item._id}
                                            href={`https://store.steampowered.com/app/${item.ResponseID}`}
                                            className="listItem"
                                        >
                                            <ResultList.Image className="image" src={item.HeaderImage}/>
                                            <ResultList.Content>
                                                <ResultList.Title
                                                    dangerouslySetInnerHTML={{
                                                        __html: item.ResponseName
                                                    }}
                                                />
                                                <ResultList.Description>
                                                    <p className="releaseDate">{item.ReleaseDate}</p>
                                                    <p className="price">${item.PriceInitial}</p>
                                                </ResultList.Description>
                                            </ResultList.Content>
                                        </ResultList>
                                    ))
                                }
                            </ResultListWrapper>
                        )}
                    </ReactiveList>
                </ReactiveBase>
            </div>
        );
    }
}

export default App;

css

SteamSearch.css

SteamSearch.css
@font-face {
    font-family: "IonIcons";
    src: url("//code.ionicframework.com/ionicons/2.0.1/fonts/ionicons.eot?v=2.0.1");
    src: url("//code.ionicframework.com/ionicons/2.0.1/fonts/ionicons.eot?v=2.0.1#iefix") format("embedded-opentype"), url("//code.ionicframework.com/ionicons/2.0.1/fonts/ionicons.ttf?v=2.0.1") format("truetype"), url("//code.ionicframework.com/ionicons/2.0.1/fonts/ionicons.woff?v=2.0.1") format("woff"), url("//code.ionicframework.com/ionicons/2.0.1/fonts/ionicons.svg?v=2.0.1#Ionicons") format("svg");
    font-weight: normal;
    font-style: normal
}

html {
    min-height: 100%;
}

body {
    background-color: #1B3C53;
    background-image: linear-gradient(315deg, #000000 0%, #1B3C53 74%);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.main-container {
    width: 616px;
    margin-top: 20px;
}

.data-search .input {
    color: white;
}

.data-search .list li {
    background-color: #aaa !important;
    color: #000;
    overflow: hidden;
}

.data-search .list li:target {
    background-color: #666 !important;
}

.resultsInfo {
    position: relative;
}

.resultsInfo:before {
    z-index: 1;
    position: absolute;
    right: 15px;
    top: 0;
    content: "\f123";
    font-family: "IonIcons";
    line-height: 43px;
    color: #7F878C;
    pointer-events: none;
}

.resultsInfo select {
    background-color: #18394D;
    color: #67c1f5;
    outline: 1px solid #000;
    background: transparent;
    background-image: none;
    padding-right: 50px;
}

.resultsInfo option {
    background-color: #417A9B;
    color: #fff;
}

.result-list .resultStats {
    color: #3b6e8c;
}

.result-list .listItem {
    background-color: #16202D;
    padding: 0;
    margin: 2px 0;
    border: 0;
    background: rgba(0, 0, 0, 0.4);
}

.result-list .listItem:hover {
    background: rgba(0, 0, 0, 0.8);
}

.result-list .image {
    width: 120px;
    height: 45px;
}

.result-list article, .result-list article div {
    display: flex;
    align-items: center;
}

.result-list article h2 {
    padding: 0;
}

.releaseDate {
    color: #4c6c8c;
    width: 150px;
}

.price {
    width: 50px;
}

input {
    background-color: #1C3345 !important;
    border: 1px solid #000 !important;
}

スクリーンショット 2020-10-06 18.05.15.png

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?