diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 01b97d8..4a68e42 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: java: ['8', '11', '17'] services: typesense: - image: typesense/typesense:27.0 + image: typesense/typesense:28.0.rc36 ports: - 8108:8108/tcp volumes: diff --git a/src/main/java/org/typesense/api/Client.java b/src/main/java/org/typesense/api/Client.java index 84e94f0..7215485 100644 --- a/src/main/java/org/typesense/api/Client.java +++ b/src/main/java/org/typesense/api/Client.java @@ -21,6 +21,8 @@ public class Client { private Analytics analytics; + private Stemming stemming; + private Stopwords stopwords; private Map individualStopwordsSets; @@ -45,6 +47,7 @@ public Client(Configuration configuration){ this.debug = new Debug(this.apiCall); this.multiSearch = new MultiSearch(this.apiCall); this.analytics = new Analytics(this.apiCall); + this.stemming = new Stemming(this.apiCall); this.stopwords = new Stopwords(this.apiCall); this.individualStopwordsSets = new HashMap<>(); } @@ -100,6 +103,10 @@ public Analytics analytics(){ return this.analytics; } + public Stemming stemming(){ + return this.stemming; + } + public Stopwords stopwords() { return this.stopwords; } diff --git a/src/main/java/org/typesense/api/Stemming.java b/src/main/java/org/typesense/api/Stemming.java new file mode 100644 index 0000000..0942c5d --- /dev/null +++ b/src/main/java/org/typesense/api/Stemming.java @@ -0,0 +1,32 @@ +package org.typesense.api; + +import java.util.HashMap; +import java.util.Map; + +public class Stemming { + private final ApiCall apiCall; + private final StemmingDictionaries dictionaries; + private final Map individualDictionaries; + + + public Stemming(ApiCall apiCall) { + this.apiCall = apiCall; + this.dictionaries = new StemmingDictionaries(this.apiCall); + this.individualDictionaries = new HashMap<>(); + } + + public StemmingDictionaries dictionaries() { + return this.dictionaries; + } + + public StemmingDictionary dictionaries(String dictionaryId) { + StemmingDictionary retVal; + + if (!this.individualDictionaries.containsKey(dictionaryId)) { + this.individualDictionaries.put(dictionaryId, new StemmingDictionary(dictionaryId, apiCall)); + } + + retVal = this.individualDictionaries.get(dictionaryId); + return retVal; + } +} diff --git a/src/main/java/org/typesense/api/StemmingDictionaries.java b/src/main/java/org/typesense/api/StemmingDictionaries.java new file mode 100644 index 0000000..f97842b --- /dev/null +++ b/src/main/java/org/typesense/api/StemmingDictionaries.java @@ -0,0 +1,59 @@ +package org.typesense.api; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.typesense.model.StemmingDictionaryWords; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class StemmingDictionaries { + private final ApiCall apiCall; + public final static String RESOURCE_PATH = "/stemming/dictionaries"; + + public StemmingDictionaries(ApiCall apiCall) { + this.apiCall = apiCall; + } + + public String upsert(String dictionaryId, String wordRootCombinations) throws Exception { + Map params = Collections.singletonMap("id", dictionaryId); + + return this.apiCall.post(this.getEndPoint("import"), wordRootCombinations, params, String.class); + } + + public List upsert(String dictionaryId, List wordRootCombinations) + throws Exception { + ObjectMapper mapper = new ObjectMapper(); + List jsonLines = new ArrayList<>(); + List objectList = new ArrayList<>(); + + for (StemmingDictionaryWords word : wordRootCombinations) { + jsonLines.add(mapper.writeValueAsString(word)); + } + + String reqBody = String.join("\n", jsonLines); + + Map params = Collections.singletonMap("id", dictionaryId); + + String resInJsonLineFormat = this.apiCall.post(this.getEndPoint("import"), reqBody, params, String.class); + + for (String line : resInJsonLineFormat.split("\n")) { + objectList.add(mapper.readValue(line, StemmingDictionaryWords.class)); + } + + return objectList; + } + + public StemmingDictionariesRetrieveSchema retrieve() throws Exception { + StemmingDictionariesRetrieveSchema response = this.apiCall.get(RESOURCE_PATH, null, + StemmingDictionariesRetrieveSchema.class); + return response != null ? response : new StemmingDictionariesRetrieveSchema(); + } + + public String getEndPoint(String target) { + return RESOURCE_PATH + "/" + target; + } + +} \ No newline at end of file diff --git a/src/main/java/org/typesense/api/StemmingDictionariesRetrieveSchema.java b/src/main/java/org/typesense/api/StemmingDictionariesRetrieveSchema.java new file mode 100644 index 0000000..aa956ac --- /dev/null +++ b/src/main/java/org/typesense/api/StemmingDictionariesRetrieveSchema.java @@ -0,0 +1,15 @@ +package org.typesense.api; + +import java.util.List; + +public class StemmingDictionariesRetrieveSchema { + private List dictionaries; + + public List getDictionaries() { + return dictionaries; + } + + public void setDictionaries(List dictionaries) { + this.dictionaries = dictionaries; + } +} \ No newline at end of file diff --git a/src/main/java/org/typesense/api/StemmingDictionary.java b/src/main/java/org/typesense/api/StemmingDictionary.java new file mode 100644 index 0000000..b13e69f --- /dev/null +++ b/src/main/java/org/typesense/api/StemmingDictionary.java @@ -0,0 +1,23 @@ +package org.typesense.api; + +import org.typesense.api.utils.URLEncoding; + +public class StemmingDictionary { + private final ApiCall apiCall; + private final String dictionaryId; + + public StemmingDictionary(String dictionaryId, ApiCall apiCall) { + this.apiCall = apiCall; + this.dictionaryId = dictionaryId; + } + + + public org.typesense.model.StemmingDictionary retrieve() throws Exception { + return this.apiCall.get(this.getEndpoint(), null, org.typesense.model.StemmingDictionary.class); + } + + private String getEndpoint() { + return StemmingDictionaries.RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(this.dictionaryId); + } + +} \ No newline at end of file diff --git a/src/test/java/org/typesense/api/Helper.java b/src/test/java/org/typesense/api/Helper.java index de910e3..8943d39 100644 --- a/src/test/java/org/typesense/api/Helper.java +++ b/src/test/java/org/typesense/api/Helper.java @@ -25,6 +25,7 @@ import org.typesense.model.SearchOverrideRule; import org.typesense.model.SearchOverrideSchema; import org.typesense.model.SearchSynonymSchema; +import org.typesense.model.StemmingDictionaryWords; import org.typesense.model.StopwordsSetSchema; import org.typesense.model.StopwordsSetUpsertSchema; import org.typesense.model.StopwordsSetsRetrieveAllSchema; @@ -140,6 +141,16 @@ public void createTestStopwordsSet() throws Exception { client.stopwords().upsert("common-words", stopwordsSetSchema); } + + public void createStemmingDictionary() throws Exception{ + List stemmingDictionaryWords = new ArrayList<>(); + + stemmingDictionaryWords.add(new StemmingDictionaryWords().word("ran").root("run")); + stemmingDictionaryWords.add(new StemmingDictionaryWords().word("running").root("run")); + + client.stemming().dictionaries().upsert("irregular-plurals", stemmingDictionaryWords); + } + public void teardown() throws Exception { CollectionResponse[] collectionResponses = client.collections().retrieve(); for (CollectionResponse c : collectionResponses) { diff --git a/src/test/java/org/typesense/api/StemmingTest.java b/src/test/java/org/typesense/api/StemmingTest.java new file mode 100644 index 0000000..5122f68 --- /dev/null +++ b/src/test/java/org/typesense/api/StemmingTest.java @@ -0,0 +1,54 @@ +package org.typesense.api; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.typesense.model.StemmingDictionary; +import org.typesense.model.StemmingDictionaryWords; + +public class StemmingTest { + private Client client; + private Helper helper; + + @BeforeEach + void setUp() throws Exception { + helper = new Helper(); + helper.teardown(); + client = helper.getClient(); + helper.createStemmingDictionary(); + } + + @Test + void testUpsert() throws Exception { + List stemmingDictionaryWords = new ArrayList<>(); + + stemmingDictionaryWords.add(new StemmingDictionaryWords().word("ran").root("run")); + stemmingDictionaryWords.add(new StemmingDictionaryWords().word("running").root("run")); + + List res = client.stemming().dictionaries().upsert("irregular-plurals", + stemmingDictionaryWords); + + assertEquals(2, res.size()); + assertEquals("ran", res.get(0).getWord()); + assertEquals("run", res.get(0).getRoot()); + assertEquals("running", res.get(1).getWord()); + assertEquals("run", res.get(1).getRoot()); + } + + @Test + void testRetrieveOne() throws Exception { + StemmingDictionary res = client.stemming().dictionaries("irregular-plurals").retrieve(); + assertEquals("irregular-plurals", res.getId()); + assertEquals(2, res.getWords().size()); + } + + @Test + void testRetrieveAll() throws Exception { + StemmingDictionariesRetrieveSchema res = client.stemming().dictionaries().retrieve(); + assertEquals(1, res.getDictionaries().size()); + assertEquals("irregular-plurals", res.getDictionaries().get(0)); + } +}