aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Aune <kraune@yahoo-inc.com>2016-06-20 14:33:33 +0200
committerKristian Aune <kraune@yahoo-inc.com>2016-06-20 14:33:33 +0200
commit0917c604de3658de129e36fe7d6d54b2e717ea75 (patch)
treeaf79aa6ce42835d7acdf085a37cc4e69f456b7a1
parentcd42fcc4d36d46fbce57010d816034ed525329ac (diff)
Add non-working draft
- so we have a place to link to in documentation
-rw-r--r--sample-apps/README.md5
-rw-r--r--sample-apps/basic-search/README.md4
-rw-r--r--sample-apps/basic-search/music-data-1.json9
-rw-r--r--sample-apps/basic-search/music-data-2.json9
-rw-r--r--sample-apps/basic-search/music-data-feed.json22
-rw-r--r--sample-apps/basic-search/pom.xml39
-rw-r--r--sample-apps/basic-search/src/main/application/hosts.xml7
-rw-r--r--sample-apps/basic-search/src/main/application/searchdefinitions/music.sd40
-rw-r--r--sample-apps/basic-search/src/main/application/services.xml23
-rw-r--r--sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleDocumentProcessor.java118
-rw-r--r--sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleSearcher.java30
-rw-r--r--sample-apps/basic-search/src/main/resources/configdefinitions/message.def3
-rw-r--r--sample-apps/basic-search/src/test/application/services.xml20
-rw-r--r--sample-apps/basic-search/src/test/java/com/mydomain/example/ExampleSearcherTest.java38
14 files changed, 367 insertions, 0 deletions
diff --git a/sample-apps/README.md b/sample-apps/README.md
new file mode 100644
index 00000000000..22500f9ecb5
--- /dev/null
+++ b/sample-apps/README.md
@@ -0,0 +1,5 @@
+# Vespa sample applications
+This is the future home of Vespa Sample applications
+
+## TODO:
+* Add basic-search
diff --git a/sample-apps/basic-search/README.md b/sample-apps/basic-search/README.md
new file mode 100644
index 00000000000..616c10acab0
--- /dev/null
+++ b/sample-apps/basic-search/README.md
@@ -0,0 +1,4 @@
+# Vespa sample applications - Basic Search
+Set up a simple Vespa application on one node.
+Feed and run simple queries
+
diff --git a/sample-apps/basic-search/music-data-1.json b/sample-apps/basic-search/music-data-1.json
new file mode 100644
index 00000000000..44ce547370e
--- /dev/null
+++ b/sample-apps/basic-search/music-data-1.json
@@ -0,0 +1,9 @@
+{
+ "fields": {
+ "album": "Bad",
+ "artist": "Michael Jackson",
+ "title": "Bad",
+ "year": 1987,
+ "duration": 247
+ }
+}
diff --git a/sample-apps/basic-search/music-data-2.json b/sample-apps/basic-search/music-data-2.json
new file mode 100644
index 00000000000..c8e2d3c017c
--- /dev/null
+++ b/sample-apps/basic-search/music-data-2.json
@@ -0,0 +1,9 @@
+{
+ "fields": {
+ "album": "Recovery",
+ "artist": "Eminem",
+ "title": "So Bad",
+ "year": 2010
+ }
+}
+
diff --git a/sample-apps/basic-search/music-data-feed.json b/sample-apps/basic-search/music-data-feed.json
new file mode 100644
index 00000000000..f896cdad75d
--- /dev/null
+++ b/sample-apps/basic-search/music-data-feed.json
@@ -0,0 +1,22 @@
+[
+ {
+ "put": "id:music:music::http://mymusic.com/Michael-Jackson-Bad",
+ "fields": {
+ "album": "Bad",
+ "artist": "Michael Jackson",
+ "title": "Bad",
+ "year": 1987,
+ "duration": 247
+ }
+ },
+ {
+ "put": "id:music:music::http://mymusic.com/Eminem-Recovery",
+ "fields": {
+ "album": "Recovery",
+ "artist": "Eminem",
+ "title": "So Bad",
+ "year": 2010
+ }
+ }
+]
+
diff --git a/sample-apps/basic-search/pom.xml b/sample-apps/basic-search/pom.xml
new file mode 100644
index 00000000000..1d4cc2ad7e2
--- /dev/null
+++ b/sample-apps/basic-search/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.mydomain.example</groupId>
+ <artifactId>basic-application</artifactId>
+ <packaging>container-plugin</packaging>
+ <version>1.0.1</version>
+ <name>application</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <test.hide>true</test.hide>
+ <application>music</application>
+ <instance>default</instance>
+ </properties>
+
+ <parent>
+ <groupId>com.yahoo.vespa.tenant</groupId>
+ <artifactId>base</artifactId>
+ <version>RELEASE</version>
+ </parent>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-Xlint:all</arg>
+ <arg>-Werror</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sample-apps/basic-search/src/main/application/hosts.xml b/sample-apps/basic-search/src/main/application/hosts.xml
new file mode 100644
index 00000000000..632e48db321
--- /dev/null
+++ b/sample-apps/basic-search/src/main/application/hosts.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hosts>
+ <host name="localhost">
+ <alias>node1</alias>
+ </host>
+</hosts>
+
diff --git a/sample-apps/basic-search/src/main/application/searchdefinitions/music.sd b/sample-apps/basic-search/src/main/application/searchdefinitions/music.sd
new file mode 100644
index 00000000000..d6bcaac8ae0
--- /dev/null
+++ b/sample-apps/basic-search/src/main/application/searchdefinitions/music.sd
@@ -0,0 +1,40 @@
+search music {
+ document music {
+ field artist type string {
+ indexing: summary | index
+ }
+ field artistId type string {
+ indexing: summary | attribute
+ }
+
+ field title type string {
+ indexing: summary | index
+ }
+
+ field album type string {
+ indexing: index
+ }
+
+ field duration type int {
+ indexing: summary
+ }
+
+ field year type int {
+ indexing: summary | attribute
+ }
+
+ field popularity type int {
+ indexing: summary | attribute
+ }
+ }
+
+ fieldset default {
+ fields: artist, title, album
+ }
+
+ rank-profile song inherits default {
+ first-phase {
+ expression:nativeRank(artist,title,album) + if(isNan(attribute(popularity)) == 1, 0,attribute(popularity))
+ }
+ }
+}
diff --git a/sample-apps/basic-search/src/main/application/services.xml b/sample-apps/basic-search/src/main/application/services.xml
new file mode 100644
index 00000000000..69899bcd1c6
--- /dev/null
+++ b/sample-apps/basic-search/src/main/application/services.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<services version="1.0">
+
+ <jdisc version="1.0" id="container">
+ <document-api />
+ <search />
+ <nodes>
+ <node hostalias="node1" />
+ </nodes>
+ </jdisc>
+
+ <content id="music" version="1.0">
+ <redundancy>1</redundancy>
+ <documents>
+ <document type="music" mode="index" />
+ </documents>
+ <nodes>
+ <node hostalias="node1" distribution-key="0" />
+ </nodes>
+ </content>
+
+</services>
+
diff --git a/sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleDocumentProcessor.java b/sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleDocumentProcessor.java
new file mode 100644
index 00000000000..a667b4a3650
--- /dev/null
+++ b/sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleDocumentProcessor.java
@@ -0,0 +1,118 @@
+package com.mydomain.example;
+
+import com.yahoo.docproc.DocumentProcessor;
+import com.yahoo.docproc.Processing;
+import com.yahoo.document.Document;
+import com.yahoo.document.DocumentOperation;
+import com.yahoo.document.DocumentPut;
+import com.yahoo.document.DocumentRemove;
+import com.yahoo.document.DocumentUpdate;
+
+import java.net.*;
+import java.io.*;
+
+import com.yahoo.document.datatypes.StringFieldValue;
+import org.json.*;
+import java.util.logging.Logger;
+
+/**
+ * A document processor
+ *
+ * @author Joe Developer
+ */
+public class ExampleDocumentProcessor extends DocumentProcessor {
+
+ private static final String artistField = "artist";
+ private static final String artistIdField = "artistId";
+ private static final String spotifyUrl = "https://api.spotify.com/v1/search?type=artist&limit=1&q=";
+ private static final Logger log = Logger.getLogger(ExampleDocumentProcessor.class.getName());
+
+ public Progress process(Processing processing) {
+ for (DocumentOperation op : processing.getDocumentOperations()) {
+ if (op instanceof DocumentPut) {
+ Document document = ((DocumentPut) op).getDocument();
+ addArtistId(document);
+ } else if (op instanceof DocumentUpdate) {
+ DocumentUpdate update = (DocumentUpdate) op;
+ //TODO do something to 'update' here
+ } else if (op instanceof DocumentRemove) {
+ DocumentRemove remove = (DocumentRemove) op;
+ //TODO do something to 'remove' here
+ }
+ }
+ return Progress.DONE;
+ }
+
+ /**
+ * Query Spotify API, parse JSON and set Artist ID
+ *
+ * @param document a Vespa Document
+ */
+ public void addArtistId(Document document) {
+ StringFieldValue artistString = (StringFieldValue) document.getFieldValue(artistField);
+ HttpURLConnection conn = null;
+ try {
+ String url = spotifyUrl + java.net.URLEncoder.encode(artistString.getString(), "UTF-8");
+ conn = getConnection(url);
+ String artistId = parseSpotifyResponse(new InputStreamReader(conn.getInputStream(), "UTF-8"));
+ if (artistId == null) {
+ return;
+ }
+ document.setFieldValue(artistIdField, new StringFieldValue(artistId));
+
+ } catch (Exception e) {
+ log.warning("Error: " );
+ } finally {
+ if (conn != null) {
+ conn.disconnect();
+ }
+ }
+ }
+
+ /**
+ * @param streamReader the response to read from
+ * @return artist id from spotify or null if not found
+ * @throws IOException
+ */
+
+ private String parseSpotifyResponse(InputStreamReader streamReader) throws IOException {
+ // Read JSON data from API
+ BufferedReader reader = new BufferedReader(streamReader);
+ StringBuilder builder = new StringBuilder();
+ for (String line; (line = reader.readLine()) != null; ) {
+ builder.append(line).append("\n");
+ }
+
+ // Parse the JSON to find the first artist item returned or null if not found
+ try {
+ JSONObject json = new JSONObject(builder.toString());
+ JSONObject artists = json.getJSONObject("artists");
+ JSONArray items = artists.getJSONArray("items");
+ JSONObject artist = items.getJSONObject(0);
+ return artist.getString("id");
+ } catch (JSONException e) {
+ return null;
+ }
+
+ }
+
+ /**
+ * Establishes an HTTP Connection
+ *
+ * @param inputUrl a String giving the URL to connect to
+ * @return an HttpURLConnection
+ * @throws java.io.IOException when connection to inputUrl failed
+ */
+ private HttpURLConnection getConnection(String inputUrl) throws IOException {
+ URL url = new URL(inputUrl);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+
+ conn.setRequestProperty("User-Agent", "Vespa Basic Search DocProc");
+ conn.setReadTimeout(10000);
+ conn.setConnectTimeout(5000);
+ conn.connect();
+
+ return conn;
+ }
+}
+
diff --git a/sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleSearcher.java b/sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleSearcher.java
new file mode 100644
index 00000000000..fb8e76f36ec
--- /dev/null
+++ b/sample-apps/basic-search/src/main/java/com/mydomain/example/ExampleSearcher.java
@@ -0,0 +1,30 @@
+package com.mydomain.example;
+
+import com.yahoo.search.Query;
+import com.yahoo.search.Result;
+import com.yahoo.search.Searcher;
+import com.yahoo.search.result.Hit;
+import com.yahoo.search.searchchain.Execution;
+
+/**
+ * A searcher adding a new hit.
+ *
+ * @author Joe Developer
+ */
+public class ExampleSearcher extends Searcher {
+ public static final String hitId = "ExampleHit";
+ private final String message;
+
+ public ExampleSearcher(MessageConfig config) {
+ message = config.message();
+ }
+
+ public Result search(Query query, Execution execution) {
+ Hit hit = new Hit(hitId);
+ hit.setField("message", message);
+
+ Result result = execution.search(query);
+ result.hits().add(hit);
+ return result;
+ }
+}
diff --git a/sample-apps/basic-search/src/main/resources/configdefinitions/message.def b/sample-apps/basic-search/src/main/resources/configdefinitions/message.def
new file mode 100644
index 00000000000..d2a2bc5407a
--- /dev/null
+++ b/sample-apps/basic-search/src/main/resources/configdefinitions/message.def
@@ -0,0 +1,3 @@
+version=1
+namespace=example
+message string default="Hello, World!" \ No newline at end of file
diff --git a/sample-apps/basic-search/src/test/application/services.xml b/sample-apps/basic-search/src/test/application/services.xml
new file mode 100644
index 00000000000..388ab448f9c
--- /dev/null
+++ b/sample-apps/basic-search/src/test/application/services.xml
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<services version='1.0'>
+ <admin version='3.0'>
+ <nodes count="1" />
+ </admin>
+
+ <!-- duplication of src/main/application due to Ticket 6904654 -->
+ <jdisc version='1.0' id='default'>
+ <search>
+ <chain id="default" inherits="vespa">
+ <searcher id="com.yahoo.example.ExampleSearcher" bundle="basic-application">
+ <config name="example.message">
+ <message>Hello, Vespa!</message>
+ </config>
+ </searcher>
+ </chain>
+ </search>
+ <nodes count="1" />
+ </jdisc>
+</services>
diff --git a/sample-apps/basic-search/src/test/java/com/mydomain/example/ExampleSearcherTest.java b/sample-apps/basic-search/src/test/java/com/mydomain/example/ExampleSearcherTest.java
new file mode 100644
index 00000000000..e562cf1173a
--- /dev/null
+++ b/sample-apps/basic-search/src/test/java/com/mydomain/example/ExampleSearcherTest.java
@@ -0,0 +1,38 @@
+package com.yahoo.example;
+
+import com.yahoo.application.Application;
+import com.yahoo.application.Networking;
+import com.yahoo.application.container.Search;
+import com.yahoo.component.ComponentSpecification;
+import com.yahoo.search.Query;
+import com.yahoo.search.Result;
+import com.yahoo.search.result.Hit;
+import org.junit.Test;
+
+import java.nio.file.Paths;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Joe Developer
+ */
+public class ExampleSearcherTest {
+ @Test
+ public void hit_is_added() throws Exception {
+ try (Application app = Application.fromApplicationPackage(
+ Paths.get("src/test/application"),
+ Networking.disable))
+ {
+ Search search = app.getJDisc("jdisc").search();
+ Result result = search.process(ComponentSpecification.fromString("default"), new Query("?query=ignored"));
+
+ Hit hit = result.hits().get(ExampleSearcher.hitId);
+ assertNotNull("Hit was not added by ExampleSearcher", hit);
+
+ Object messageFromConfig = "Hello, Vespa!";
+ assertThat(hit.getField("message"), is(messageFromConfig));
+ }
+ }
+}