start work on more like this action

This commit is contained in:
kimchy 2010-02-27 00:52:13 +02:00
parent 1ec1716a7b
commit 284a35131c
21 changed files with 962 additions and 222 deletions

View File

@ -45,6 +45,7 @@ import org.elasticsearch.action.deletebyquery.TransportIndexDeleteByQueryAction;
import org.elasticsearch.action.deletebyquery.TransportShardDeleteByQueryAction;
import org.elasticsearch.action.get.TransportGetAction;
import org.elasticsearch.action.index.TransportIndexAction;
import org.elasticsearch.action.mlt.TransportMoreLikeThisAction;
import org.elasticsearch.action.search.TransportSearchAction;
import org.elasticsearch.action.search.TransportSearchScrollAction;
import org.elasticsearch.action.search.type.*;
@ -100,5 +101,7 @@ public class TransportActionModule extends AbstractModule {
bind(TransportSearchScrollQueryThenFetchAction.class).asEagerSingleton();
bind(TransportSearchScrollAction.class).asEagerSingleton();
bind(TransportMoreLikeThisAction.class).asEagerSingleton();
}
}

View File

@ -40,6 +40,8 @@ public class TransportActions {
public static final String TERMS = "indices/terms";
public static final String MORE_LIKE_THIS = "indices/moreLikeThis";
public static class Admin {
public static class Indices {

View File

@ -0,0 +1,274 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.mlt;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.Actions;
import org.elasticsearch.util.Strings;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class MoreLikeThisRequest implements ActionRequest {
private String index;
private String type;
private String id;
private String[] fields;
private float percentTermsToMatch = -1;
private int minTermFrequency = -1;
private int maxQueryTerms = -1;
private String[] stopWords = null;
private int minDocFreq = -1;
private int maxDocFreq = -1;
private int minWordLen = -1;
private int maxWordLen = -1;
private Boolean boostTerms = null;
private float boostTermsFactor = -1;
private boolean threadedListener = false;
public MoreLikeThisRequest() {
}
public MoreLikeThisRequest(String index) {
this.index = index;
}
public String index() {
return index;
}
public String type() {
return type;
}
public MoreLikeThisRequest type(String type) {
this.type = type;
return this;
}
public String id() {
return id;
}
public MoreLikeThisRequest id(String id) {
this.id = id;
return this;
}
public String[] fields() {
return this.fields;
}
public MoreLikeThisRequest percentTermsToMatch(float percentTermsToMatch) {
this.percentTermsToMatch = percentTermsToMatch;
return this;
}
public float percentTermsToMatch() {
return this.percentTermsToMatch;
}
public MoreLikeThisRequest minTermFrequency(int minTermFrequency) {
this.minTermFrequency = minTermFrequency;
return this;
}
public int minTermFrequency() {
return this.minTermFrequency;
}
public MoreLikeThisRequest maxQueryTerms(int maxQueryTerms) {
this.maxQueryTerms = maxQueryTerms;
return this;
}
public int maxQueryTerms() {
return this.maxQueryTerms;
}
public MoreLikeThisRequest stopWords(String... stopWords) {
this.stopWords = stopWords;
return this;
}
public String[] stopWords() {
return this.stopWords;
}
public MoreLikeThisRequest minDocFreq(int minDocFreq) {
this.minDocFreq = minDocFreq;
return this;
}
public int minDocFreq() {
return this.minDocFreq;
}
public MoreLikeThisRequest maxDocFreq(int maxDocFreq) {
this.maxDocFreq = maxDocFreq;
return this;
}
public int maxDocFreq() {
return this.maxDocFreq;
}
public MoreLikeThisRequest minWordLen(int minWordLen) {
this.minWordLen = minWordLen;
return this;
}
public int minWordLen() {
return this.minWordLen;
}
public MoreLikeThisRequest maxWordLen(int maxWordLen) {
this.maxWordLen = maxWordLen;
return this;
}
public int maxWordLen() {
return this.maxWordLen;
}
public MoreLikeThisRequest boostTerms(boolean boostTerms) {
this.boostTerms = boostTerms;
return this;
}
public Boolean boostTerms() {
return this.boostTerms;
}
public MoreLikeThisRequest boostTermsFactor(float boostTermsFactor) {
this.boostTermsFactor = boostTermsFactor;
return this;
}
public float boostTermsFactor() {
return this.boostTermsFactor;
}
@Override public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (index == null) {
validationException = Actions.addValidationError("index is missing", validationException);
}
if (type == null) {
validationException = Actions.addValidationError("type is missing", validationException);
}
if (id == null) {
validationException = Actions.addValidationError("id is missing", validationException);
}
return validationException;
}
@Override public boolean listenerThreaded() {
return threadedListener;
}
@Override public ActionRequest listenerThreaded(boolean listenerThreaded) {
this.threadedListener = listenerThreaded;
return this;
}
@Override public void readFrom(DataInput in) throws IOException, ClassNotFoundException {
index = in.readUTF();
type = in.readUTF();
id = in.readUTF();
// no need to pass threading over the network, they are always false when coming throw a thread pool
int size = in.readInt();
if (size == 0) {
fields = Strings.EMPTY_ARRAY;
} else {
fields = new String[in.readInt()];
for (int i = 0; i < size; i++) {
fields[i] = in.readUTF();
}
}
percentTermsToMatch = in.readFloat();
minTermFrequency = in.readInt();
maxQueryTerms = in.readInt();
size = in.readInt();
if (size > 0) {
stopWords = new String[size];
for (int i = 0; i < size; i++) {
stopWords[i] = in.readUTF();
}
}
minDocFreq = in.readInt();
maxDocFreq = in.readInt();
minWordLen = in.readInt();
maxWordLen = in.readInt();
if (in.readBoolean()) {
boostTerms = in.readBoolean();
}
boostTermsFactor = in.readFloat();
}
@Override public void writeTo(DataOutput out) throws IOException {
out.writeUTF(index);
out.writeUTF(type);
out.writeUTF(id);
if (fields == null) {
out.writeInt(0);
} else {
out.writeInt(fields.length);
for (String field : fields) {
out.writeUTF(field);
}
}
out.writeFloat(percentTermsToMatch);
out.writeInt(minTermFrequency);
out.writeInt(maxQueryTerms);
if (stopWords == null) {
out.writeInt(0);
} else {
out.writeInt(stopWords.length);
for (String stopWord : stopWords) {
out.writeUTF(stopWord);
}
}
out.writeInt(minDocFreq);
out.writeInt(maxDocFreq);
out.writeInt(minWordLen);
out.writeInt(maxWordLen);
if (boostTerms == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeBoolean(boostTerms);
}
out.writeFloat(boostTermsFactor);
}
}

View File

@ -0,0 +1,195 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.action.mlt;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.Term;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.TransportGetAction;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.TransportSearchAction;
import org.elasticsearch.action.support.BaseAction;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMappers;
import org.elasticsearch.index.mapper.InternalMapper;
import org.elasticsearch.index.query.json.BoolJsonQueryBuilder;
import org.elasticsearch.index.query.json.MoreLikeThisFieldJsonQueryBuilder;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.transport.BaseTransportRequestHandler;
import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.settings.Settings;
import java.util.Set;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.index.query.json.JsonQueryBuilders.*;
import static org.elasticsearch.search.builder.SearchSourceBuilder.*;
/**
* @author kimchy (shay.banon)
*/
public class TransportMoreLikeThisAction extends BaseAction<MoreLikeThisRequest, SearchResponse> {
private final TransportSearchAction searchAction;
private final TransportGetAction getAction;
private final IndicesService indicesService;
@Inject public TransportMoreLikeThisAction(Settings settings, TransportSearchAction searchAction, TransportGetAction getAction,
IndicesService indicesService, TransportService transportService) {
super(settings);
this.searchAction = searchAction;
this.getAction = getAction;
this.indicesService = indicesService;
transportService.registerHandler(TransportActions.MORE_LIKE_THIS, new TransportHandler());
}
@Override protected void doExecute(final MoreLikeThisRequest request, final ActionListener<SearchResponse> listener) {
GetRequest getRequest = getRequest(request.index())
.type(request.type())
.id(request.id())
.listenerThreaded(false);
getAction.execute(getRequest, new ActionListener<GetResponse>() {
@Override public void onResponse(GetResponse getResponse) {
if (getResponse.empty()) {
listener.onFailure(new ElasticSearchException("document missing"));
return;
}
final BoolJsonQueryBuilder boolBuilder = boolQuery();
try {
DocumentMapper docMapper = indicesService.indexServiceSafe(request.index()).mapperService().documentMapper(request.type());
final Set<String> fields = Sets.newHashSet();
if (request.fields() != null) {
for (String field : request.fields()) {
FieldMappers fieldMappers = docMapper.mappers().smartName(field);
if (fieldMappers != null) {
fields.add(fieldMappers.mapper().names().indexName());
} else {
fields.add(field);
}
}
}
docMapper.parse(request.type(), request.id(), getResponse.source(), new DocumentMapper.ParseListenerAdapter() {
@Override public boolean beforeFieldAdded(FieldMapper fieldMapper, Fieldable field, Object parseContext) {
if (fieldMapper instanceof InternalMapper) {
return true;
}
String value = fieldMapper.valueAsString(field);
if (value == null) {
return false;
}
if (fields.isEmpty() || fields.contains(field.name())) {
addMoreLikeThis(request, boolBuilder, fieldMapper, field);
}
return false;
}
});
// exclude myself
Term uidTerm = docMapper.uidMapper().term(request.type(), request.id());
boolBuilder.mustNot(termQuery(uidTerm.field(), uidTerm.text()));
} catch (Exception e) {
listener.onFailure(e);
}
SearchRequest searchRequest = searchRequest(request.index()).types(request.type())
.listenerThreaded(request.listenerThreaded())
.source(searchSource()
.query(boolBuilder)
);
searchAction.execute(searchRequest, new ActionListener<SearchResponse>() {
@Override public void onResponse(SearchResponse response) {
listener.onResponse(response);
}
@Override public void onFailure(Throwable e) {
listener.onFailure(e);
}
});
}
@Override public void onFailure(Throwable e) {
listener.onFailure(e);
}
});
}
private void addMoreLikeThis(MoreLikeThisRequest request, BoolJsonQueryBuilder boolBuilder, FieldMapper fieldMapper, Fieldable field) {
MoreLikeThisFieldJsonQueryBuilder mlt = moreLikeThisFieldQuery(field.name())
.likeText(fieldMapper.valueAsString(field))
.percentTermsToMatch(request.percentTermsToMatch())
.boostTerms(request.boostTerms())
.boostTermsFactor(request.boostTermsFactor())
.minDocFreq(request.minDocFreq())
.maxDocFreq(request.maxDocFreq())
.minWordLen(request.minWordLen())
.maxWordLen(request.maxWordLen())
.minTermFrequency(request.minTermFrequency())
.maxQueryTerms(request.maxQueryTerms())
.stopWords(request.stopWords());
boolBuilder.should(mlt);
}
private class TransportHandler extends BaseTransportRequestHandler<MoreLikeThisRequest> {
@Override public MoreLikeThisRequest newInstance() {
return new MoreLikeThisRequest();
}
@Override public void messageReceived(MoreLikeThisRequest request, final TransportChannel channel) throws Exception {
// no need to have a threaded listener since we just send back a response
request.listenerThreaded(false);
execute(request, new ActionListener<SearchResponse>() {
@Override public void onResponse(SearchResponse result) {
try {
channel.sendResponse(result);
} catch (Exception e) {
onFailure(e);
}
}
@Override public void onFailure(Throwable e) {
try {
channel.sendResponse(e);
} catch (Exception e1) {
logger.warn("Failed to send response for get", e1);
}
}
});
}
@Override public boolean spawn() {
return false;
}
}
}

View File

@ -37,7 +37,7 @@ import static org.elasticsearch.action.Actions.*;
* <p>This is very handy to implement things like tag clouds and auto complete (using {@link #prefix(String)} or
* {@link #regexp(String)}).
*
* @author kimchy (Shay Banon)
* @author kimchy (shay.banon)
*/
public class TermsRequest extends BroadcastOperationRequest {

View File

@ -31,6 +31,7 @@ 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.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
@ -266,9 +267,40 @@ public interface Client {
*/
void execSearchScroll(SearchScrollRequest request, ActionListener<SearchResponse> listener);
/**
* A terms request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param request The term request
* @return The result future
* @see Requests#termsRequest(String...)
*/
ActionFuture<TermsResponse> terms(TermsRequest request);
/**
* A terms request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param request The term request
* @param listener A listener to be notified of the result
* @return The result future
* @see Requests#termsRequest(String...)
*/
ActionFuture<TermsResponse> terms(TermsRequest request, ActionListener<TermsResponse> listener);
/**
* A terms request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param request The term request
* @param listener A listener to be notified of the result
* @see Requests#termsRequest(String...)
*/
void execTerms(TermsRequest request, ActionListener<TermsResponse> listener);
ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request);
ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener);
void execMoreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener);
}

View File

@ -38,6 +38,7 @@ import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.deletebyquery.DeleteByQueryRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.terms.TermsRequest;
@ -109,10 +110,26 @@ public class Requests {
return new CountRequest(indices);
}
/**
* Terms request represent a request to get terms in one or more indices of specific fields and their
* document frequencies (in how many document each term exists).
*
* @param indices The indices the delete by query against. Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
* @return The terms request
* @see org.elasticsearch.client.Client#terms(org.elasticsearch.action.terms.TermsRequest)
*/
public static TermsRequest termsRequest(String... indices) {
return new TermsRequest(indices);
}
/**
* @param index
* @return
*/
public static MoreLikeThisRequest moreLikeThisRequest(String index) {
return new MoreLikeThisRequest(index);
}
/**
* Creates a search request against one or more indices. Note, the search source must be set either using the
* actual JSON search source, or the {@link org.elasticsearch.search.builder.SearchSourceBuilder}.

View File

@ -37,6 +37,8 @@ import org.elasticsearch.action.get.TransportGetAction;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.index.TransportIndexAction;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.mlt.TransportMoreLikeThisAction;
import org.elasticsearch.action.search.*;
import org.elasticsearch.action.terms.TermsRequest;
import org.elasticsearch.action.terms.TermsResponse;
@ -69,11 +71,13 @@ public class ServerClient extends AbstractComponent implements Client {
private final TransportTermsAction termsAction;
private final TransportMoreLikeThisAction moreLikeThisAction;
@Inject public ServerClient(Settings settings, ServerAdminClient admin,
TransportIndexAction indexAction, TransportDeleteAction deleteAction,
TransportDeleteByQueryAction deleteByQueryAction, TransportGetAction getAction, TransportCountAction countAction,
TransportSearchAction searchAction, TransportSearchScrollAction searchScrollAction,
TransportTermsAction termsAction) {
TransportTermsAction termsAction, TransportMoreLikeThisAction moreLikeThisAction) {
super(settings);
this.admin = admin;
this.indexAction = indexAction;
@ -84,6 +88,7 @@ public class ServerClient extends AbstractComponent implements Client {
this.searchAction = searchAction;
this.searchScrollAction = searchScrollAction;
this.termsAction = termsAction;
this.moreLikeThisAction = moreLikeThisAction;
}
@Override public void close() {
@ -189,4 +194,16 @@ public class ServerClient extends AbstractComponent implements Client {
@Override public void execTerms(TermsRequest request, ActionListener<TermsResponse> listener) {
termsAction.execute(request, listener);
}
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request) {
return moreLikeThisAction.submit(request);
}
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
return moreLikeThisAction.submit(request, listener);
}
@Override public void execMoreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
moreLikeThisAction.execute(request, listener);
}
}

View File

@ -36,6 +36,7 @@ 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.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
@ -304,4 +305,16 @@ public class TransportClient implements Client {
@Override public void execTerms(TermsRequest request, ActionListener<TermsResponse> listener) {
internalClient.terms(request, listener);
}
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request) {
return internalClient.moreLikeThis(request);
}
@Override public ActionFuture<SearchResponse> moreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
return internalClient.moreLikeThis(request, listener);
}
@Override public void execMoreLikeThis(MoreLikeThisRequest request, ActionListener<SearchResponse> listener) {
internalClient.execMoreLikeThis(request, listener);
}
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.transport.action.mlt;
import com.google.inject.Inject;
import org.elasticsearch.action.TransportActions;
import org.elasticsearch.action.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.action.support.BaseClientTransportAction;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.settings.Settings;
/**
* @author kimchy (shay.banon)
*/
public class ClientTransportMoreLikeThisAction extends BaseClientTransportAction<MoreLikeThisRequest, SearchResponse> {
@Inject public ClientTransportMoreLikeThisAction(Settings settings, TransportService transportService) {
super(settings, transportService, SearchResponse.class);
}
@Override protected String action() {
return TransportActions.MORE_LIKE_THIS;
}
}

View File

@ -33,6 +33,7 @@ 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.mlt.MoreLikeThisRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
@ -46,6 +47,7 @@ import org.elasticsearch.client.transport.action.delete.ClientTransportDeleteAct
import org.elasticsearch.client.transport.action.deletebyquery.ClientTransportDeleteByQueryAction;
import org.elasticsearch.client.transport.action.get.ClientTransportGetAction;
import org.elasticsearch.client.transport.action.index.ClientTransportIndexAction;
import org.elasticsearch.client.transport.action.mlt.ClientTransportMoreLikeThisAction;
import org.elasticsearch.client.transport.action.search.ClientTransportSearchAction;
import org.elasticsearch.client.transport.action.search.ClientTransportSearchScrollAction;
import org.elasticsearch.client.transport.action.terms.ClientTransportTermsAction;
@ -78,11 +80,13 @@ public class InternalTransportClient extends AbstractComponent implements Client
private final ClientTransportTermsAction termsAction;
private final ClientTransportMoreLikeThisAction moreLikeThisAction;
@Inject public InternalTransportClient(Settings settings, TransportClientNodesService nodesService, InternalTransportAdminClient adminClient,
ClientTransportIndexAction indexAction, ClientTransportDeleteAction deleteAction, ClientTransportGetAction getAction,
ClientTransportDeleteByQueryAction deleteByQueryAction, ClientTransportCountAction countAction,
ClientTransportSearchAction searchAction, ClientTransportSearchScrollAction searchScrollAction,
ClientTransportTermsAction termsAction) {
ClientTransportTermsAction termsAction, ClientTransportMoreLikeThisAction moreLikeThisAction) {
super(settings);
this.nodesService = nodesService;
this.adminClient = adminClient;
@ -95,6 +99,7 @@ public class InternalTransportClient extends AbstractComponent implements Client
this.searchAction = searchAction;
this.searchScrollAction = searchScrollAction;
this.termsAction = termsAction;
this.moreLikeThisAction = moreLikeThisAction;
}
@Override public void close() {
@ -304,4 +309,29 @@ public class InternalTransportClient extends AbstractComponent implements Client
}
});
}
@Override public ActionFuture<SearchResponse> moreLikeThis(final MoreLikeThisRequest request) {
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<SearchResponse>>() {
@Override public ActionFuture<SearchResponse> doWithNode(Node node) throws ElasticSearchException {
return moreLikeThisAction.submit(node, request);
}
});
}
@Override public ActionFuture<SearchResponse> moreLikeThis(final MoreLikeThisRequest request, final ActionListener<SearchResponse> listener) {
return nodesService.execute(new TransportClientNodesService.NodeCallback<ActionFuture<SearchResponse>>() {
@Override public ActionFuture<SearchResponse> doWithNode(Node node) throws ElasticSearchException {
return moreLikeThisAction.submit(node, request, listener);
}
});
}
@Override public void execMoreLikeThis(final MoreLikeThisRequest request, final ActionListener<SearchResponse> listener) {
nodesService.execute(new TransportClientNodesService.NodeCallback<Void>() {
@Override public Void doWithNode(Node node) throws ElasticSearchException {
moreLikeThisAction.submit(node, request);
return null;
}
});
}
}

View File

@ -0,0 +1,76 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.query.json;
import org.apache.lucene.search.BooleanClause;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.ArrayList;
/**
* @author kimchy (Shay Banon)
*/
public class BoolJsonFilterBuilder extends BaseJsonQueryBuilder {
private ArrayList<Clause> clauses = new ArrayList<Clause>();
public BoolJsonFilterBuilder must(JsonFilterBuilder filterBuilder) {
clauses.add(new Clause(filterBuilder, BooleanClause.Occur.MUST));
return this;
}
public BoolJsonFilterBuilder mustNot(JsonFilterBuilder filterBuilder) {
clauses.add(new Clause(filterBuilder, BooleanClause.Occur.MUST_NOT));
return this;
}
public BoolJsonFilterBuilder should(JsonFilterBuilder filterBuilder) {
clauses.add(new Clause(filterBuilder, BooleanClause.Occur.SHOULD));
return this;
}
@Override protected void doJson(JsonBuilder builder, Params params) throws IOException {
builder.startObject("bool");
for (Clause clause : clauses) {
if (clause.occur == BooleanClause.Occur.MUST) {
builder.field("must");
clause.filterBuilder.toJson(builder, params);
} else if (clause.occur == BooleanClause.Occur.MUST_NOT) {
builder.field("mustNot");
clause.filterBuilder.toJson(builder, params);
} else if (clause.occur == BooleanClause.Occur.SHOULD) {
builder.field("should");
clause.filterBuilder.toJson(builder, params);
}
}
builder.endObject();
}
private static class Clause {
final JsonFilterBuilder filterBuilder;
final BooleanClause.Occur occur;
private Clause(JsonFilterBuilder filterBuilder, BooleanClause.Occur occur) {
this.filterBuilder = filterBuilder;
this.occur = occur;
}
}
}

View File

@ -88,7 +88,7 @@ public class BoolJsonQueryBuilder extends BaseJsonQueryBuilder {
if (disableCoord != null) {
builder.field("disableCoord", disableCoord);
}
if (minimumNumberShouldMatch == -1) {
if (minimumNumberShouldMatch != -1) {
builder.field("minimumNumberShouldMatch", minimumNumberShouldMatch);
}
builder.endObject();

View File

@ -76,6 +76,10 @@ public abstract class JsonFilterBuilders {
return new QueryJsonFilterBuilder(queryBuilder);
}
public static BoolJsonFilterBuilder boolFilter() {
return new BoolJsonFilterBuilder();
}
private JsonFilterBuilders() {
}

View File

@ -92,7 +92,7 @@ public class MoreLikeThisFieldJsonQueryBuilder extends BaseJsonQueryBuilder {
return this;
}
public MoreLikeThisFieldJsonQueryBuilder boostTerms(boolean boostTerms) {
public MoreLikeThisFieldJsonQueryBuilder boostTerms(Boolean boostTerms) {
this.boostTerms = boostTerms;
return this;
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.util.lucene.search;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.elasticsearch.util.lucene.Lucene;
import org.testng.annotations.Test;
import static org.elasticsearch.util.lucene.DocumentBuilder.*;
import static org.elasticsearch.util.lucene.IndexWriters.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (shay.banon)
*/
@Test
public class MoreLikeThisQueryTests {
@Test public void testSimple() throws Exception {
Directory dir = new RAMDirectory();
IndexWriter indexWriter = new IndexWriter(dir, Lucene.STANDARD_ANALYZER, true, IndexWriter.MaxFieldLength.UNLIMITED);
indexWriter.commit();
assertThat("Index is empty after creation and commit", estimateRamSize(indexWriter), equalTo(0l));
indexWriter.addDocument(doc().add(field("_id", "1")).add(field("text", "lucene")).build());
indexWriter.addDocument(doc().add(field("_id", "2")).add(field("text", "lucene release")).build());
IndexReader reader = indexWriter.getReader();
IndexSearcher searcher = new IndexSearcher(reader);
MoreLikeThisQuery mltQuery = new MoreLikeThisQuery("lucene", new String[]{"text"}, Lucene.STANDARD_ANALYZER);
mltQuery.setLikeText("lucene");
mltQuery.setMinTermFrequency(1);
mltQuery.setMinDocFreq(1);
long count = Lucene.count(searcher, mltQuery, -1);
assertThat(count, equalTo(2l));
reader.close();
indexWriter.close();
}
}

View File

@ -1,189 +0,0 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.integration.client.transport;
import org.elasticsearch.action.admin.indices.flush.FlushResponse;
import org.elasticsearch.action.admin.indices.optimize.OptimizeResponse;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.admin.indices.status.IndicesStatusResponse;
import org.elasticsearch.action.count.CountResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.server.internal.InternalServer;
import org.elasticsearch.test.integration.AbstractServersTests;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.Unicode;
import org.elasticsearch.util.transport.TransportAddress;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.index.query.json.JsonQueryBuilders.*;
import static org.elasticsearch.util.settings.ImmutableSettings.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (Shay Banon)
*/
public class SimpleSingleTransportClientTests extends AbstractServersTests {
private TransportClient client;
@AfterMethod public void closeServers() {
closeAllServers();
if (client != null) {
client.close();
}
}
@Test public void testOnlyWithTransportAddress() throws Exception {
startServer("server1");
TransportAddress server1Address = ((InternalServer) server("server1")).injector().getInstance(TransportService.class).boundAddress().publishAddress();
client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", false).build());
client.addTransportAddress(server1Address);
testSimpleActions(client);
}
/*@Test*/
public void testWithDiscovery() throws Exception {
startServer("server1");
client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", true).build());
// wait a bit so nodes will be discovered
Thread.sleep(1000);
testSimpleActions(client);
}
private void testSimpleActions(Client client) throws Exception {
logger.info("Creating index test");
client.admin().indices().create(createIndexRequest("test")).actionGet();
Thread.sleep(500);
IndexResponse indexResponse = client.index(Requests.indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
assertThat(indexResponse.id(), equalTo("1"));
assertThat(indexResponse.type(), equalTo("type1"));
logger.info("Refreshing");
RefreshResponse refreshResponse = client.admin().indices().refresh(refreshRequest("test")).actionGet();
assertThat(refreshResponse.successfulShards(), equalTo(5));
assertThat(refreshResponse.failedShards(), equalTo(5)); // 5 are not active, since we started just one server
logger.info("Optimizing");
OptimizeResponse optimizeResponse = client.admin().indices().optimize(optimizeRequest("test")).actionGet();
assertThat(optimizeResponse.successfulShards(), equalTo(5));
assertThat(optimizeResponse.failedShards(), equalTo(5)); // 5 are not active, since we started just one server
IndicesStatusResponse indicesStatusResponse = client.admin().indices().status(indicesStatus()).actionGet();
assertThat(indicesStatusResponse.successfulShards(), equalTo(5));
assertThat(indicesStatusResponse.failedShards(), equalTo(5)); // 5 are not active, since we started just one server
assertThat(indicesStatusResponse.indices().size(), equalTo(1));
assertThat(indicesStatusResponse.index("test").shards().size(), equalTo(5)); // 5 index shards (1 with 1 backup)
assertThat(indicesStatusResponse.index("test").docs().numDocs(), equalTo(1l));
GetResponse getResult;
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1").threadedOperation(false)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client.get(getRequest("test").type("type1").id("1").threadedOperation(true)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
}
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat(getResult.empty(), equalTo(true));
}
DeleteResponse deleteResponse = client.delete(deleteRequest("test").type("type1").id("1")).actionGet();
assertThat(deleteResponse.id(), equalTo("1"));
assertThat(deleteResponse.type(), equalTo("type1"));
client.admin().indices().refresh(refreshRequest("test")).actionGet();
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat(getResult.empty(), equalTo(true));
}
client.index(Requests.indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
client.index(Requests.indexRequest("test").type("type1").id("2").source(source("2", "test"))).actionGet();
FlushResponse flushResult = client.admin().indices().flush(flushRequest("test")).actionGet();
assertThat(flushResult.successfulShards(), equalTo(5));
assertThat(flushResult.failedShards(), equalTo(5)); // we only start one server
client.admin().indices().refresh(refreshRequest("test")).actionGet();
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("2", "test")));
}
// check count
for (int i = 0; i < 5; i++) {
// test successful
CountResponse countResponse = client.count(countRequest("test").querySource(termQuery("_type", "type1"))).actionGet();
assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0));
// test failed (simply query that can't be parsed)
countResponse = client.count(countRequest("test").querySource(Unicode.fromStringAsBytes("{ term : { _type : \"type1 } }"))).actionGet();
assertThat(countResponse.count(), equalTo(0l));
assertThat(countResponse.successfulShards(), equalTo(0));
assertThat(countResponse.failedShards(), equalTo(5));
}
DeleteByQueryResponse queryResponse = client.deleteByQuery(deleteByQueryRequest("test").querySource(termQuery("name", "test2"))).actionGet();
assertThat(queryResponse.index("test").successfulShards(), equalTo(5));
assertThat(queryResponse.index("test").failedShards(), equalTo(0));
client.admin().indices().refresh(refreshRequest("test")).actionGet();
for (int i = 0; i < 5; i++) {
getResult = client.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.empty(), equalTo(false));
}
// stop the server
closeServer("server1");
// it should try and reconnect
try {
client.index(Requests.indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
assert false : "should fail...";
} catch (NoNodeAvailableException e) {
// all is well
}
}
private String source(String id, String nameValue) {
return "{ type1 : { \"id\" : \"" + id + "\", \"name\" : \"" + nameValue + "\" } }";
}
}

View File

@ -0,0 +1,49 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.integration.client.transport;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.server.internal.InternalServer;
import org.elasticsearch.test.integration.document.DocumentActionsTests;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.util.transport.TransportAddress;
import static org.elasticsearch.util.settings.ImmutableSettings.*;
/**
* @author kimchy (shay.banon)
*/
public class TransportClientDocumentActionsTests extends DocumentActionsTests {
@Override protected Client getClient1() {
TransportAddress server1Address = ((InternalServer) server("server1")).injector().getInstance(TransportService.class).boundAddress().publishAddress();
TransportClient client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", false).build());
client.addTransportAddress(server1Address);
return client;
}
@Override protected Client getClient2() {
TransportAddress server1Address = ((InternalServer) server("server2")).injector().getInstance(TransportService.class).boundAddress().publishAddress();
TransportClient client = new TransportClient(settingsBuilder().putBoolean("discovery.enabled", false).build());
client.addTransportAddress(server1Address);
return client;
}
}

View File

@ -30,9 +30,11 @@ import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.broadcast.BroadcastOperationThreading;
import org.elasticsearch.client.Client;
import org.elasticsearch.test.integration.AbstractServersTests;
import org.elasticsearch.util.Unicode;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*;
@ -45,34 +47,51 @@ import static org.hamcrest.Matchers.*;
*/
public class DocumentActionsTests extends AbstractServersTests {
private Client client1;
private Client client2;
@BeforeMethod public void startServers() {
startServer("server1");
startServer("server2");
client1 = getClient1();
client2 = getClient2();
}
@AfterMethod public void closeServers() {
client1.close();
client2.close();
closeAllServers();
}
@Test public void testIndexActions() throws Exception {
startServer("server1");
startServer("server2");
protected Client getClient1() {
return client("server1");
}
protected Client getClient2() {
return client("server2");
}
@Test public void testIndexActions() throws Exception {
logger.info("Creating index test");
client("server1").admin().indices().create(createIndexRequest("test")).actionGet();
client1.admin().indices().create(createIndexRequest("test")).actionGet();
logger.info("Running Cluster Health");
ClusterHealthResponse clusterHealth = client("server1").admin().cluster().health(clusterHealth().waitForGreenStatus()).actionGet();
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealth().waitForGreenStatus()).actionGet();
logger.info("Done Cluster Health, status " + clusterHealth.status());
assertThat(clusterHealth.timedOut(), equalTo(false));
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
logger.info("Indexing [type1/1]");
IndexResponse indexResponse = client("server1").index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
IndexResponse indexResponse = client1.index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
assertThat(indexResponse.id(), equalTo("1"));
assertThat(indexResponse.type(), equalTo("type1"));
logger.info("Refreshing");
RefreshResponse refreshResponse = client("server1").admin().indices().refresh(refreshRequest("test")).actionGet();
RefreshResponse refreshResponse = client1.admin().indices().refresh(refreshRequest("test")).actionGet();
assertThat(refreshResponse.successfulShards(), equalTo(10));
assertThat(refreshResponse.failedShards(), equalTo(0));
logger.info("Optimizing");
OptimizeResponse optimizeResponse = client("server1").admin().indices().optimize(optimizeRequest("test")).actionGet();
OptimizeResponse optimizeResponse = client1.admin().indices().optimize(optimizeRequest("test")).actionGet();
assertThat(optimizeResponse.successfulShards(), equalTo(10));
assertThat(optimizeResponse.failedShards(), equalTo(0));
@ -80,48 +99,48 @@ public class DocumentActionsTests extends AbstractServersTests {
logger.info("Get [type1/1]");
for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1").threadedOperation(false)).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("1").threadedOperation(false)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client("server1").get(getRequest("test").type("type1").id("1").threadedOperation(true)).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("1").threadedOperation(true)).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
}
logger.info("Get [type1/2] (should be empty)");
for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("2")).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat(getResult.empty(), equalTo(true));
}
logger.info("Delete [type1/1]");
DeleteResponse deleteResponse = client("server1").delete(deleteRequest("test").type("type1").id("1")).actionGet();
DeleteResponse deleteResponse = client1.delete(deleteRequest("test").type("type1").id("1")).actionGet();
assertThat(deleteResponse.id(), equalTo("1"));
assertThat(deleteResponse.type(), equalTo("type1"));
logger.info("Refreshing");
client("server1").admin().indices().refresh(refreshRequest("test")).actionGet();
client1.admin().indices().refresh(refreshRequest("test")).actionGet();
logger.info("Get [type1/1] (should be empty)");
for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1")).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat(getResult.empty(), equalTo(true));
}
logger.info("Index [type1/1]");
client("server1").index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
client1.index(indexRequest("test").type("type1").id("1").source(source("1", "test"))).actionGet();
logger.info("Index [type1/2]");
client("server1").index(indexRequest("test").type("type1").id("2").source(source("2", "test"))).actionGet();
client1.index(indexRequest("test").type("type1").id("2").source(source("2", "test"))).actionGet();
logger.info("Flushing");
FlushResponse flushResult = client("server1").admin().indices().flush(flushRequest("test")).actionGet();
FlushResponse flushResult = client1.admin().indices().flush(flushRequest("test")).actionGet();
assertThat(flushResult.successfulShards(), equalTo(10));
assertThat(flushResult.failedShards(), equalTo(0));
logger.info("Refreshing");
client("server1").admin().indices().refresh(refreshRequest("test")).actionGet();
client1.admin().indices().refresh(refreshRequest("test")).actionGet();
logger.info("Get [type1/1] and [type1/2]");
for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1")).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client("server1").get(getRequest("test").type("type1").id("2")).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("2", "test")));
}
@ -129,23 +148,23 @@ public class DocumentActionsTests extends AbstractServersTests {
// check count
for (int i = 0; i < 5; i++) {
// test successful
CountResponse countResponse = client("server1").count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.NO_THREADS)).actionGet();
CountResponse countResponse = client1.count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.NO_THREADS)).actionGet();
assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0));
countResponse = client("server1").count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.SINGLE_THREAD)).actionGet();
countResponse = client1.count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.SINGLE_THREAD)).actionGet();
assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0));
countResponse = client("server1").count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.THREAD_PER_SHARD)).actionGet();
countResponse = client1.count(countRequest("test").querySource(termQuery("_type", "type1")).operationThreading(BroadcastOperationThreading.THREAD_PER_SHARD)).actionGet();
assertThat(countResponse.count(), equalTo(2l));
assertThat(countResponse.successfulShards(), equalTo(5));
assertThat(countResponse.failedShards(), equalTo(0));
// test failed (simply query that can't be parsed)
countResponse = client("server1").count(countRequest("test").querySource(Unicode.fromStringAsBytes("{ term : { _type : \"type1 } }"))).actionGet();
countResponse = client1.count(countRequest("test").querySource(Unicode.fromStringAsBytes("{ term : { _type : \"type1 } }"))).actionGet();
assertThat(countResponse.count(), equalTo(0l));
assertThat(countResponse.successfulShards(), equalTo(0));
@ -153,16 +172,16 @@ public class DocumentActionsTests extends AbstractServersTests {
}
logger.info("Delete by query");
DeleteByQueryResponse queryResponse = client("server2").deleteByQuery(deleteByQueryRequest("test").querySource(termQuery("name", "test2"))).actionGet();
DeleteByQueryResponse queryResponse = client2.deleteByQuery(deleteByQueryRequest("test").querySource(termQuery("name", "test2"))).actionGet();
assertThat(queryResponse.index("test").successfulShards(), equalTo(5));
assertThat(queryResponse.index("test").failedShards(), equalTo(0));
client("server1").admin().indices().refresh(refreshRequest("test")).actionGet();
client1.admin().indices().refresh(refreshRequest("test")).actionGet();
logger.info("Get [type1/1] and [type1/2], should be empty");
for (int i = 0; i < 5; i++) {
getResult = client("server1").get(getRequest("test").type("type1").id("1")).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("1")).actionGet();
assertThat("cycle #" + i, getResult.sourceAsString(), equalTo(source("1", "test")));
getResult = client("server1").get(getRequest("test").type("type1").id("2")).actionGet();
getResult = client1.get(getRequest("test").type("type1").id("2")).actionGet();
assertThat("cycle #" + i, getResult.empty(), equalTo(false));
}
}

View File

@ -0,0 +1,86 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.integration.document;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.test.integration.AbstractServersTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.util.json.JsonBuilder.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (shay.banon)
*/
public class MoreLikeThisActionTests extends AbstractServersTests {
private Client client1;
private Client client2;
@BeforeMethod public void startServers() {
startServer("server1");
startServer("server2");
client1 = getClient1();
client2 = getClient2();
}
@AfterMethod public void closeServers() {
client1.close();
client2.close();
closeAllServers();
}
protected Client getClient1() {
return client("server1");
}
protected Client getClient2() {
return client("server2");
}
@Test public void testSimpleMoreLikeThis() throws Exception {
logger.info("Creating index test");
client1.admin().indices().create(createIndexRequest("test")).actionGet();
logger.info("Running Cluster Health");
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealth().waitForGreenStatus()).actionGet();
logger.info("Done Cluster Health, status " + clusterHealth.status());
assertThat(clusterHealth.timedOut(), equalTo(false));
assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN));
logger.info("Indexing...");
client1.index(indexRequest("test").type("type1").id("1").source(binaryJsonBuilder().startObject().field("text", "lucene").endObject())).actionGet();
client1.index(indexRequest("test").type("type1").id("2").source(binaryJsonBuilder().startObject().field("text", "lucene release").endObject())).actionGet();
client1.admin().indices().refresh(refreshRequest()).actionGet();
logger.info("Running moreLikeThis");
SearchResponse mltResponse = client1.moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFrequency(1).minDocFreq(1)).actionGet();
assertThat(mltResponse.successfulShards(), equalTo(5));
assertThat(mltResponse.failedShards(), equalTo(0));
assertThat(mltResponse.hits().totalHits(), equalTo(1l));
}
}

View File

@ -0,0 +1,6 @@
cluster:
routing:
schedule: 100ms
index:
numberOfShards: 5
numberOfReplicas: 1