Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(analytics): add analytics rules and events support #72

Merged
merged 3 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,62 @@ client.collections("Countries").delete();
client.collections("Countries").documents().export();
```

### Create an analytics rule
```java
AnalyticsRuleSchema analyticsRule = new AnalyticsRuleSchema();
analyticsRule.setName("popular-queries");
analyticsRule.setType(AnalyticsRuleSchema.TypeEnum.POPULAR_QUERIES);
analyticsRule.setParams(new AnalyticsRuleParameters()
.source(new AnalyticsRuleParametersSource()
.collections(Arrays.asList("Countries")))
.destination(new AnalyticsRuleParametersDestination()
.collection("top_searches")));

client.analytics().rules().create(analyticsRule);
```

### Upsert an analytics rule
```java
AnalyticsRuleUpsertSchema analyticsRule = new AnalyticsRuleUpsertSchema()
.type(AnalyticsRuleUpsertSchema.TypeEnum.NOHITS_QUERIES)
.params(new AnalyticsRuleParameters()
.source(new AnalyticsRuleParametersSource()
.collections(Arrays.asList("Countries")))
.destination(new AnalyticsRuleParametersDestination()
.collection("failed_searches")));

client.analytics().rules().upsert("failed-searches", analyticsRule);
```

### Retrieve all analytics rules
```java
AnalyticsRulesRetrieveSchema rules = client.analytics().rules().retrieve();
```

### Retrieve a single analytics rule
```java
AnalyticsRuleSchema rule = client.analytics().rules("failed-searches").retrieve();
```

### Delete an analytics rule
```java
client.analytics().rules("failed-searches").delete();
```

#### Create an analytics event
```java
AnalyticsEventCreateSchema analyticsEvent = new AnalyticsEventCreateSchema()
.type("conversion")
.name("purchase_made")
.data(Map.of(
"product_id", "123",
"user_id", "user_456",
"amount", "99.99"
));

client.analytics().events().create(analyticsEvent);
```

### Create an API key
```java
ApiKeySchema apiKeySchema = new ApiKeySchema();
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/org/typesense/api/Analytics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.typesense.api;

import java.util.HashMap;
import java.util.Map;

public class Analytics {
private final ApiCall apiCall;
private final AnalyticsRules rules;
private final Map<String, AnalyticsRule> individualRules;
private final AnalyticsEvents events;

public Analytics(ApiCall apiCall) {
this.apiCall = apiCall;
this.rules = new AnalyticsRules(this.apiCall);
this.individualRules = new HashMap<>();
this.events = new AnalyticsEvents(this.apiCall);
}

public AnalyticsRules rules() {
return this.rules;
}

public AnalyticsRule rules(String ruleId) {
AnalyticsRule retVal;

if (!this.individualRules.containsKey(ruleId)) {
this.individualRules.put(ruleId, new AnalyticsRule(ruleId, apiCall));
}

retVal = this.individualRules.get(ruleId);
return retVal;
}

public AnalyticsEvents events() {
return this.events;
}
}
18 changes: 18 additions & 0 deletions src/main/java/org/typesense/api/AnalyticsEvents.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.typesense.api;

import org.typesense.model.AnalyticsEventCreateResponse;
import org.typesense.model.AnalyticsEventCreateSchema;


public class AnalyticsEvents {
private final ApiCall apiCall;
public final static String RESOURCE_PATH = "/analytics/events";

public AnalyticsEvents(ApiCall apiCall) {
this.apiCall = apiCall;
}

public AnalyticsEventCreateResponse create(AnalyticsEventCreateSchema event) throws Exception {
return this.apiCall.post(RESOURCE_PATH, event, null, AnalyticsEventCreateResponse.class);
}
}
29 changes: 29 additions & 0 deletions src/main/java/org/typesense/api/AnalyticsRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.typesense.api;

import org.typesense.api.utils.URLEncoding;
import org.typesense.model.AnalyticsRuleDeleteResponse;
import org.typesense.model.AnalyticsRuleSchema;

public class AnalyticsRule {
private final ApiCall apiCall;
private final String ruleId;

public AnalyticsRule(String ruleId, ApiCall apiCall) {
this.apiCall = apiCall;
this.ruleId = ruleId;
}


public AnalyticsRuleSchema retrieve() throws Exception {
return this.apiCall.get(this.getEndpoint(), null, AnalyticsRuleSchema.class);
}

public AnalyticsRuleDeleteResponse delete() throws Exception {
return this.apiCall.delete(this.getEndpoint(), null, AnalyticsRuleDeleteResponse.class);
}

private String getEndpoint() {
return AnalyticsRules.RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(ruleId);
}

}
30 changes: 30 additions & 0 deletions src/main/java/org/typesense/api/AnalyticsRules.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.typesense.api;

import org.typesense.api.utils.URLEncoding;
import org.typesense.model.AnalyticsRuleSchema;
import org.typesense.model.AnalyticsRuleUpsertSchema;
import org.typesense.model.AnalyticsRulesRetrieveSchema;

public class AnalyticsRules {

private final ApiCall apiCall;
public final static String RESOURCE_PATH = "/analytics/rules";

public AnalyticsRules(ApiCall apiCall) {
this.apiCall = apiCall;
}

public AnalyticsRuleSchema create(AnalyticsRuleSchema rule) throws Exception {
return this.apiCall.post(RESOURCE_PATH, rule, null, AnalyticsRuleSchema.class);
}

public AnalyticsRuleSchema upsert(String name, AnalyticsRuleUpsertSchema rule) throws Exception {
return this.apiCall.put(RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(name), rule, null,
AnalyticsRuleSchema.class);
}

public AnalyticsRulesRetrieveSchema retrieve() throws Exception {
return this.apiCall.get(RESOURCE_PATH, null, AnalyticsRulesRetrieveSchema.class);
}

}
9 changes: 9 additions & 0 deletions src/main/java/org/typesense/api/Client.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.typesense.api;


import java.util.HashMap;
import java.util.Map;

Expand All @@ -17,6 +18,9 @@ public class Client {
private Keys keys;
private Map<Long, Key> individualKeys;


private Analytics analytics;

public Health health;
public Operations operations;
public Metrics metrics;
Expand All @@ -37,6 +41,7 @@ public Client(Configuration configuration){
this.metrics = new Metrics(this.apiCall);
this.debug = new Debug(this.apiCall);
this.multiSearch = new MultiSearch(this.apiCall);
this.analytics = new Analytics(this.apiCall);
}

public Collection collections(String name){
Expand Down Expand Up @@ -85,4 +90,8 @@ public Key keys(Long id){
retVal = this.individualKeys.get(id);
return retVal;
}

public Analytics analytics(){
return this.analytics;
}
}
48 changes: 48 additions & 0 deletions src/test/java/org/typesense/api/AnalyticsEventsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.typesense.api;

import java.util.HashMap;

import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.typesense.model.AnalyticsEventCreateResponse;
import org.typesense.model.AnalyticsEventCreateSchema;

public class AnalyticsEventsTest {

private Client client;
private Helper helper;

@BeforeEach
void setUp() throws Exception {
helper = new Helper();
client = helper.getClient();
helper.teardown();
helper.createTestCollection();
helper.createTestQueryCollection();
helper.createTestAnalyticsRule();
}

@AfterEach
void tearDown() throws Exception {
helper.teardown();
}

@Test
void testCreate() throws Exception {
HashMap<String, Object> eventData = new HashMap<>();
eventData.put("q", "running shoes");
eventData.put("user_id", "1234");
AnalyticsEventCreateSchema analyticsEvent = new AnalyticsEventCreateSchema()
.type("search")
.name("products_search_event")
.data(eventData);

AnalyticsEventCreateResponse result = this.client.analytics().events().create(analyticsEvent);
assertNotNull(result);
assertEquals(true, result.isOk());

}
}
131 changes: 131 additions & 0 deletions src/test/java/org/typesense/api/AnalyticsRulesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.typesense.api;

import java.util.Arrays;

import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.typesense.model.AnalyticsRuleDeleteResponse;
import org.typesense.model.AnalyticsRuleParameters;
import org.typesense.model.AnalyticsRuleParametersDestination;
import org.typesense.model.AnalyticsRuleParametersSource;
import org.typesense.model.AnalyticsRuleSchema;
import org.typesense.model.AnalyticsRuleUpsertSchema;
import org.typesense.model.AnalyticsRulesRetrieveSchema;

public class AnalyticsRulesTest {

private Client client;
private Helper helper;

@BeforeEach
void setUp() throws Exception {
helper = new Helper();
client = helper.getClient();
helper.teardown();
helper.createTestCollection();
helper.createTestQueryCollection();
}

@AfterEach
void tearDown() throws Exception {
helper.teardown();
}

@Test
void testCreate() throws Exception {
AnalyticsRuleSchema analyticsRuleSchema = new AnalyticsRuleSchema();
analyticsRuleSchema.setName("nohits-queries");
analyticsRuleSchema.setType(AnalyticsRuleSchema.TypeEnum.NOHITS_QUERIES);
analyticsRuleSchema.setParams(new AnalyticsRuleParameters()
.source(new AnalyticsRuleParametersSource()
.collections(Arrays.asList("books")))
.destination(new AnalyticsRuleParametersDestination()
.collection("queries")));

AnalyticsRuleSchema result = this.client.analytics().rules().create(analyticsRuleSchema);
assertNotNull(result);
assertEquals("nohits-queries", result.getName());

AnalyticsRuleParameters params = result.getParams();
assertNotNull(params);

assertNotNull(params.getSource());
assertEquals(Arrays.asList("books"), params.getSource().getCollections());

assertNotNull(params.getDestination());
assertEquals("queries", params.getDestination().getCollection());
}

@Test
void testUpsert() throws Exception {
AnalyticsRuleUpsertSchema analyticsRuleSchema = new AnalyticsRuleUpsertSchema()
.type(AnalyticsRuleUpsertSchema.TypeEnum.NOHITS_QUERIES)
.params(new AnalyticsRuleParameters()
.source(new AnalyticsRuleParametersSource()
.collections(Arrays.asList("books")))
.destination(new AnalyticsRuleParametersDestination()
.collection("queries")));

AnalyticsRuleSchema result = this.client.analytics().rules().upsert("nohits-queries", analyticsRuleSchema);
assertNotNull(result);
assertEquals("nohits-queries", result.getName());

AnalyticsRuleParameters params = result.getParams();
assertNotNull(params);

assertNotNull(params.getSource());
assertEquals(Arrays.asList("books"), params.getSource().getCollections());

assertNotNull(params.getDestination());
assertEquals("queries", params.getDestination().getCollection());
}

@Test
void testRetrieve() throws Exception {
helper.createTestAnalyticsRule();
AnalyticsRuleSchema result = this.client.analytics().rules("analytics-rule").retrieve();

assertNotNull(result);
assertEquals("analytics-rule", result.getName());

AnalyticsRuleParameters params = result.getParams();
assertNotNull(params);

assertNotNull(params.getSource());
assertEquals(Arrays.asList("books"), params.getSource().getCollections());

assertNotNull(params.getDestination());
assertEquals("queries", params.getDestination().getCollection());
}

@Test
void testRetrieveAll() throws Exception {
helper.createTestAnalyticsRule();
AnalyticsRulesRetrieveSchema result = this.client.analytics().rules().retrieve();

assertNotNull(result);
assertEquals("analytics-rule", result.getRules().get(0).getName());
assertEquals(1, result.getRules().size());

AnalyticsRuleParameters params = result.getRules().get(0).getParams();
assertNotNull(params);

assertNotNull(params.getSource());
assertEquals(Arrays.asList("books"), params.getSource().getCollections());

assertNotNull(params.getDestination());
assertEquals("queries", params.getDestination().getCollection());
}

@Test
void testDelete() throws Exception {
helper.createTestAnalyticsRule();
AnalyticsRuleDeleteResponse result = this.client.analytics().rules("analytics-rule").delete();

assertNotNull(result);
assertEquals("analytics-rule", result.getName());
}
}
Loading