groovy plugin - add search API

This commit is contained in:
kimchy 2010-04-14 19:10:29 +03:00
parent 96a185e107
commit 0da66ba367
18 changed files with 456 additions and 114 deletions

View File

@ -68,6 +68,13 @@ public class SearchResponse implements ActionResponse, ToJson {
return internalResponse.hits();
}
/**
* The search hits.
*/
public SearchHits getHits() {
return hits();
}
/**
* The search facets.
*/
@ -75,6 +82,13 @@ public class SearchResponse implements ActionResponse, ToJson {
return internalResponse.facets();
}
/**
* The search facets.
*/
public Facets getFacets() {
return facets();
}
/**
* The total number of shards the search was executed on.
*/
@ -82,6 +96,13 @@ public class SearchResponse implements ActionResponse, ToJson {
return totalShards;
}
/**
* The total number of shards the search was executed on.
*/
public int getTotalShards() {
return totalShards;
}
/**
* The successful number of shards the search was executed on.
*/
@ -89,6 +110,13 @@ public class SearchResponse implements ActionResponse, ToJson {
return successfulShards;
}
/**
* The successful number of shards the search was executed on.
*/
public int getSuccessfulShards() {
return successfulShards;
}
/**
* The failed number of shards the search was executed on.
*/
@ -96,6 +124,13 @@ public class SearchResponse implements ActionResponse, ToJson {
return totalShards - successfulShards;
}
/**
* The failed number of shards the search was executed on.
*/
public int getFailedShards() {
return failedShards();
}
/**
* The failures that occurred during the search.
*/
@ -103,6 +138,13 @@ public class SearchResponse implements ActionResponse, ToJson {
return this.shardFailures;
}
/**
* The failures that occurred during the search.
*/
public ShardSearchFailure[] getShardFailures() {
return shardFailures;
}
/**
* If scrolling was enabled ({@link SearchRequest#scroll(org.elasticsearch.search.Scroll)}, the
* scroll id that can be used to continue scrolling.
@ -111,6 +153,14 @@ public class SearchResponse implements ActionResponse, ToJson {
return scrollId;
}
/**
* If scrolling was enabled ({@link SearchRequest#scroll(org.elasticsearch.search.Scroll)}, the
* scroll id that can be used to continue scrolling.
*/
public String getScrollId() {
return scrollId;
}
@Override public void toJson(JsonBuilder builder, Params params) throws IOException {
if (scrollId != null) {
builder.field("_scrollId", scrollId);

View File

@ -40,21 +40,41 @@ public interface SearchHit extends Streamable, ToJson, Iterable<SearchHitField>
*/
String index();
/**
* The index of the hit.
*/
String getIndex();
/**
* The id of the document.
*/
String id();
/**
* The id of the document.
*/
String getId();
/**
* The type of the document.
*/
String type();
/**
* The type of the document.
*/
String getType();
/**
* The source of the document (can be <tt>null</tt>).
*/
byte[] source();
/**
* The source of the document as a map (can be <tt>null</tt>).
*/
Map<String, Object> getSource();
/**
* The source of the document as string (can be <tt>null</tt>).
*/
@ -70,19 +90,40 @@ public interface SearchHit extends Streamable, ToJson, Iterable<SearchHitField>
*/
Explanation explanation();
/**
* If enabled, the explanation of the search hit.
*/
Explanation getExplanation();
/**
* A map of hit fields (from field name to hit fields) if additional fields
* were required to be loaded.
*/
Map<String, SearchHitField> fields();
/**
* A map of hit fields (from field name to hit fields) if additional fields
* were required to be loaded.
*/
Map<String, SearchHitField> getFields();
/**
* A map of highlighted fields.
*/
Map<String, HighlightField> highlightFields();
/**
* A map of highlighted fields.
*/
Map<String, HighlightField> getHighlightFields();
/**
* The shard of the search hit.
*/
SearchShardTarget shard();
/**
* The shard of the search hit.
*/
SearchShardTarget getShard();
}

View File

@ -36,8 +36,18 @@ public interface SearchHitField extends Streamable, Iterable<Object> {
*/
String name();
/**
* The name of the field.
*/
String getName();
/**
* The field values.
*/
List<Object> values();
/**
* The field values.
*/
List<Object> getValues();
}

View File

@ -27,15 +27,27 @@ import org.elasticsearch.util.json.ToJson;
*
* @author kimchy (shay.banon)
*/
public interface SearchHits extends Streamable, ToJson {
public interface SearchHits extends Streamable, ToJson, Iterable<SearchHit> {
/**
* The total number of hits that matches the search request.
*/
long totalHits();
/**
* The total number of hits that matches the search request.
*/
long getTotalHits();
/**
* The hits of the search request (based on the search type, and from / size provided).
*/
SearchHit[] hits();
SearchHit getAt(int position);
/**
* The hits of the search request (based on the search type, and from / size provided).
*/
public SearchHit[] getHits();
}

View File

@ -53,14 +53,26 @@ public class SearchShardTarget implements Streamable, Serializable {
return nodeId;
}
public String getNodeId() {
return nodeId;
}
public String index() {
return index;
}
public String getIndex() {
return index;
}
public int shardId() {
return shardId;
}
public int getShardId() {
return shardId;
}
public static SearchShardTarget readSearchShardTarget(StreamInput in) throws IOException {
SearchShardTarget result = new SearchShardTarget();
result.readFrom(in);

View File

@ -49,6 +49,10 @@ public class CountFacet implements Facet {
return Type.COUNT;
}
@Override public Type getType() {
return type();
}
/**
* The "logical" name of the facet.
*/
@ -56,6 +60,10 @@ public class CountFacet implements Facet {
return name;
}
@Override public String getName() {
return name();
}
/**
* The count of the facet.
*/
@ -63,6 +71,13 @@ public class CountFacet implements Facet {
return count;
}
/**
* The count of the facet.
*/
public long getCount() {
return count;
}
public void increment(long increment) {
count += increment;
}

View File

@ -60,8 +60,18 @@ public interface Facet extends Streamable, ToJson {
*/
String name();
/**
* The "logical" name of the search facet.
*/
String getName();
/**
* The type of the facet.
*/
Type type();
/**
* The type of the facet.
*/
Type getType();
}

View File

@ -29,8 +29,10 @@ import org.elasticsearch.util.json.ToJson;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Lists.*;
import static com.google.common.collect.Maps.*;
import static org.elasticsearch.search.facets.CountFacet.*;
/**
@ -44,6 +46,8 @@ public class Facets implements Streamable, ToJson, Iterable<Facet> {
private List<Facet> facets = EMPTY;
private Map<String, Facet> facetsAsMap;
private Facets() {
}
@ -69,6 +73,28 @@ public class Facets implements Streamable, ToJson, Iterable<Facet> {
return facets;
}
/**
* Returns the {@link Facet}s keyed by map.
*/
public Map<String, Facet> getFacets() {
return facetsAsMap;
}
/**
* Returns the {@link Facet}s keyed by map.
*/
public Map<String, Facet> facetsAsMap() {
if (facetsAsMap != null) {
return facetsAsMap;
}
Map<String, Facet> facetsAsMap = newHashMap();
for (Facet facet : facets) {
facetsAsMap.put(facet.name(), facet);
}
this.facetsAsMap = facetsAsMap;
return facetsAsMap;
}
/**
* A specific count facet against the registered facet name.
*/
@ -80,12 +106,7 @@ public class Facets implements Streamable, ToJson, Iterable<Facet> {
* A facet of the specified name.
*/
public Facet facet(String name) {
for (Facet facet : facets) {
if (facet.name().equals(name)) {
return facet;
}
}
return null;
return facetsAsMap().get(name);
}
@Override public void toJson(JsonBuilder builder, Params params) throws IOException {

View File

@ -42,7 +42,7 @@ import java.util.List;
* }
* </pre>
*
* @author kimchy (Shay Banon)
* @author kimchy (shay.banon)
*/
public class FacetsParseElement implements SearchParseElement {
@ -55,7 +55,7 @@ public class FacetsParseElement implements SearchParseElement {
if (token == JsonToken.FIELD_NAME) {
topLevelFieldName = jp.getCurrentName();
} else if (token == JsonToken.VALUE_STRING) {
if ("query_execution".equals(topLevelFieldName)) {
if ("query_execution".equals(topLevelFieldName) || "queryExecution".equals(topLevelFieldName)) {
String text = jp.getText();
if ("collect".equals(text)) {
queryExecutionType = SearchContextFacets.QueryExecutionType.COLLECT;

View File

@ -53,6 +53,13 @@ public class HighlightField implements Streamable {
return name;
}
/**
* The name of the field highlighted.
*/
public String getName() {
return name();
}
/**
* The highlighted fragments. <tt>null</tt> if failed to highlight (for example, the field is not stored).
*/
@ -60,6 +67,13 @@ public class HighlightField implements Streamable {
return fragments;
}
/**
* The highlighted fragments. <tt>null</tt> if failed to highlight (for example, the field is not stored).
*/
public String[] getFragments() {
return fragments();
}
@Override public String toString() {
return "[" + name + "], fragments[" + Arrays.toString(fragments) + "]";
}

View File

@ -71,13 +71,13 @@ public class HighlighterParseElement implements SearchParseElement {
if (token == JsonToken.FIELD_NAME) {
topLevelFieldName = jp.getCurrentName();
} else if (token == JsonToken.START_ARRAY) {
if ("pre_tags".equals(topLevelFieldName)) {
if ("pre_tags".equals(topLevelFieldName) || "preTags".equals(topLevelFieldName)) {
List<String> preTagsList = Lists.newArrayList();
while ((token = jp.nextToken()) != JsonToken.END_ARRAY) {
preTagsList.add(jp.getText());
}
preTags = preTagsList.toArray(new String[preTagsList.size()]);
} else if ("post_tags".equals(topLevelFieldName)) {
} else if ("post_tags".equals(topLevelFieldName) || "postTags".equals(topLevelFieldName)) {
List<String> postTagsList = Lists.newArrayList();
while ((token = jp.nextToken()) != JsonToken.END_ARRAY) {
postTagsList.add(jp.getText());
@ -91,7 +91,7 @@ public class HighlighterParseElement implements SearchParseElement {
} else {
scoreOrdered = false;
}
} else if ("tags_schema".equals(topLevelFieldName)) {
} else if ("tags_schema".equals(topLevelFieldName) || "tagsSchema".equals(topLevelFieldName)) {
String schema = jp.getText();
if ("styled".equals(schema)) {
preTags = STYLED_PRE_TAG;
@ -112,15 +112,15 @@ public class HighlighterParseElement implements SearchParseElement {
if (token == JsonToken.FIELD_NAME) {
fieldName = jp.getCurrentName();
} else if (token == JsonToken.VALUE_STRING) {
if ("fragment_size".equals(fieldName)) {
if ("fragment_size".equals(fieldName) || "fragmentSize".equals(fieldName)) {
fragmentSize = Integer.parseInt(jp.getText());
} else if ("number_of_fragments".equals(fieldName)) {
} else if ("number_of_fragments".equals(fieldName) || "numberOfFragments".equals(fieldName)) {
numOfFragments = Integer.parseInt(jp.getText());
}
} else if (token == JsonToken.VALUE_NUMBER_INT) {
if ("fragment_size".equals(fieldName)) {
if ("fragment_size".equals(fieldName) || "fragmentSize".equals(fieldName)) {
fragmentSize = jp.getIntValue();
} else if ("number_of_fragments".equals(fieldName)) {
} else if ("number_of_fragments".equals(fieldName) || "numberOfFragments".equals(fieldName)) {
numOfFragments = jp.getIntValue();
}
}

View File

@ -64,6 +64,8 @@ public class InternalSearchHit implements SearchHit {
@Nullable private SearchShardTarget shard;
private Map<String, Object> sourceAsMap;
private InternalSearchHit() {
}
@ -84,18 +86,34 @@ public class InternalSearchHit implements SearchHit {
return shard.index();
}
@Override public String getIndex() {
return index();
}
@Override public String id() {
return id;
}
@Override public String getId() {
return id();
}
@Override public String type() {
return type;
}
@Override public String getType() {
return type();
}
@Override public byte[] source() {
return source;
}
@Override public Map<String, Object> getSource() {
return sourceAsMap();
}
@Override public String sourceAsString() {
if (source == null) {
return null;
@ -103,12 +121,17 @@ public class InternalSearchHit implements SearchHit {
return Unicode.fromBytes(source);
}
@SuppressWarnings({"unchecked"})
@Override public Map<String, Object> sourceAsMap() throws ElasticSearchParseException {
if (source == null) {
return null;
}
if (sourceAsMap != null) {
return sourceAsMap;
}
try {
return defaultObjectMapper().readValue(source, 0, source.length, Map.class);
sourceAsMap = defaultObjectMapper().readValue(source, 0, source.length, Map.class);
return sourceAsMap;
} catch (Exception e) {
throw new ElasticSearchParseException("Failed to parse source to map", e);
}
@ -122,6 +145,10 @@ public class InternalSearchHit implements SearchHit {
return fields;
}
@Override public Map<String, SearchHitField> getFields() {
return fields();
}
public void fields(Map<String, SearchHitField> fields) {
this.fields = fields;
}
@ -130,6 +157,10 @@ public class InternalSearchHit implements SearchHit {
return this.highlightFields;
}
@Override public Map<String, HighlightField> getHighlightFields() {
return highlightFields();
}
public void highlightFields(Map<String, HighlightField> highlightFields) {
this.highlightFields = highlightFields;
}
@ -138,6 +169,10 @@ public class InternalSearchHit implements SearchHit {
return explanation;
}
@Override public Explanation getExplanation() {
return explanation();
}
public void explanation(Explanation explanation) {
this.explanation = explanation;
}
@ -146,6 +181,10 @@ public class InternalSearchHit implements SearchHit {
return shard;
}
@Override public SearchShardTarget getShard() {
return shard();
}
public void shard(SearchShardTarget target) {
this.shard = target;
}

View File

@ -51,10 +51,19 @@ public class InternalSearchHitField implements SearchHitField {
return name;
}
@Override public String getName() {
return name();
}
public List<Object> values() {
return values;
}
@Override public List<Object> getValues() {
return values();
}
@Override public Iterator<Object> iterator() {
return values.iterator();
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.search.internal;
import com.google.common.collect.Iterators;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.SearchShardTarget;
@ -29,6 +30,7 @@ import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.search.SearchShardTarget.*;
@ -58,10 +60,26 @@ public class InternalSearchHits implements SearchHits {
return totalHits;
}
@Override public long getTotalHits() {
return totalHits();
}
public SearchHit[] hits() {
return this.hits;
}
@Override public SearchHit getAt(int position) {
return hits[position];
}
@Override public SearchHit[] getHits() {
return hits();
}
@Override public Iterator<SearchHit> iterator() {
return Iterators.forArray(hits());
}
public InternalSearchHit[] internalHits() {
return this.hits;
}

View File

@ -47,7 +47,9 @@ public class QueryPhase implements SearchPhase {
ImmutableMap.Builder<String, SearchParseElement> parseElements = ImmutableMap.builder();
parseElements.put("from", new FromParseElement()).put("size", new SizeParseElement())
.put("query_parser_name", new QueryParserNameParseElement())
.put("queryParserName", new QueryParserNameParseElement())
.put("indices_boost", new IndicesBoostParseElement())
.put("indicesBoost", new IndicesBoostParseElement())
.put("query", new QueryParseElement())
.put("sort", new SortParseElement())
.putAll(facetsPhase.parseElements());

View File

@ -30,6 +30,8 @@ import org.elasticsearch.action.get.GetRequest
import org.elasticsearch.action.get.GetResponse
import org.elasticsearch.action.index.IndexRequest
import org.elasticsearch.action.index.IndexResponse
import org.elasticsearch.action.search.SearchRequest
import org.elasticsearch.action.search.SearchResponse
import org.elasticsearch.action.terms.TermsRequest
import org.elasticsearch.action.terms.TermsResponse
import org.elasticsearch.client.Client
@ -63,6 +65,13 @@ class GClient {
CountRequest.metaClass.query = {Closure c ->
delegate.query(new JsonBuilder().buildAsBytes(c))
}
SearchRequest.metaClass.setSource = {Closure c ->
delegate.source(new JsonBuilder().buildAsBytes(c))
}
SearchRequest.metaClass.source = {Closure c ->
delegate.source(new JsonBuilder().buildAsBytes(c))
}
}
final Client client;
@ -170,6 +179,24 @@ class GClient {
client.count(request, listener)
}
GActionFuture<SearchResponse> search(Closure c) {
SearchRequest request = new SearchRequest()
c.resolveStrategy = resolveStrategy
c.setDelegate request
c.call()
search(request)
}
GActionFuture<SearchResponse> search(SearchRequest request) {
GActionFuture<SearchResponse> future = new GActionFuture<SearchResponse>(internalClient.threadPool(), request);
client.search(request, future)
return future
}
void search(SearchRequest request, ActionListener<SearchResponse> listener) {
client.search(request, listener)
}
GActionFuture<TermsResponse> terms(Closure c) {
TermsRequest request = new TermsRequest()
c.resolveStrategy = resolveStrategy

View File

@ -0,0 +1,126 @@
package org.elasticsearch.groovy.test.client
import java.util.concurrent.CountDownLatch
import org.elasticsearch.action.index.IndexRequest
import org.elasticsearch.action.index.IndexResponse
import org.elasticsearch.groovy.node.GNode
import org.elasticsearch.groovy.node.GNodeBuilder
import static org.elasticsearch.client.Requests.*
/**
* @author kimchy (shay.banon)
*/
class DifferentApiExecutionTests extends GroovyTestCase {
def GNode node
protected void setUp() {
GNodeBuilder nodeBuilder = new GNodeBuilder()
nodeBuilder.settings {
node {
local = true
}
}
node = nodeBuilder.node
}
protected void tearDown() {
node.close
}
void testSimpleOperations() {
def response = node.client.index(new IndexRequest(
index: "test",
type: "type1",
id: "1",
source: {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
}
})).response
assertEquals "test", response.index
assertEquals "type1", response.type
assertEquals "1", response.id
def refresh = node.client.admin.indices.refresh {}
assertEquals 0, refresh.response.failedShards
def getR = node.client.get {
index "test"
type "type1"
id "1"
}
assertTrue getR.response.exists
assertEquals "test", getR.response.index
assertEquals "type1", getR.response.type
assertEquals "1", getR.response.id
assertEquals '{"test":"value","complex":{"value1":"value1","value2":"value2"}}', getR.response.sourceAsString()
assertEquals "value", getR.response.source.test
assertEquals "value1", getR.response.source.complex.value1
response = node.client.index({
index = "test"
type = "type1"
id = "1"
source = {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
}
}
}).response
assertEquals "test", response.index
assertEquals "type1", response.type
assertEquals "1", response.id
def indexR = node.client.index(indexRequest().with {
index "test"
type "type1"
id "1"
source {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
}
}
})
CountDownLatch latch = new CountDownLatch(1)
indexR.success = {IndexResponse responseX ->
assertEquals "test", responseX.index
assertEquals "test", indexR.response.index
assertEquals "type1", responseX.type
assertEquals "type1", indexR.response.type
assertEquals "1", responseX.id
assertEquals "1", indexR.response.id
latch.countDown()
}
latch.await()
indexR = node.client.index {
index "test"
type "type1"
id "1"
source {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
}
}
}
latch = new CountDownLatch(1)
indexR.listener = {
assertEquals "test", indexR.response.index
assertEquals "type1", indexR.response.type
assertEquals "1", indexR.response.id
latch.countDown()
}
latch.await()
}
}

View File

@ -1,18 +1,16 @@
package org.elasticsearch.groovy.test.client
import java.util.concurrent.CountDownLatch
import org.elasticsearch.action.index.IndexRequest
import org.elasticsearch.action.index.IndexResponse
import org.elasticsearch.groovy.node.GNode
import org.elasticsearch.groovy.node.GNodeBuilder
import static org.elasticsearch.client.Requests.*
/**
* @author kimchy (shay.banon)
*/
class SimpleActionsTests extends GroovyTestCase {
void testSimpleOperations() {
def GNode node
protected void setUp() {
GNodeBuilder nodeBuilder = new GNodeBuilder()
nodeBuilder.settings {
node {
@ -20,80 +18,16 @@ class SimpleActionsTests extends GroovyTestCase {
}
}
GNode node = nodeBuilder.node
node = nodeBuilder.node
}
def response = node.client.index(new IndexRequest(
index: "test",
type: "type1",
id: "1",
source: {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
protected void tearDown() {
node.close
}
})).response
assertEquals "test", response.index
assertEquals "type1", response.type
assertEquals "1", response.id
def refresh = node.client.admin.indices.refresh {}
assertEquals 0, refresh.response.failedShards
def getR = node.client.get {
index "test"
type "type1"
id "1"
}
assertTrue getR.response.exists
assertEquals "test", getR.response.index
assertEquals "type1", getR.response.type
assertEquals "1", getR.response.id
assertEquals '{"test":"value","complex":{"value1":"value1","value2":"value2"}}', getR.response.sourceAsString()
assertEquals "value", getR.response.source.test
assertEquals "value1", getR.response.source.complex.value1
response = node.client.index({
index = "test"
type = "type1"
id = "1"
source = {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
}
}
}).response
assertEquals "test", response.index
assertEquals "type1", response.type
assertEquals "1", response.id
def indexR = node.client.index(indexRequest().with {
index "test"
type "type1"
id "1"
source {
test = "value"
complex {
value1 = "value1"
value2 = "value2"
}
}
})
CountDownLatch latch = new CountDownLatch(1)
indexR.success = {IndexResponse responseX ->
assertEquals "test", responseX.index
assertEquals "test", indexR.response.index
assertEquals "type1", responseX.type
assertEquals "type1", indexR.response.type
assertEquals "1", responseX.id
assertEquals "1", indexR.response.id
latch.countDown()
}
latch.await()
indexR = node.client.index {
void testSimpleOperations() {
def indexR = node.client.index {
index "test"
type "type1"
id "1"
@ -105,14 +39,9 @@ class SimpleActionsTests extends GroovyTestCase {
}
}
}
latch = new CountDownLatch(1)
indexR.listener = {
assertEquals "test", indexR.response.index
assertEquals "type1", indexR.response.type
assertEquals "1", indexR.response.id
latch.countDown()
}
latch.await()
def delete = node.client.delete {
index "test"
@ -123,15 +52,15 @@ class SimpleActionsTests extends GroovyTestCase {
assertEquals "type1", delete.response.type
assertEquals "1", delete.response.id
refresh = node.client.admin.indices.refresh {}
def refresh = node.client.admin.indices.refresh {}
assertEquals 0, refresh.response.failedShards
getR = node.client.get {
def get = node.client.get {
index "test"
type "type1"
id "1"
}
assertFalse getR.response.exists
assertFalse get.response.exists
indexR = node.client.index {
index "test"
@ -145,19 +74,13 @@ class SimpleActionsTests extends GroovyTestCase {
}
}
}
assertEquals "test", indexR.response.index
assertEquals "type1", indexR.response.type
assertEquals "1", indexR.response.id
refresh = node.client.admin.indices.refresh {}
assertEquals 0, refresh.response.failedShards
getR = node.client.get {
index "test"
type "type1"
id "1"
}
assertTrue getR.response.exists
def count = node.client.count {
indices "test"
types "type1"
@ -170,6 +93,19 @@ class SimpleActionsTests extends GroovyTestCase {
assertEquals 0, count.response.failedShards
assertEquals 1, count.response.count
def search = node.client.search {
indices "test"
types "type1"
source {
query {
term(test: "value")
}
}
}
assertEquals 0, search.response.failedShards
assertEquals 1, search.response.hits.totalHits
assertEquals "value", search.response.hits[0].source.test
def deleteByQuery = node.client.deleteByQuery {
indices "test"
query {
@ -181,11 +117,11 @@ class SimpleActionsTests extends GroovyTestCase {
refresh = node.client.admin.indices.refresh {}
assertEquals 0, refresh.response.failedShards
getR = node.client.get {
get = node.client.get {
index "test"
type "type1"
id "1"
}
assertFalse getR.response.exists
assertFalse get.response.exists
}
}