how to write like facet.method=enum in query with spring solr - spring

in solr query...
facet.method=enum
how spring data solr can do like above.
SimpleFacetQuery facetQuery = new SimpleFacetQuery(new Criteria(CrawlDocument.FIELD_CONTENT).contains(searchStr));
facetQuery.setFacetOptions(new FacetOptions().addFacetOnField(CrawlDocument.FIELD_CONTENT).setFacetLimit(20));
????
please give tips

It's depends on solrj-1.1.0 and spring-data-4.6.1.
#Test
public void testFacetMethodEnum() throws SolrServerException {
SimpleFacetQuery query = new SimpleFacetQuery();
query.addCriteria(new Criteria("coumn_name1").is("value1"));
query.addCriteria(new Criteria("coumn_name2").is("value2"));
query.addProjectionOnField("projection_1");
FacetOptions facetOptions = new FacetOptions("facet_field");
facetOptions.setFacetLimit(1000);
query.setFacetOptions(facetOptions);
QueryParsers queryParsers = new QueryParsers();
SolrQuery solrQuery = queryParsers.getForClass(query.getClass()).constructSolrQuery(query);
solrQuery.setParam(FacetParams.FACET_METHOD, FacetParams.FACET_METHOD_enum);
QueryResponse reponse = Your_SolrTemplate.getSolrOperations().getSolrServer().query(solrQuery);
assertNotNull(reponse);
}

Related

ElasticSearch new Java API print created quesy

I trying out the new Java Client for Elastic 8.1.1.
In older versions i was able to print out the generated json query by using searchRequest.source().
I cannot find out actuallay what methode/service i can use do to so with the new client.
My code looks:
final Query range_query = new Query.Builder().range(r -> r.field("pixel_x")
.from(String.valueOf(lookupDto.getPixel_x_min())).to(String.valueOf(lookupDto.getPixel_x_max())))
.build();
final Query bool_query = new Query.Builder().bool(t -> t.must(range_query)).build();
SearchRequest sc = SearchRequest.of(s -> s.query(bool_query).index(INDEX).size(100));
The SearchRequest object offers a source() method but ist value is null.
You can use below code for printing query with new Elastic Java Client:
Query termQuery = TermQuery.of(t -> t.field("field_name").value("search_value"))._toQuery();
StringWriter writer = new StringWriter();
JsonGenerator generator = JacksonJsonProvider.provider().createGenerator(writer);
termQuery.serialize(generator, new JacksonJsonpMapper());
generator.flush();
System.out.println(writer.toString());

spring data mongodb BulkOperations upsert not save the data to mongodb

for (int i = 0; i < deviceDataList.size(); i++) {
updateList = new ArrayList<>();
deviceData = deviceDataList.get(i);
Query query = new Query();
query.addCriteria(new Criteria("seqId").is(deviceData.getDeviceCd()));
query.addCriteria(new Criteria("time").is(deviceData.getGpsAtMillis()));
Update update = new Update();
update.set("seqId", deviceData.getSeqId());
update.set("partId", deviceData.getPartId());
update.set("partName", deviceData.getPartName());
update.set("time", deviceData.getTime());
Pair<Query, Update> updatePair = Pair.of(query, update);
updateList.add(updatePair);
}
MongoTemplate mongoTemplate = null;
BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, collectionName);
operations.upsert(updateList);
BulkWriteResult writeResult = operations.execute();
result.setSuccess(writeResult.wasAcknowledged());
result.setResult(writeResult.getModifiedCount());
I write a code to insert data when data do not exist or update data when data exist, but I find when the update data is included, the updateList data does not save into the MongoDB, I did not know why, this confuse me.
I use MongoDB 3.4.12 and use the spring-data-MongoDB jar, I am not sure why this happens, and what I should do to solve this problem.

How to use SearchAfter API correctly?

I recently work with elasticsearch and I have such a question. I have a million documents in index and I wanna to get more than 10_000. For this I can use scroll API or SearchAfter API. I understood how does scroll api works but I have some problem with SearchAfter.
Here is my SearchSourceBuilder method:
public SearchRequest buildRequest(SearchDistanceParameters args) {
final SearchSourceBuilder searchSourceBuilder = prepareSearchSourceBuilder(args);
final SearchRequest searchRequest = new SearchRequest();
return searchRequest.source(searchSourceBuilder);
}
private SearchSourceBuilder prepareSearchSourceBuilder(SearchDistanceParameters searchDistanceParameters) {
final FieldSortBuilder fieldSortBuilder = new FieldSortBuilder("_id").order(SortOrder.ASC);
final SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
final GeoDistanceQueryBuilder geoDistanceQueryBuilder = geoDistanceQuery(GeoLocationModelFieldName.LOCATION.name().toLowerCase());
geoDistanceQueryBuilder.point(searchDistanceParameters.getLatitude(), searchDistanceParameters.getLongitude());
geoDistanceQueryBuilder.distance(searchDistanceParameters.getDistance(), DistanceUnit.KILOMETERS);
searchSourceBuilder.query(geoDistanceQueryBuilder);
searchSourceBuilder.sort(fieldSortBuilder);
searchSourceBuilder.searchAfter();
return searchSourceBuilder;
}
Here I do sort before searchAfter() as mention in SearchAfter API doc.
Here I am sending my request to ElasticSearch:
public SearchResponse sendRequestToElastic(SearchDistanceParameters args) throws IOException {
SearchRequest searchRequest = searchByDistanceRequestBuilder.buildRequest(args);
return elasticDao.search(searchRequest, RequestOptions.DEFAULT); // standard RestHighLevelClient.search method inside elasticDao.
}
And finally I am trying to get my objects from SearchResponse:
public List<GeoPointsFromElasticSearchResponse> searchByDistance(SearchDistanceParameters searchDistanceParameters) {
final SearchResponse searchResponse = searchRepository.searchByDistance(searchDistanceParameters);
return getGeoPointsFromElasticSearchResponses(searchResponse);
}
private List<GeoPointsFromElasticSearchResponse> getGeoPointsFromElasticSearchResponses(SearchResponse searchResponse) {
SearchHit[] hits = searchResponse.getHits().getHits();
return Arrays.stream(hits)
.map(hit -> {
final GeoPointsFromElasticSearchResponse geoPointsFromElasticSearchResponse = new GeoPointsFromElasticSearchResponse();
final Map<String, Object> sourceMap = hit.getSourceAsMap();
final Map map = (Map) sourceMap.get(GeoLocationModelFieldName.LOCATION.name().toLowerCase());
geoPointsFromElasticSearchResponse.setLatitude((Double) map.get("lat"));
geoPointsFromElasticSearchResponse.setLongitude((Double) map.get("lon"));
log.info("Sorted hits: {}", hit.getSortValues());
return geoPointsFromElasticSearchResponse;
}).collect(Collectors.toList());
}
But I've got only 10_000 objects. It seems I am doing something wrong in last part. What am I doing wrong? How to use SearchAfter api in java correctly?
Well the search API wont return all the documents in one request, the behaviour is similar as pagination.
You have to pass argument to search after:
https://www.elastic.co/guide/en/elasticsearch/reference/6.7/search-request-search-after.html
According to the constructor : searchSourceBuilder.searchAfter(new Object[]{sortAfterValue});
The value you want to set is the one returned by the first search request (hits => getAt(lastIndex) => getSortValues())

(How to achieve pagination with rest high level client and spring?)or an alternative of elasticsearchTemplate.queryForPage()

I'm having issue migrating from transport client to Rest high-level client.
The following code will not work with RestHighLevelClient which I want to use to get a response of aggregated pages of type Class.
elasticsearchTemplate.queryForPage(searchQuery, Class.class)
Any suggestions to achieve the same with other method is also welcomed.
My workaround using restHighLevelClient without Spring data elasticsearch consist in this code (this is not the solution but perhaps could be help for your solution):
BoolQueryBuilder criteriaQuerySpecification = getCriteriaQuerySpecification(transactionFilter);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.sort(new FieldSortBuilder("operation_created_at").order(SortOrder.DESC));
sourceBuilder.query(criteriaQuerySpecification);
SearchRequest searchRequest = generateSearchRequest(totalElementsInt, pageNumberInt, sourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
List<OperationDto > operations = Arrays.asList(hits).stream().map(hit -> {
hit.getSourceAsString();
// get operation is a method mapping from hit to your dto using Map<String, Object> sourceAsMap = hit.getSourceAsMap();
OperationDto operation = getOperationDto(hit);
//convert hit to OperationDto
return operation;
}).collect(Collectors.toList());
private SearchRequest generateSearchRequest(Integer totalElementsInt, Integer pageNumberInt, SearchSourceBuilder sourceBuilder) {
SearchRequest searchRequest = new SearchRequest("operation-index").types("operation");
int offset = pageNumberInt *totalElementsInt;
sourceBuilder.from(offset);
sourceBuilder.size(totalElementsInt);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
return searchRequest;
}
This worked for me
public Page<T> search(){
Query query;
SearchHits<T> t;
Criteria nameCriteria = new Criteria("name").is(text).and(new
Criteria("jsonNode").in(String ...)); //This can be any Aggregator
query = new CriteriaQuery(nameCriteria).setPageable(paging);
searchHits = elasticsearchOperations.search(query, T.class);
return (Page) SearchHitSupport.searchPageFor(searchHits, query.getPageable());;
}

How to save an object using Spring Data ElasticSearchTemplate

How do I save an entity using Spring Data ElasticSearchTemplate? Can't find it in the documentation.
I believe index() is the method for saving an entity in Elasticsearch using the template.
Take a look at this sample application that uses .index() to prepare a JUnit test:
public void before() {
elasticsearchTemplate.deleteIndex(Article.class);
elasticsearchTemplate.createIndex(Article.class);
elasticsearchTemplate.putMapping(Article.class);
elasticsearchTemplate.refresh(Article.class, true);
IndexQuery article1 = new ArticleBuilder("1").title("article four").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addAuthor(JONATHAN_YAN).score(10).buildIndex();
IndexQuery article2 = new ArticleBuilder("2").title("article three").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addPublishedYear(YEAR_2000).score(20).buildIndex();
IndexQuery article3 = new ArticleBuilder("3").title("article two").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(30).buildIndex();
IndexQuery article4 = new ArticleBuilder("4").title("article one").addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(40).buildIndex();
elasticsearchTemplate.index(article1);
elasticsearchTemplate.index(article2);
elasticsearchTemplate.index(article3);
elasticsearchTemplate.index(article4);
elasticsearchTemplate.refresh(Article.class, true);
}
You can, also, use bulkIndex for multiple indexes making use of Elasticsearch's bulk index feature.
Employee employee = new Employee(1,"Mike");
IndexQuery indexQuery = new IndexQueryBuilder()
.withId(employee.getId())
.withIndexName(indexName).withObject(employee)
.withType(indexName).build();
elasticsearchTemplate.index(indexQuery);

Resources