Closed mkubenka closed 8 years ago
Hi @mkubenka
There is no such built-in engine in the module. However as it is very generic, you can easily create your own for your use cases. For eg, the following demo engine use a List<Node>
as input and add all their related nodes as recommendations where the score will the the internal id value of the reco node (this is a quick demo :) )
package com.graphaware.reco.demo.multi;
import com.graphaware.reco.generic.context.Context;
import com.graphaware.reco.generic.engine.RecommendationEngine;
import com.graphaware.reco.generic.policy.ParticipationPolicy;
import com.graphaware.reco.generic.result.PartialScore;
import com.graphaware.reco.generic.result.Recommendations;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import java.util.List;
public class MultipleInputRecoEngine implements RecommendationEngine<Node, List<Node>> {
@Override
public String name() {
return "test_multi_engine";
}
@Override
public ParticipationPolicy<Node, List<Node>> participationPolicy(Context<Node, List<Node>> context) {
return ParticipationPolicy.ALWAYS;
}
@Override
public Recommendations<Node> recommend(List<Node> input, Context<Node, List<Node>> context) {
Recommendations<Node> result = new Recommendations<>();
for (Node partiaInput : input) {
for (Relationship relationship : partiaInput.getRelationships()) {
Node reco = relationship.getOtherNode(partiaInput);
result.add(reco, name(), new PartialScore(reco.getId()));
}
}
return result;
}
}
And a simple test would be :
package com.graphaware.reco.demo;
import com.graphaware.reco.demo.multi.MultipleInputRecoEngine;
import com.graphaware.reco.generic.config.SimpleConfig;
import com.graphaware.reco.generic.context.SimpleContext;
import com.graphaware.reco.generic.engine.RecommendationEngine;
import com.graphaware.reco.generic.result.Recommendation;
import com.graphaware.reco.generic.result.Recommendations;
import com.graphaware.test.integration.GraphAwareApiTest;
import org.junit.Test;
import org.neo4j.graphdb.*;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class MultiInputRecoEngineDemo extends GraphAwareApiTest {
private static final Label LABEL = DynamicLabel.label("Node");
@Test
public void testMultiRecoEngine() throws Exception {
createData();
MultipleInputRecoEngine engine = new MultipleInputRecoEngine();
List<Node> input = new ArrayList<>();
try (Transaction tx = getDatabase().beginTx()) {
ResourceIterator<Node> it = getDatabase().findNodes(LABEL);
while (it.hasNext()) {
input.add(it.next());
}
tx.success();
}
Recommendations recommendations = getRecommendations(input, engine);
if (null == recommendations) {
assertEquals(1, 2);
}
assertEquals(3, recommendations.size());
int i = 1;
for (Object reco : recommendations.get()) {
Recommendation<Node> r = (Recommendation<Node>) reco;
assertEquals(i, r.getItem().getId(), 0L);
assertEquals(i, r.getScore().getTotalScore(), 0.0f);
i += 2;
}
}
private Recommendations<Node> getRecommendations(List<Node> input, RecommendationEngine recommendationEngine){
Recommendations recommendations = null;
try (Transaction tx = getDatabase().beginTx()) {
recommendations = recommendationEngine.recommend(input, new SimpleContext(input, new SimpleConfig(10)));
tx.success();
}
return recommendations;
}
private void createData() {
try (Transaction tx = getDatabase().beginTx()) {
for (int i = 0; i < 3; ++i) {
Node a = getDatabase().createNode();
a.addLabel(LABEL);
Node b = getDatabase().createNode();
a.createRelationshipTo(b, DynamicRelationshipType.withName("RELATES"));
}
tx.success();
}
}
}
1
{total:1.0, test_multi_engine:1.0}
3
{total:3.0, test_multi_engine:3.0}
5
{total:5.0, test_multi_engine:5.0}
If you end up creating a generic enough implementation with some tests, we would be happy to merge it in the repository.
Let us know if this helps,
Chris
@mkubenka is it answering your question ?
Is it possible to use list of nodes as input? So, for example I would like to find recommendations for a product based on another 3 user-picked products.