From 5843ef9baac81e05781db478cd5a0d8f6a023ba7 Mon Sep 17 00:00:00 2001 From: Ahsan Bagwan Date: Thu, 24 Dec 2020 20:51:59 +0530 Subject: [PATCH] #394 - Configure searchstore in backend --- build.gradle | 1 + .../api/config/elide/ElideConfig.java | 16 ++++++++++++ .../com/faforever/api/data/domain/Avatar.java | 26 +++++++++++++++++++ .../api/data/domain/AvatarAssignment.java | 17 ++++++++++++ 4 files changed, 60 insertions(+) diff --git a/build.gradle b/build.gradle index 79f83f1bd..bbea9f849 100644 --- a/build.gradle +++ b/build.gradle @@ -232,6 +232,7 @@ dependencies { implementation("com.yahoo.elide:elide-core:${elideVersion}") implementation("com.yahoo.elide:elide-swagger:${elideVersion}") implementation("com.yahoo.elide:elide-datastore-hibernate5:${elideVersion}") + implementation("com.yahoo.elide:elide-datastore-search:${elideVersion}") implementation("org.luaj:luaj-jse:${luajVersion}") implementation("com.github.micheljung:nocatch:${nocatchVersion}") diff --git a/src/main/java/com/faforever/api/config/elide/ElideConfig.java b/src/main/java/com/faforever/api/config/elide/ElideConfig.java index bc1d6b1c4..ad01ecdcd 100644 --- a/src/main/java/com/faforever/api/config/elide/ElideConfig.java +++ b/src/main/java/com/faforever/api/config/elide/ElideConfig.java @@ -26,9 +26,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.yahoo.elide.Elide; import com.yahoo.elide.ElideSettingsBuilder; +import com.yahoo.elide.core.DataStore; import com.yahoo.elide.core.EntityDictionary; import com.yahoo.elide.core.filter.dialect.CaseSensitivityStrategy; import com.yahoo.elide.core.filter.dialect.RSQLFilterDialect; +import com.yahoo.elide.datastores.search.SearchDataStore; import com.yahoo.elide.jsonapi.JsonApiMapper; import com.yahoo.elide.security.checks.Check; import com.yahoo.elide.utils.coerce.CoerceUtil; @@ -41,6 +43,8 @@ import org.springframework.transaction.PlatformTransactionManager; import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; @@ -130,4 +134,16 @@ public EntityDictionary entityDictionary() { return new EntityDictionary(checks); } + + @Bean + public Elide initElideSearch(SpringHibernateDataStore springHibernateDataStore) { + DataStore store = springHibernateDataStore; + + EntityManagerFactory emf = Persistence.createEntityManagerFactory("searchDataStore"); + + boolean indexOnStartup = true; + DataStore searchStore = new SearchDataStore(store, emf, indexOnStartup); + + return new Elide(new ElideSettingsBuilder(searchStore).build()); + } } diff --git a/src/main/java/com/faforever/api/data/domain/Avatar.java b/src/main/java/com/faforever/api/data/domain/Avatar.java index de1825236..6fa2fd991 100644 --- a/src/main/java/com/faforever/api/data/domain/Avatar.java +++ b/src/main/java/com/faforever/api/data/domain/Avatar.java @@ -8,6 +8,18 @@ import com.yahoo.elide.annotation.Include; import com.yahoo.elide.annotation.UpdatePermission; import lombok.Setter; +import org.apache.lucene.analysis.core.LowerCaseFilterFactory; +import org.apache.lucene.analysis.ngram.NGramTokenizerFactory; +import org.hibernate.search.annotations.Analyze; +import org.hibernate.search.annotations.Analyzer; +import org.hibernate.search.annotations.AnalyzerDef; +import org.hibernate.search.annotations.Field; +import org.hibernate.search.annotations.Index; +import org.hibernate.search.annotations.Indexed; +import org.hibernate.search.annotations.Parameter; +import org.hibernate.search.annotations.Store; +import org.hibernate.search.annotations.TokenFilterDef; +import org.hibernate.search.annotations.TokenizerDef; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -22,6 +34,16 @@ @Entity @Table(name = "avatars_list") @Include(rootLevel = true, type = Avatar.TYPE_NAME) +@Indexed +@AnalyzerDef(name = "case_insensitive", + tokenizer = @TokenizerDef(factory = NGramTokenizerFactory.class, params = { + @Parameter(name = "minGramSize", value = "3"), + @Parameter(name = "maxGramSize", value = "10") + }), + filters = { + @TokenFilterDef(factory = LowerCaseFilterFactory.class) + } +) @Setter @Type(Avatar.TYPE_NAME) @EntityListeners(AvatarEnricherListener.class) @@ -42,10 +64,14 @@ public String getUrl() { @Column(name = "filename") @NotNull + @Field(index = Index.YES, analyze = Analyze.YES, + store = Store.NO, analyzer = @Analyzer(definition = "case_insensitive")) public String getFilename() { return filename; } @Column(name = "tooltip") @UpdatePermission(expression = WriteAvatarCheck.EXPRESSION) + @Field(index = Index.YES, analyze = Analyze.YES, + store = Store.NO, analyzer = @Analyzer(definition = "case_insensitive")) public String getTooltip() { return tooltip; } diff --git a/src/main/java/com/faforever/api/data/domain/AvatarAssignment.java b/src/main/java/com/faforever/api/data/domain/AvatarAssignment.java index 8fea0ae21..233dbeae6 100644 --- a/src/main/java/com/faforever/api/data/domain/AvatarAssignment.java +++ b/src/main/java/com/faforever/api/data/domain/AvatarAssignment.java @@ -12,6 +12,13 @@ import com.yahoo.elide.annotation.Include; import com.yahoo.elide.annotation.UpdatePermission; import lombok.Setter; +import org.apache.lucene.analysis.core.LowerCaseFilterFactory; +import org.apache.lucene.analysis.ngram.NGramTokenizerFactory; +import org.hibernate.search.annotations.AnalyzerDef; +import org.hibernate.search.annotations.Indexed; +import org.hibernate.search.annotations.Parameter; +import org.hibernate.search.annotations.TokenFilterDef; +import org.hibernate.search.annotations.TokenizerDef; import javax.persistence.Column; import javax.persistence.Entity; @@ -26,6 +33,16 @@ @Entity @Table(name = "avatars") @Include(rootLevel = true, type = AvatarAssignment.TYPE_NAME) +@Indexed +@AnalyzerDef(name = "case_insensitive", + tokenizer = @TokenizerDef(factory = NGramTokenizerFactory.class, params = { + @Parameter(name = "minGramSize", value = "3"), + @Parameter(name = "maxGramSize", value = "10") + }), + filters = { + @TokenFilterDef(factory = LowerCaseFilterFactory.class) + } +) @CreatePermission(expression = WriteAvatarCheck.EXPRESSION) @DeletePermission(expression = WriteAvatarCheck.EXPRESSION) @Audit(action = Action.CREATE, logStatement = "Avatar ''{0}'' has been assigned to player ''{1}''", logExpressions = {"${avatarAssignment.avatar.id}", "${avatarAssignment.player.id}"})