diff options
author | Kristian Aune <kraune@yahoo-inc.com> | 2016-06-20 14:33:33 +0200 |
---|---|---|
committer | Kristian Aune <kraune@yahoo-inc.com> | 2016-06-20 14:33:33 +0200 |
commit | 0917c604de3658de129e36fe7d6d54b2e717ea75 (patch) | |
tree | af79aa6ce42835d7acdf085a37cc4e69f456b7a1 /sample-apps | |
parent | cd42fcc4d36d46fbce57010d816034ed525329ac (diff) |
Add non-working draft
- so we have a place to link to in documentation
Diffstat (limited to 'sample-apps')
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)); + } + } +} |