start work on more like this action
This commit is contained in:
parent
1ec1716a7b
commit
284a35131c
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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}.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -76,6 +76,10 @@ public abstract class JsonFilterBuilders {
|
|||
return new QueryJsonFilterBuilder(queryBuilder);
|
||||
}
|
||||
|
||||
public static BoolJsonFilterBuilder boolFilter() {
|
||||
return new BoolJsonFilterBuilder();
|
||||
}
|
||||
|
||||
private JsonFilterBuilders() {
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 + "\" } }";
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
cluster:
|
||||
routing:
|
||||
schedule: 100ms
|
||||
index:
|
||||
numberOfShards: 5
|
||||
numberOfReplicas: 1
|
Loading…
Reference in New Issue