summaryrefslogtreecommitdiffstats
path: root/sample-apps
diff options
context:
space:
mode:
authorLester Solbakken <lesters@yahoo-inc.com>2016-07-01 16:25:10 +0200
committerLester Solbakken <lesters@yahoo-inc.com>2016-07-01 16:25:10 +0200
commitc97564a092efd74608f0e76af6b9c15542b10e9a (patch)
treeb509417c3fedd4d1ea3fc071c8db2f9dabf00e86 /sample-apps
parent5c80034a3b64ecee8314bea7c7e7c57d4638ad01 (diff)
Add filtering of already read items to sample app.
Add filtering of already read items to the recommendation sample app.
Diffstat (limited to 'sample-apps')
-rw-r--r--sample-apps/blog-recommendation/src/main/java/com/yahoo/example/BlogTensorSearcher.java27
-rw-r--r--sample-apps/blog-recommendation/src/main/java/com/yahoo/example/UserProfileSearcher.java73
2 files changed, 55 insertions, 45 deletions
diff --git a/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/BlogTensorSearcher.java b/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/BlogTensorSearcher.java
index f9ff27c4813..5bbd7140cb8 100644
--- a/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/BlogTensorSearcher.java
+++ b/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/BlogTensorSearcher.java
@@ -1,6 +1,10 @@
package com.yahoo.example;
+import com.yahoo.data.access.Inspectable;
+import com.yahoo.data.access.Inspector;
import com.yahoo.prelude.query.IntItem;
+import com.yahoo.prelude.query.NotItem;
+import com.yahoo.prelude.query.WordItem;
import com.yahoo.processing.request.CompoundName;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
@@ -9,6 +13,9 @@ import com.yahoo.search.querytransform.QueryTreeUtil;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.tensor.Tensor;
+import java.util.ArrayList;
+import java.util.List;
+
public class BlogTensorSearcher extends Searcher {
@Override
@@ -20,8 +27,13 @@ public class BlogTensorSearcher extends Searcher {
// Modify the query by restricting to blog_posts...
query.getModel().setRestrict("blog_post");
- // ... that has a tensor field fed
- QueryTreeUtil.andQueryItemWithRoot(query, new IntItem(1, "has_user_item_cf"));
+ // ... that has a tensor field fed and does not contains already read items.
+ NotItem notItem = new NotItem();
+ notItem.addItem(new IntItem(1, "has_user_item_cf"));
+ for (String item : getReadItems(query)) {
+ notItem.addItem(new WordItem(item, "post_id"));
+ }
+ QueryTreeUtil.andQueryItemWithRoot(query, notItem);
// Modify the ranking by using the 'tensor' rank-profile (as defined in blog_post.sd)...
query.properties().set(new CompoundName("ranking"), "tensor");
@@ -40,4 +52,15 @@ public class BlogTensorSearcher extends Searcher {
return Tensor.from(tensor.toString());
}
+ private List<String> getReadItems(Query query) {
+ List<String> items = new ArrayList<>();
+ Object readItems = query.properties().get("has_read_items");
+ if (readItems instanceof Inspectable) {
+ for (Inspector entry : ((Inspectable)readItems).inspect().entries()) {
+ items.add(entry.asString());
+ }
+ }
+ return items;
+ }
+
}
diff --git a/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/UserProfileSearcher.java b/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/UserProfileSearcher.java
index 63bf4110e67..adc13976b9a 100644
--- a/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/UserProfileSearcher.java
+++ b/sample-apps/blog-recommendation/src/main/java/com/yahoo/example/UserProfileSearcher.java
@@ -11,7 +11,6 @@ import com.yahoo.search.result.Hit;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.search.searchchain.SearchChain;
import com.yahoo.tensor.MapTensorBuilder;
-import com.yahoo.tensor.Tensor;
import java.util.Iterator;
import java.util.Map;
@@ -19,27 +18,19 @@ import java.util.Map;
public class UserProfileSearcher extends Searcher {
public Result search(Query query, Execution execution) {
-
Object userIdProperty = query.properties().get("user_id");
if (userIdProperty != null) {
-
- // Retrieve user profile...
- Tensor userProfile = retrieveUserProfile(userIdProperty.toString(), execution);
-
- // ... and add user profile to query properties so BlogTensorSearcher can pick it up
- query.properties().set(new CompoundName("user_item_cf"), userProfile);
-
- if (query.isTraceable(9)) {
- String tensorRepresentation = userProfile != null ? userProfile.toString() : "";
- query.trace("Setting user profile to :" + tensorRepresentation, 9);
+ Hit userProfile = retrieveUserProfile(userIdProperty.toString(), execution);
+ if (userProfile != null) {
+ addUserProfileTensorToQuery(query, userProfile);
+ addReadItemsToQuery(query, userProfile);
}
}
-
return execution.search(query);
}
- private Tensor retrieveUserProfile(String userId, Execution execution) {
+ private Hit retrieveUserProfile(String userId, Execution execution) {
Query query = new Query();
query.getModel().setRestrict("user");
query.getModel().getQueryTree().setRoot(new WordItem(userId, "user_id"));
@@ -48,42 +39,38 @@ public class UserProfileSearcher extends Searcher {
SearchChain vespaChain = execution.searchChainRegistry().getComponent("vespa");
Result result = new Execution(vespaChain, execution.context()).search(query);
- // This is needed to get the actual summary data
- execution.fill(result);
-
- Hit hit = getFirstHit(result);
- if (hit != null) {
- Object userItemCf = hit.getField("user_item_cf");
- if (userItemCf instanceof Inspectable) {
- return convertTensor((Inspectable) userItemCf);
- }
- }
- return null;
- }
+ execution.fill(result); // this is needed to get the actual summary data
- private Hit getFirstHit(Result result) {
Iterator<Hit> hiterator = result.hits().deepIterator();
return hiterator.hasNext() ? hiterator.next() : null;
}
- private Tensor convertTensor(Inspectable field) {
- MapTensorBuilder tensorBuilder = new MapTensorBuilder();
-
- Inspector cells = field.inspect().field("cells");
- for (Inspector cell : cells.entries()) {
- MapTensorBuilder.CellBuilder cellBuilder = tensorBuilder.cell();
+ private void addReadItemsToQuery(Query query, Hit userProfile) {
+ Object readItems = userProfile.getField("has_read_items");
+ if (readItems != null && readItems instanceof Inspectable) {
+ query.properties().set(new CompoundName("has_read_items"), readItems);
+ }
+ }
- Inspector address = cell.field("address");
- for (Map.Entry<String, Inspector> entry : address.fields()) {
- String dim = entry.getKey();
- String label = entry.getValue().asString();
- cellBuilder.label(dim, label);
+ private void addUserProfileTensorToQuery(Query query, Hit userProfile) {
+ Object userItemCf = userProfile.getField("user_item_cf");
+ if (userItemCf != null && userItemCf instanceof Inspectable) {
+ MapTensorBuilder tensorBuilder = new MapTensorBuilder();
+ Inspector cells = ((Inspectable)userItemCf).inspect().field("cells");
+ for (Inspector cell : cells.entries()) {
+ MapTensorBuilder.CellBuilder cellBuilder = tensorBuilder.cell();
+
+ Inspector address = cell.field("address");
+ for (Map.Entry<String, Inspector> entry : address.fields()) {
+ String dim = entry.getKey();
+ String label = entry.getValue().asString();
+ cellBuilder.label(dim, label);
+ }
+
+ Inspector value = cell.field("value");
+ cellBuilder.value(value.asDouble());
}
-
- Inspector value = cell.field("value");
- cellBuilder.value(value.asDouble());
+ query.properties().set(new CompoundName("user_item_cf"), tensorBuilder.build());
}
- return tensorBuilder.build();
}
-
}