added es code
This commit is contained in:
BIN
spring-boot/spring-boot-elasticsearch/.DS_Store
vendored
Normal file
BIN
spring-boot/spring-boot-elasticsearch/.DS_Store
vendored
Normal file
Binary file not shown.
117
spring-boot/spring-boot-elasticsearch/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
spring-boot/spring-boot-elasticsearch/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2007-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||
* use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||
".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||
".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if(mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if(mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if(!outputFile.getParentFile().exists()) {
|
||||
if(!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
||||
BIN
spring-boot/spring-boot-elasticsearch/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
spring-boot/spring-boot-elasticsearch/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
spring-boot/spring-boot-elasticsearch/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
spring-boot/spring-boot-elasticsearch/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
3
spring-boot/spring-boot-elasticsearch/README.md
Normal file
3
spring-boot/spring-boot-elasticsearch/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Related Blog Posts
|
||||
|
||||
* [How to Configure Logging Behavior with Spring Boot](https://reflectoring.io/springboot-logging/)
|
||||
3380
spring-boot/spring-boot-elasticsearch/app.log
Normal file
3380
spring-boot/spring-boot-elasticsearch/app.log
Normal file
File diff suppressed because it is too large
Load Diff
310
spring-boot/spring-boot-elasticsearch/mvnw
vendored
Executable file
310
spring-boot/spring-boot-elasticsearch/mvnw
vendored
Executable file
@@ -0,0 +1,310 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
182
spring-boot/spring-boot-elasticsearch/mvnw.cmd
vendored
Normal file
182
spring-boot/spring-boot-elasticsearch/mvnw.cmd
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
63
spring-boot/spring-boot-elasticsearch/pom.xml
Normal file
63
spring-boot/spring-boot-elasticsearch/pom.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.6.RELEASE</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>io.pratik.elasticsearch</groupId>
|
||||
<artifactId>productsearchapp</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>productsearchapp</name>
|
||||
<description>Demo project for Elasticsearch with Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
BIN
spring-boot/spring-boot-elasticsearch/src/.DS_Store
vendored
Normal file
BIN
spring-boot/spring-boot-elasticsearch/src/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
spring-boot/spring-boot-elasticsearch/src/main/.DS_Store
vendored
Normal file
BIN
spring-boot/spring-boot-elasticsearch/src/main/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
spring-boot/spring-boot-elasticsearch/src/main/java/.DS_Store
vendored
Normal file
BIN
spring-boot/spring-boot-elasticsearch/src/main/java/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
spring-boot/spring-boot-elasticsearch/src/main/java/io/.DS_Store
vendored
Normal file
BIN
spring-boot/spring-boot-elasticsearch/src/main/java/io/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.controllers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.services.ProductSearchService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
@Slf4j
|
||||
public class SearchController {
|
||||
|
||||
private ProductSearchService searchService;
|
||||
|
||||
@Autowired
|
||||
public SearchController(ProductSearchService searchService) {
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
@GetMapping("/products")
|
||||
@ResponseBody
|
||||
public List<Product> fetchByNameOrDesc(@RequestParam(value = "q", required = false) String query) {
|
||||
log.info("searching by name {}",query);
|
||||
List<Product> products = searchService.processSearch(query) ;
|
||||
log.info("products {}",products);
|
||||
return products;
|
||||
}
|
||||
|
||||
@GetMapping("/suggestions")
|
||||
@ResponseBody
|
||||
public List<String> fetchSuggestions(@RequestParam(value = "q", required = false) String query) {
|
||||
log.info("fetch suggests {}",query);
|
||||
List<String> suggests = searchService.fetchRecentSuggestions(query);
|
||||
log.info("suggests {}",suggests);
|
||||
return suggests;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.controllers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.services.SearchService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
@Slf4j
|
||||
public class UIController {
|
||||
|
||||
private SearchService searchService;
|
||||
|
||||
@Autowired
|
||||
public UIController(SearchService searchService) {
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
@GetMapping("/search")
|
||||
public String home(Model model) {
|
||||
List<Product> products = searchService.fetchProductNamesContaining("Hornby");
|
||||
|
||||
List<String> names = products.stream().flatMap(prod->{
|
||||
return Stream.of(prod.getName());
|
||||
}).collect(Collectors.toList());
|
||||
log.info("product names {}", names);
|
||||
model.addAttribute("names", names);
|
||||
return "search";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.models;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Document(indexName = "productindex")
|
||||
public class Product {
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@Field(type = FieldType.Text, name = "name")
|
||||
private String name;
|
||||
|
||||
@Field(type = FieldType.Double, name = "price")
|
||||
private Double price;
|
||||
|
||||
@Field(type = FieldType.Integer, name = "quantity")
|
||||
private Integer quantity;
|
||||
|
||||
@Field(type = FieldType.Keyword, name = "category")
|
||||
private String category;
|
||||
|
||||
@Field(type = FieldType.Text, name = "desc")
|
||||
private String description;
|
||||
|
||||
@Field(type = FieldType.Keyword, name = "manufacturer")
|
||||
private String manufacturer;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.models;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Document(indexName = "searchsuggest")
|
||||
public class SearchSuggest {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@Field(type = FieldType.Text)
|
||||
private String searchText;
|
||||
|
||||
@CreatedDate
|
||||
@Field(type = FieldType.Date, format = DateFormat.basic_date_time)
|
||||
private Instant creationDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.productsearchapp;
|
||||
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.RestClients;
|
||||
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableElasticsearchRepositories(basePackages = "io.pratik.elasticsearch.repositories")
|
||||
@ComponentScan(basePackages = { "io.pratik.elasticsearch" })
|
||||
public class ElasticsearchClientConfig extends AbstractElasticsearchConfiguration {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public RestHighLevelClient elasticsearchClient() {
|
||||
|
||||
final ClientConfiguration clientConfiguration =
|
||||
ClientConfiguration
|
||||
.builder()
|
||||
.connectedTo("localhost:9200")
|
||||
.build();
|
||||
|
||||
return RestClients
|
||||
.create(clientConfiguration)
|
||||
.rest();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package io.pratik.elasticsearch.productsearchapp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Scanner;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.repositories.ProductRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@SpringBootApplication
|
||||
@Slf4j
|
||||
public class ProductsearchappApplication {
|
||||
|
||||
private static final String COMMA_DELIMITER = ",";
|
||||
|
||||
@Autowired
|
||||
private ElasticsearchOperations esOps;
|
||||
|
||||
@Autowired
|
||||
private ProductRepository productRepo;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ProductsearchappApplication.class, args);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void deleteIndex() {
|
||||
esOps.indexOps(Product.class).delete();
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void buildIndex() {
|
||||
|
||||
esOps.indexOps(Product.class).refresh();
|
||||
productRepo.deleteAll();
|
||||
productRepo.saveAll(prepareDataset());
|
||||
}
|
||||
|
||||
private Collection<Product> prepareDataset() {
|
||||
Resource resource = new ClassPathResource("fashion-products.csv");
|
||||
List<Product> productList = new ArrayList<Product>();
|
||||
|
||||
try (
|
||||
InputStream input = resource.getInputStream();
|
||||
Scanner scanner = new Scanner(resource.getInputStream());) {
|
||||
int lineNo = 0;
|
||||
while (scanner.hasNextLine()) {
|
||||
++lineNo;
|
||||
String line = scanner.nextLine();
|
||||
if(lineNo == 1) continue;
|
||||
Optional<Product> product =
|
||||
csvRowToProductMapper(line);
|
||||
if(product.isPresent())
|
||||
productList.add(product.get());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("File read error {}",e);;
|
||||
}
|
||||
return productList;
|
||||
}
|
||||
|
||||
private Optional<Product> csvRowToProductMapper(final String line) {
|
||||
try (
|
||||
Scanner rowScanner = new Scanner(line)) {
|
||||
rowScanner.useDelimiter(COMMA_DELIMITER);
|
||||
while (rowScanner.hasNext()) {
|
||||
String name = rowScanner.next();
|
||||
String description = rowScanner.next();
|
||||
String manufacturer = rowScanner.next();
|
||||
return Optional.of(
|
||||
Product.builder()
|
||||
.name(name)
|
||||
.description(description)
|
||||
.manufacturer(manufacturer)
|
||||
.build());
|
||||
|
||||
}
|
||||
}
|
||||
return Optional.of(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.repositories;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
public interface ProductRepository extends ElasticsearchRepository<Product, String> {
|
||||
List<Product> findByName(String name);
|
||||
|
||||
List<Product> findByNameContaining(String name);
|
||||
|
||||
List<Product> findByManufacturerAndCategory(String manufacturer,String category);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.repositories;
|
||||
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import io.pratik.elasticsearch.models.SearchSuggest;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
public interface SearchSuggestRepository extends ElasticsearchRepository<SearchSuggest, String> {
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.services;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.models.SearchSuggest;
|
||||
import io.pratik.elasticsearch.repositories.SearchSuggestRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ProductSearchService {
|
||||
|
||||
private static final String PRODUCT_INDEX = "productindex";
|
||||
private static final String SEARCH_SUGGEST_INDEX = "searchsuggest";
|
||||
|
||||
private ElasticsearchOperations elasticsearchOperations;
|
||||
private SearchSuggestRepository searchSuggestRepository;
|
||||
|
||||
@Autowired
|
||||
public ProductSearchService(final ElasticsearchOperations elasticsearchOperations, final SearchSuggestRepository searchSuggestRepository) {
|
||||
super();
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
this.searchSuggestRepository = searchSuggestRepository;
|
||||
}
|
||||
|
||||
public List<String> createProductIndexBulk(final List<Product> products) {
|
||||
|
||||
List<IndexQuery> queries = products.stream()
|
||||
.map(product -> new IndexQueryBuilder().withId(product.getId().toString()).withObject(product).build())
|
||||
.collect(Collectors.toList());
|
||||
;
|
||||
|
||||
return elasticsearchOperations.bulkIndex(queries, IndexCoordinates.of(PRODUCT_INDEX));
|
||||
|
||||
}
|
||||
|
||||
public String createProductIndex(Product product) {
|
||||
|
||||
IndexQuery indexQuery = new IndexQueryBuilder().withId(product.getId().toString()).withObject(product).build();
|
||||
String documentId = elasticsearchOperations.index(indexQuery, IndexCoordinates.of(PRODUCT_INDEX));
|
||||
|
||||
return documentId;
|
||||
}
|
||||
|
||||
public void findProductCountByBrand(final String brandName) {
|
||||
QueryBuilder queryBuilder = QueryBuilders
|
||||
.matchQuery("manufacturer", brandName);
|
||||
// .fuzziness(0.8)
|
||||
// .boost(1.0f)
|
||||
// .prefixLength(0)
|
||||
// .fuzzyTranspositions(true);
|
||||
|
||||
Query searchQuery = new NativeSearchQueryBuilder()
|
||||
//.addAggregation(AggregationBuilders
|
||||
// .cardinality("category"))
|
||||
.withQuery(queryBuilder)
|
||||
.build();
|
||||
|
||||
SearchHits<Product> productHits =
|
||||
elasticsearchOperations
|
||||
.search(searchQuery, Product.class,
|
||||
IndexCoordinates.of(PRODUCT_INDEX));
|
||||
|
||||
log.info("productHits {} {}", productHits.getSearchHits().size(), productHits.getSearchHits());
|
||||
|
||||
List<SearchHit<Product>> srchHits =
|
||||
productHits.getSearchHits();
|
||||
int i = 0;
|
||||
for (SearchHit<Product> srchHit : srchHits) {
|
||||
log.info("srchHit {}", srchHit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void findByProductName(final String productName) {
|
||||
Query searchQuery = new StringQuery(
|
||||
"{ \"match\": { \"name\": { \"query\": \""+ productName + "\" } } } \"");
|
||||
|
||||
SearchHits<Product> products = elasticsearchOperations.search(searchQuery, Product.class,
|
||||
IndexCoordinates.of(PRODUCT_INDEX));
|
||||
}
|
||||
|
||||
public void findByProductPrice(final String productPrice) {
|
||||
Criteria criteria = new Criteria("price").greaterThan(10.0).lessThan(100.0);
|
||||
Query searchQuery = new CriteriaQuery(criteria);
|
||||
|
||||
SearchHits<Product> products = elasticsearchOperations.search(searchQuery, Product.class,
|
||||
IndexCoordinates.of(PRODUCT_INDEX));
|
||||
}
|
||||
|
||||
public List<Product> processSearch(final String query) {
|
||||
log.info("Search with query {}", query);
|
||||
|
||||
// 1. Update searchsuggest Index
|
||||
updateSuggestionsIndex(query);
|
||||
|
||||
// 2. Create query on multiple fields enabling fuzzy search
|
||||
QueryBuilder queryBuilder =
|
||||
QueryBuilders
|
||||
.multiMatchQuery(query, "name", "description")
|
||||
.fuzziness(Fuzziness.AUTO);
|
||||
|
||||
Query searchQuery = new NativeSearchQueryBuilder()
|
||||
.withFilter(queryBuilder)
|
||||
.build();
|
||||
|
||||
// 3. Execute search
|
||||
SearchHits<Product> productHits =
|
||||
elasticsearchOperations
|
||||
.search(searchQuery, Product.class,
|
||||
IndexCoordinates.of(PRODUCT_INDEX));
|
||||
|
||||
// 4. Map searchHits to product list
|
||||
List<Product> productMatches = new ArrayList<Product>();
|
||||
productHits.forEach(srchHit->{
|
||||
productMatches.add(srchHit.getContent());
|
||||
});
|
||||
return productMatches;
|
||||
}
|
||||
|
||||
|
||||
public void updateSuggestionsIndex(String query) {
|
||||
if(query.getBytes().length < 512) {
|
||||
searchSuggestRepository
|
||||
.save(SearchSuggest
|
||||
.builder()
|
||||
.id(query)
|
||||
.searchText(query)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> fetchRecentSuggestions(String query) {
|
||||
QueryBuilder queryBuilder = QueryBuilders
|
||||
.wildcardQuery("searchText", query+"*");
|
||||
|
||||
Query searchQuery = new NativeSearchQueryBuilder()
|
||||
.withFilter(queryBuilder).build();
|
||||
|
||||
SearchHits<SearchSuggest> searchSuggestions =
|
||||
elasticsearchOperations.search(searchQuery,
|
||||
SearchSuggest.class,
|
||||
IndexCoordinates.of(SEARCH_SUGGEST_INDEX));
|
||||
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
searchSuggestions.getSearchHits().forEach(srchHit->{
|
||||
suggestions.add(srchHit.getContent().getSearchText());
|
||||
});
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.repositories.ProductRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ProductSearchServiceWithRepo {
|
||||
|
||||
private ProductRepository productRepository;
|
||||
|
||||
@Autowired
|
||||
public ProductSearchServiceWithRepo(final ProductRepository productRepository) {
|
||||
super();
|
||||
this.productRepository = productRepository;
|
||||
}
|
||||
|
||||
public void createProductIndexBulk(final List<Product> products) {
|
||||
productRepository.saveAll(products);
|
||||
}
|
||||
|
||||
public void createProductIndex(final Product product) {
|
||||
productRepository.save(product);
|
||||
}
|
||||
|
||||
public List<Product> findProductsByManufacturerAndCategory(final String manufacturer, final String category) {
|
||||
return productRepository.findByManufacturerAndCategory(manufacturer, category);
|
||||
}
|
||||
|
||||
public List<Product> findByProductName(final String productName) {
|
||||
return productRepository.findByName(productName);
|
||||
}
|
||||
|
||||
public List<Product> findByProductMatchingNames(final String productName) {
|
||||
return productRepository.findByNameContaining(productName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.repositories.ProductRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class SearchService {
|
||||
|
||||
private ProductRepository productRepository;
|
||||
|
||||
private ElasticsearchOperations elasticsearchOperations;
|
||||
|
||||
@Autowired
|
||||
public SearchService(ProductRepository productRepository, ElasticsearchOperations elasticsearchOperations) {
|
||||
super();
|
||||
this.productRepository = productRepository;
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<Product> fetchProductNames(final String name){
|
||||
|
||||
return productRepository.findByManufacturerAndCategory(name, "");
|
||||
}
|
||||
|
||||
public List<Product> fetchProductNamesContaining(final String name){
|
||||
|
||||
|
||||
|
||||
return productRepository.findByNameContaining(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,49 @@
|
||||
<configuration debug="true">
|
||||
<include
|
||||
resource="/org/springframework/boot/logging/logback/base.xml" />
|
||||
<appender name="STDOUT"
|
||||
class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%X{user}] [%X{function}] [%thread]
|
||||
%-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>app.log</file>
|
||||
<rollingPolicy
|
||||
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${app.logPathPrefix}/myproject.%d{yyyy-MM-dd}.%i.log.gz
|
||||
</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy
|
||||
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>50MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [%thread]
|
||||
[%logger:%line] %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="ERROR" />
|
||||
<logger name="io.pratik" level="INFO" />
|
||||
<logger name="org.springframework.data.elasticsearch.client.WIRE" level="trace"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
<springProfile name="dev">
|
||||
<logger name="io.pratik" level="info" />
|
||||
</springProfile>
|
||||
<springProfile name="test">
|
||||
<logger name="io.pratik" level="trace" />
|
||||
</springProfile>
|
||||
</configuration>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head>
|
||||
<title>Product Search</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="card mb-3" style="max-width: 540px;">
|
||||
<p class="text-info">Search Products</p>
|
||||
<span class="border border-info">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" placeholder="Search Product by Name or description" aria-label="Product Name" aria-describedby="btnNameSearch" id="productNamedesc">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" id="btnNameSearch">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="results" class="card"></div>
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
$('#productNamedesc').autocomplete({
|
||||
source: function (request, response){
|
||||
$.get("http://localhost:8080/suggestions?",{q : request.term},function(data, status){
|
||||
$("#results").html("");
|
||||
if(status=='success'){
|
||||
response(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$("#btnNameSearch").click(function(){
|
||||
var inputText = $("#productNamedesc").val();
|
||||
if(inputText.length == 0) {
|
||||
alert("Enter product name or description");
|
||||
}else{
|
||||
var response = '';
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "http://localhost:8080/products?q="+inputText,
|
||||
async: true,
|
||||
success: function(resp) {
|
||||
var len = resp.length;
|
||||
var strHtml = "";
|
||||
if(len == 0) {
|
||||
$("#results").html("<p class='text-danger'>Zero matches</p>");
|
||||
}else{
|
||||
strHTML = "<p class='text-success'>"+len + " matches found.</p>";
|
||||
strHTML += "<ul class='list-unstyled'>";
|
||||
for(var i=0; i<len; i++){
|
||||
strHTML += "<li>"+resp[i].name+"</li>";
|
||||
}
|
||||
strHTML = strHTML + "</ul>";
|
||||
$("#results").html(strHTML)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.productsearchapp;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.services.ProductSearchService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
class ProductSearchServiceTest {
|
||||
|
||||
@Autowired
|
||||
private ProductSearchService productSearchService;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@AfterEach
|
||||
void tearDown() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#createProductIndexBulk(java.util.List)}.
|
||||
*/
|
||||
@Test
|
||||
void testCreateProductIndexBulk() {
|
||||
|
||||
List<Product> products = new ArrayList<Product>();
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("New Apple iPhone 12 Pro Max (128GB) - Pacific Blue")
|
||||
.category("phone")
|
||||
.price(2300.0)
|
||||
.quantity(55)
|
||||
.manufacturer("apple")
|
||||
.description("6.7-inch Super Retina XDR display\n" +
|
||||
"Ceramic Shield, tougher than any smartphone glass\n" +
|
||||
"A14 Bionic chip, the fastest chip ever in a smartphone\n" +
|
||||
"Pro camera system with 12MP Ultra Wide, Wide and Telephoto cameras; 5x optical zoom range; Night mode, Deep Fusion, Smart HDR 3, Apple ProRAW, 4K Dolby Vision HDR recording")
|
||||
.build()
|
||||
);
|
||||
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("New Apple iPhone 12 Mini (64GB) - Blue")
|
||||
.category("phone")
|
||||
.price(2300.0)
|
||||
.quantity(15)
|
||||
.manufacturer("apple")
|
||||
.description("5.4-inch Super Retina XDR display\n" +
|
||||
"Ceramic Shield, tougher than any smartphone glass\n" +
|
||||
"A14 Bionic chip, the fastest chip ever in a smartphone\n" +
|
||||
"Advanced dual-camera system with 12MP Ultra Wide and Wide cameras; Night mode, Deep Fusion, Smart HDR 3, 4K Dolby Vision HDR recording\n" +
|
||||
"12MP TrueDepth front camera with Night mode, 4K Dolby Vision HDR recording\n" +
|
||||
"Industry-leading IP68 water resistance")
|
||||
.build()
|
||||
);
|
||||
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("Samsung Galaxy Note10 Lite (Aura Glow, 8GB RAM, 128GB Storage)")
|
||||
.category("phone")
|
||||
.price(2100.0)
|
||||
.quantity(25)
|
||||
.manufacturer("samsung")
|
||||
.description("12MP Ultra wide (123°) FF + F2.2 \" Wide (77°) 12MP AF F1.7 Dual Pixel + Tele (45°) 12MP AF F2.4 OIS, 2x Zoom camera | 32MP front facing camera\n" +
|
||||
"17.04 centimeters (6.7-inch) super Amoled infinity-O display and FHD+ capacitive multi-touch touchscreen with 2400 x 1080 pixels resolution | 16M color support\n" +
|
||||
"Memory, Storage & SIM: 8GB RAM | 128GB internal memory expandable up to 1TB | Dual SIM dual-standby (4G+4G)\n" +
|
||||
"Android v10.0 operating system with 2.7GHz+1.8GHz Exynos 9810 octa core processor")
|
||||
.build()
|
||||
);
|
||||
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("Samsung 163 cm (65 Inches) Q Series 4K Ultra HD QLED")
|
||||
.category("television")
|
||||
.price(2100.0)
|
||||
.quantity(5)
|
||||
.manufacturer("samsung")
|
||||
.description("Resolution: 4K Ultra HD (3840x2160) | Refresh Rate: 120 hertz\n" +
|
||||
"Connectivity: 3 HDMI ports to connect set top box, Blu Ray players, gaming console | 2 USB ports to connect hard drives and other USB devices\n" +
|
||||
"Sound : 40 Watts Output\n" +
|
||||
"Display : QLED Panel | Q HDR Elite (HDR 10+) | Slim and stylish design")
|
||||
.build()
|
||||
);
|
||||
List<String> documentIDs = productSearchService.createProductIndexBulk(products );
|
||||
log.info("documentIDs {}", documentIDs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#createProductIndex(io.pratik.elasticsearch.models.Product)}.
|
||||
*/
|
||||
@Test
|
||||
void testCreateProductIndex() {
|
||||
final Product product = Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("Dell Vostro 3401 14inch FHD AG 2 Side Narrow Border Display Laptop")
|
||||
.category("laptop")
|
||||
.price(2100.0)
|
||||
.quantity(28)
|
||||
.manufacturer("dell")
|
||||
.description("Processor:10th Generation Intel Core i3-1005G1 Processor (4MB Cache, Base frequency 1.2 GHz)\n" +
|
||||
"Memory & Storage:4GB RAM 1TB 5400 rpm 2.5\" SATA Hard Drive\n" +
|
||||
"Display:14.0-inch FHD (1920 x 1080) Anti-glare LED Backlight 2 Side Narrow Border WVA Display")
|
||||
.build();
|
||||
String documentID = productSearchService.createProductIndex(product );
|
||||
log.info("documentID {}", documentID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#findProductCountByBrand(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
void testFindProductCountByBrand() {
|
||||
productSearchService.findProductCountByBrand("samsung");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#findByProductName(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
void testFindByProductName() {
|
||||
productSearchService.findByProductName("iphone");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#findByProductPrice(java.lang.String)}.
|
||||
*/
|
||||
@Test
|
||||
void testFindByProductPrice() {
|
||||
productSearchService.findByProductPrice("25.00");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testSearchByNameDesc() {
|
||||
List<Product> results = productSearchService.processSearch("apple");
|
||||
log.info("results {}",results);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSearchIndexUpdate() {
|
||||
productSearchService.updateSuggestionsIndex("samsng 163 cm");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchSearchSuggestions() {
|
||||
List<String> suggestions = productSearchService.fetchRecentSuggestions("samsng 163 cm");
|
||||
log.info("suggestions {}",suggestions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package io.pratik.elasticsearch.productsearchapp;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import io.pratik.elasticsearch.models.Product;
|
||||
import io.pratik.elasticsearch.services.ProductSearchServiceWithRepo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Pratik Das
|
||||
*
|
||||
*/
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
class ProductSearchServiceWithRepoTest {
|
||||
|
||||
@Autowired
|
||||
private ProductSearchServiceWithRepo productSearchServiceWithRepo;
|
||||
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@AfterEach
|
||||
void tearDown() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#createProductIndexBulk(java.util.List)}.
|
||||
*/
|
||||
@Test
|
||||
void testCreateProductIndexBulk() {
|
||||
|
||||
List<Product> products = new ArrayList<Product>();
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("New Apple iPhone 12 Pro Max (128GB) - Pacific Blue")
|
||||
.category("phone")
|
||||
.price(2300.0)
|
||||
.quantity(55)
|
||||
.manufacturer("apple")
|
||||
.description("6.7-inch Super Retina XDR display\n" +
|
||||
"Ceramic Shield, tougher than any smartphone glass\n" +
|
||||
"A14 Bionic chip, the fastest chip ever in a smartphone\n" +
|
||||
"Pro camera system with 12MP Ultra Wide, Wide and Telephoto cameras; 5x optical zoom range; Night mode, Deep Fusion, Smart HDR 3, Apple ProRAW, 4K Dolby Vision HDR recording")
|
||||
.build()
|
||||
);
|
||||
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("New Apple iPhone 12 Mini (64GB) - Blue")
|
||||
.category("phone")
|
||||
.price(2300.0)
|
||||
.quantity(15)
|
||||
.manufacturer("apple")
|
||||
.description("5.4-inch Super Retina XDR display\n" +
|
||||
"Ceramic Shield, tougher than any smartphone glass\n" +
|
||||
"A14 Bionic chip, the fastest chip ever in a smartphone\n" +
|
||||
"Advanced dual-camera system with 12MP Ultra Wide and Wide cameras; Night mode, Deep Fusion, Smart HDR 3, 4K Dolby Vision HDR recording\n" +
|
||||
"12MP TrueDepth front camera with Night mode, 4K Dolby Vision HDR recording\n" +
|
||||
"Industry-leading IP68 water resistance")
|
||||
.build()
|
||||
);
|
||||
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("Samsung Galaxy Note10 Lite (Aura Glow, 8GB RAM, 128GB Storage)")
|
||||
.category("phone")
|
||||
.price(2100.0)
|
||||
.quantity(25)
|
||||
.manufacturer("samsung")
|
||||
.description("12MP Ultra wide (123°) FF + F2.2 \" Wide (77°) 12MP AF F1.7 Dual Pixel + Tele (45°) 12MP AF F2.4 OIS, 2x Zoom camera | 32MP front facing camera\n" +
|
||||
"17.04 centimeters (6.7-inch) super Amoled infinity-O display and FHD+ capacitive multi-touch touchscreen with 2400 x 1080 pixels resolution | 16M color support\n" +
|
||||
"Memory, Storage & SIM: 8GB RAM | 128GB internal memory expandable up to 1TB | Dual SIM dual-standby (4G+4G)\n" +
|
||||
"Android v10.0 operating system with 2.7GHz+1.8GHz Exynos 9810 octa core processor")
|
||||
.build()
|
||||
);
|
||||
|
||||
products.add(Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("Samsung 163 cm (65 Inches) Q Series 4K Ultra HD QLED")
|
||||
.category("television")
|
||||
.price(2100.0)
|
||||
.quantity(5)
|
||||
.manufacturer("samsung")
|
||||
.description("Resolution: 4K Ultra HD (3840x2160) | Refresh Rate: 120 hertz\n" +
|
||||
"Connectivity: 3 HDMI ports to connect set top box, Blu Ray players, gaming console | 2 USB ports to connect hard drives and other USB devices\n" +
|
||||
"Sound : 40 Watts Output\n" +
|
||||
"Display : QLED Panel | Q HDR Elite (HDR 10+) | Slim and stylish design")
|
||||
.build()
|
||||
);
|
||||
productSearchServiceWithRepo.createProductIndexBulk(products );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link io.pratik.elasticsearch.services.ProductSearchService#createProductIndex(io.pratik.elasticsearch.models.Product)}.
|
||||
*/
|
||||
@Test
|
||||
void testCreateProductIndex() {
|
||||
final Product product = Product.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.name("Dell Vostro 3401 14inch FHD AG 2 Side Narrow Border Display Laptop")
|
||||
.category("laptop")
|
||||
.price(2100.0)
|
||||
.quantity(28)
|
||||
.manufacturer("dell")
|
||||
.description("Processor:10th Generation Intel Core i3-1005G1 Processor (4MB Cache, Base frequency 1.2 GHz)\n" +
|
||||
"Memory & Storage:4GB RAM 1TB 5400 rpm 2.5\" SATA Hard Drive\n" +
|
||||
"Display:14.0-inch FHD (1920 x 1080) Anti-glare LED Backlight 2 Side Narrow Border WVA Display")
|
||||
.build();
|
||||
productSearchServiceWithRepo.createProductIndex(product);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchProductByName() {
|
||||
List<Product> products = productSearchServiceWithRepo.findByProductName("apple");
|
||||
log.info("products {}",products);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchProductByManufacturerAndCategory() {
|
||||
List<Product> products = productSearchServiceWithRepo.findProductsByManufacturerAndCategory("samsung", "laptop");
|
||||
log.info("products {}",products);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchProductByManufacturer() {
|
||||
List<Product> products = productSearchServiceWithRepo.findProductsByManufacturerAndCategory("samsung", "laptop");
|
||||
log.info("products {}",products);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,49 @@
|
||||
<configuration debug="true">
|
||||
<include
|
||||
resource="/org/springframework/boot/logging/logback/base.xml" />
|
||||
<appender name="STDOUT"
|
||||
class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%X{user}] [%X{function}] [%thread]
|
||||
%-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>app.log</file>
|
||||
<rollingPolicy
|
||||
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${app.logPathPrefix}/myproject.%d{yyyy-MM-dd}.%i.log.gz
|
||||
</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy
|
||||
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>50MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [%thread]
|
||||
[%logger:%line] %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="ERROR" />
|
||||
<logger name="io.pratik" level="INFO" />
|
||||
<logger name="org.springframework.data.elasticsearch.client.WIRE" level="trace"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
<springProfile name="dev">
|
||||
<logger name="io.pratik" level="info" />
|
||||
</springProfile>
|
||||
<springProfile name="test">
|
||||
<logger name="io.pratik" level="trace" />
|
||||
</springProfile>
|
||||
</configuration>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head>
|
||||
<title>Product Search</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="card mb-3" style="max-width: 540px;">
|
||||
<p class="text-info">Search Products</p>
|
||||
<span class="border border-info">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" placeholder="Search Product by Name or description" aria-label="Product Name" aria-describedby="btnNameSearch" id="productNamedesc">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" id="btnNameSearch">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="results" class="card"></div>
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
$('#productNamedesc').autocomplete({
|
||||
source: function (request, response){
|
||||
$.get("http://localhost:8080/suggestions?",{q : request.term},function(data, status){
|
||||
$("#results").html("");
|
||||
if(status=='success'){
|
||||
response(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$("#btnNameSearch").click(function(){
|
||||
var inputText = $("#productNamedesc").val();
|
||||
if(inputText.length == 0) {
|
||||
alert("Enter product name or description");
|
||||
}else{
|
||||
var response = '';
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "http://localhost:8080/products?q="+inputText,
|
||||
async: true,
|
||||
success: function(resp) {
|
||||
var len = resp.length;
|
||||
var strHtml = "";
|
||||
if(len == 0) {
|
||||
$("#results").html("<p class='text-danger'>Zero matches</p>");
|
||||
}else{
|
||||
strHTML = "<p class='text-success'>"+len + " matches found.</p>";
|
||||
strHTML += "<ul class='list-unstyled'>";
|
||||
for(var i=0; i<len; i++){
|
||||
strHTML += "<li>"+resp[i].name+"</li>";
|
||||
}
|
||||
strHTML = strHTML + "</ul>";
|
||||
$("#results").html(strHTML)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
artifactId=productsearchapp
|
||||
groupId=io.pratik.elasticsearch
|
||||
version=0.0.1-SNAPSHOT
|
||||
@@ -0,0 +1,13 @@
|
||||
io/pratik/elasticsearch/services/ProductSearchServiceWithRepo.class
|
||||
io/pratik/elasticsearch/services/ProductSearchService.class
|
||||
io/pratik/elasticsearch/productsearchapp/ProductsearchappApplication.class
|
||||
io/pratik/elasticsearch/models/SearchSuggest$SearchSuggestBuilder.class
|
||||
io/pratik/elasticsearch/services/SearchService.class
|
||||
io/pratik/elasticsearch/models/Product.class
|
||||
io/pratik/elasticsearch/repositories/SearchSuggestRepository.class
|
||||
io/pratik/elasticsearch/productsearchapp/ElasticsearchClientConfig.class
|
||||
io/pratik/elasticsearch/controllers/UIController.class
|
||||
io/pratik/elasticsearch/controllers/SearchController.class
|
||||
io/pratik/elasticsearch/repositories/ProductRepository.class
|
||||
io/pratik/elasticsearch/models/Product$ProductBuilder.class
|
||||
io/pratik/elasticsearch/models/SearchSuggest.class
|
||||
@@ -0,0 +1,11 @@
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/repositories/ProductRepository.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/services/SearchService.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/models/SearchSuggest.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/controllers/UIController.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/controllers/SearchController.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/services/ProductSearchService.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/repositories/SearchSuggestRepository.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/productsearchapp/ElasticsearchClientConfig.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/services/ProductSearchServiceWithRepo.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/models/Product.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/main/java/io/pratik/elasticsearch/productsearchapp/ProductsearchappApplication.java
|
||||
@@ -0,0 +1,2 @@
|
||||
io/pratik/elasticsearch/productsearchapp/ProductSearchServiceTest.class
|
||||
io/pratik/elasticsearch/productsearchapp/ProductSearchServiceWithRepoTest.class
|
||||
@@ -0,0 +1,2 @@
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/test/java/io/pratik/elasticsearch/productsearchapp/ProductSearchServiceWithRepoTest.java
|
||||
/Users/fab/Documents/pratik/code-examples/spring-boot/spring-boot-elasticsearch/src/test/java/io/pratik/elasticsearch/productsearchapp/ProductSearchServiceTest.java
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
|
||||
-------------------------------------------------------------------------------
|
||||
Test set: io.pratik.elasticsearch.productsearchapp.ProductSearchServiceTest
|
||||
-------------------------------------------------------------------------------
|
||||
Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.224 s - in io.pratik.elasticsearch.productsearchapp.ProductSearchServiceTest
|
||||
@@ -0,0 +1,4 @@
|
||||
-------------------------------------------------------------------------------
|
||||
Test set: io.pratik.elasticsearch.productsearchapp.ProductSearchServiceWithRepoTest
|
||||
-------------------------------------------------------------------------------
|
||||
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.528 s - in io.pratik.elasticsearch.productsearchapp.ProductSearchServiceWithRepoTest
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user