use of com.rbmhtechnology.vind.model.DocumentFactory in project vind by RBMHTechnology.
the class SolrSearchServer method buildSolrQuery.
protected SolrQuery buildSolrQuery(ExecutableSuggestionSearch search, DocumentFactory assets, DocumentFactory childFactory) {
final String searchContext = search.getSearchContext();
final SolrQuery query = new SolrQuery();
query.setRequestHandler("/suggester");
if (search.isStringSuggestion()) {
StringSuggestionSearch s = (StringSuggestionSearch) search;
query.setParam("suggestion.field", s.getSuggestionFields().stream().map(name -> {
if (Objects.nonNull(childFactory)) {
final FieldDescriptor<?> field = Objects.nonNull(assets.getField(name)) ? assets.getField(name) : childFactory.getField(name);
if (Objects.isNull(field)) {
log.warn("No field descriptor found for field name {} in factories: {}, {}", name, assets.getType(), childFactory.getType());
}
return getFieldname(field, UseCase.Suggest, searchContext);
} else {
if (Objects.isNull(assets.getField(name))) {
log.warn("No field descriptor found for field name {} in factory: {}", name, assets.getType());
}
return getFieldname(assets.getField(name), UseCase.Suggest, searchContext);
}
}).filter(Objects::nonNull).toArray(String[]::new));
} else {
DescriptorSuggestionSearch s = (DescriptorSuggestionSearch) search;
query.setParam("suggestion.field", s.getSuggestionFields().stream().map(descriptor -> getFieldname(descriptor, UseCase.Suggest, searchContext)).filter(Objects::nonNull).toArray(String[]::new));
}
query.setParam("q", search.getInput());
// TODO: somehow this is still needed here, it should by configuration
query.setParam("suggestion.df", SUGGESTION_DF_FIELD);
query.setParam("suggestion.limit", String.valueOf(search.getLimit()));
String parentTypeFilter = "_type_:" + assets.getType();
if (Objects.nonNull(childFactory)) {
parentTypeFilter = "(" + parentTypeFilter + " OR _type_:" + childFactory.getType() + ")";
}
query.add(CommonParams.FQ, parentTypeFilter);
// filters
if (search.hasFilter()) {
SolrUtils.Query.buildFilterString(search.getFilter(), assets, childFactory, query, searchContext, false);
new SolrChildrenSerializerVisitor(assets, childFactory, searchContext, false);
}
// suggestion deep search
if (Objects.nonNull(childFactory)) {
if (search.hasFilter()) {
// TODO clean up!
final String parentFilterQuery = "(" + String.join(" AND ", query.getFilterQueries()) + ")";
final String childrenFilterQuery = search.getFilter().accept(new SolrChildrenSerializerVisitor(assets, childFactory, searchContext, false));
final String childrenBJQ = "{!child of=\"_type_:" + assets.getType() + "\" v='" + childrenFilterQuery + "'}";
query.set(CommonParams.FQ, String.join(" ", parentFilterQuery, "OR", childrenBJQ));
}
}
return query;
}
use of com.rbmhtechnology.vind.model.DocumentFactory in project vind by RBMHTechnology.
the class SolrSearchServer method getRawQuery.
@Override
public <T> String getRawQuery(FulltextSearch search, Class<T> c) {
final DocumentFactory factory = AnnotationUtil.createDocumentFactory(c);
final SolrQuery query = buildSolrQuery(search, factory);
return query.toString();
}
use of com.rbmhtechnology.vind.model.DocumentFactory in project vind by RBMHTechnology.
the class SolrSearchServer method buildSolrQuery.
protected SolrQuery buildSolrQuery(FulltextSearch search, DocumentFactory factory) {
// build query
final SolrQuery query = new SolrQuery();
final String searchContext = search.getSearchContext();
if (search.getTimeZone() != null) {
query.set(CommonParams.TZ, search.getTimeZone());
}
// fulltext search
query.set(CommonParams.Q, search.getSearchString());
if (SearchConfiguration.get(SearchConfiguration.SEARCH_RESULT_SHOW_SCORE, true)) {
query.set(CommonParams.FL, "*,score");
} else {
query.set(CommonParams.FL, "*");
}
if (search.getGeoDistance() != null) {
final FieldDescriptor descriptor = factory.getField(search.getGeoDistance().getFieldName());
if (Objects.nonNull(descriptor)) {
query.setParam(CommonParams.FL, query.get(CommonParams.FL) + "," + DISTANCE + ":geodist()");
query.setParam("pt", search.getGeoDistance().getLocation().toString());
query.setParam("sfield", getFieldname(descriptor, UseCase.Facet, searchContext));
}
}
Collection<FieldDescriptor<?>> fulltext = factory.listFields().stream().filter(FieldDescriptor::isFullText).collect(Collectors.toList());
if (!fulltext.isEmpty()) {
query.setParam(DisMaxParams.QF, SolrUtils.Query.buildQueryFieldString(fulltext, searchContext));
query.setParam("defType", "edismax");
} else {
query.setParam(CommonParams.DF, TEXT);
}
// filters
query.add(CommonParams.FQ, "_type_:" + factory.getType());
if (search.hasFilter()) {
SolrUtils.Query.buildFilterString(search.getFilter(), factory, search.getChildrenFactory(), query, searchContext, search.getStrict());
}
// fulltext search deep search
if (search.isChildrenSearchEnabled()) {
// append childCount facet
search.facet(new Facet.SubdocumentFacet(factory));
// TODO: move to SolrUtils
final String parentSearchQuery = "((" + query.get(CommonParams.Q) + ") AND " + TYPE + ":" + factory.getType() + ")";
final String childrenSearchQuery = "_query_:\"{!parent which=" + TYPE + ":" + factory.getType() + "}(" + TYPE + ":" + search.getChildrenFactory().getType() + " AND (" + search.getChildrenSearchString().getEscapedSearchString() + "))\"";
query.set(CommonParams.Q, String.join(" ", parentSearchQuery, search.getChildrenSearchOperator().name(), childrenSearchQuery));
if (search.getChildrenSearchString().hasFilter()) {
// TODO clean up!
final String parentFilterQuery = "(" + String.join(" AND ", query.getFilterQueries()) + ")";
final String childrenFilterQuery = search.getChildrenSearchString().getFilter().accept(new SolrChildrenSerializerVisitor(factory, search.getChildrenFactory(), searchContext, search.getStrict()));
query.set(CommonParams.FQ, String.join(" ", parentFilterQuery, search.getChildrenSearchOperator().name(), "(" + childrenFilterQuery + ")"));
}
}
if (search.hasFacet()) {
query.setFacet(true);
query.setFacetMinCount(search.getFacetMinCount());
query.setFacetLimit(search.getFacetLimit());
// Query facets
search.getFacets().values().stream().filter(facet -> Facet.QueryFacet.class.isAssignableFrom(facet.getClass())).map(genericFacet -> (Facet.QueryFacet) genericFacet).forEach(queryFacet -> query.addFacetQuery(StringUtils.join(SolrUtils.Query.buildSolrFacetCustomName(SolrUtils.Query.buildFilterString(queryFacet.getFilter(), factory, search.getChildrenFactory(), searchContext, search.getStrict()), queryFacet))));
// Numeric Range facet
search.getFacets().values().stream().filter(facet -> Facet.NumericRangeFacet.class.isAssignableFrom(facet.getClass())).map(genericFacet -> (Facet.NumericRangeFacet) genericFacet).forEach(numericRangeFacet -> {
final UseCase useCase = UseCase.valueOf(numericRangeFacet.getScope().name());
final String fieldName = getFieldname(numericRangeFacet.getFieldDescriptor(), useCase, searchContext);
query.add(FacetParams.FACET_RANGE, SolrUtils.Query.buildSolrFacetCustomName(fieldName, numericRangeFacet));
query.add(String.format(Locale.ROOT, "f.%s.%s", fieldName, FacetParams.FACET_RANGE_START), numericRangeFacet.getStart().toString());
query.add(String.format(Locale.ROOT, "f.%s.%s", fieldName, FacetParams.FACET_RANGE_END), numericRangeFacet.getEnd().toString());
query.add(String.format(Locale.ROOT, "f.%s.%s", fieldName, FacetParams.FACET_RANGE_GAP), numericRangeFacet.getGap().toString());
/*query.addNumericRangeFacet(
SolrUtils.Query.buildSolrFacetCustomName(fieldName, numericRangeFacet.getName()),
numericRangeFacet.getStart(),
numericRangeFacet.getEnd(),
numericRangeFacet.getGap());*/
});
// Interval Range facet
search.getFacets().values().stream().filter(facet -> Facet.IntervalFacet.class.isAssignableFrom(facet.getClass())).map(genericFacet -> (Facet.IntervalFacet) genericFacet).forEach(intervalFacet -> {
final UseCase useCase = UseCase.valueOf(intervalFacet.getScope().name());
final String fieldName = getFieldname(intervalFacet.getFieldDescriptor(), useCase, searchContext);
query.add(FacetParams.FACET_INTERVAL, SolrUtils.Query.buildSolrFacetKey(intervalFacet.getName()) + fieldName);
for (Object o : intervalFacet.getIntervals()) {
// TODO why is this necessary?
Interval i = (Interval) o;
query.add(String.format("f.%s.%s", fieldName, FacetParams.FACET_INTERVAL_SET), String.format("%s%s%s,%s%s", SolrUtils.Query.buildSolrFacetKey(i.getName()), i.includesStart() ? "[" : "(", i.getStart() == null ? SOLR_WILDCARD : SolrUtils.Query.buildSolrQueryValue(i.getStart()), i.getEnd() == null ? SOLR_WILDCARD : SolrUtils.Query.buildSolrQueryValue(i.getEnd()), i.includesEnd() ? "]" : ")"));
}
});
// Date Range facet
search.getFacets().values().stream().filter(facet -> Facet.DateRangeFacet.class.isAssignableFrom(facet.getClass())).map(genericFacet -> (Facet.DateRangeFacet) genericFacet).forEach(dateRangeFacet -> generateDateRangeQuery(dateRangeFacet, query, searchContext));
// stats
search.getFacets().values().stream().filter(facet -> Facet.StatsFacet.class.isAssignableFrom(facet.getClass())).map(genericFacet -> (Facet.StatsFacet) genericFacet).forEach(statsFacet -> {
final UseCase useCase = UseCase.valueOf(statsFacet.getScope().name());
String fieldName = getFieldname(statsFacet.getField(), useCase, searchContext);
query.add(StatsParams.STATS, "true");
query.add(StatsParams.STATS_FIELD, SolrUtils.Query.buildSolrStatsQuery(fieldName, statsFacet));
});
// pivot facet
search.getFacets().values().stream().filter(facet -> Facet.PivotFacet.class.isAssignableFrom(facet.getClass())).map(genericFacet -> (Facet.PivotFacet) genericFacet).forEach(pivotFacet -> {
String[] fieldNames = pivotFacet.getFieldDescriptors().stream().map(fieldDescriptor -> getFieldname(fieldDescriptor, UseCase.Facet, searchContext)).toArray(String[]::new);
query.add(FacetParams.FACET_PIVOT, SolrUtils.Query.buildSolrPivotSubFacetName(pivotFacet.getName(), fieldNames));
});
// facet fields
final HashMap<String, Object> strings = SolrUtils.Query.buildJsonTermFacet(search.getFacets(), search.getFacetLimit(), factory, search.getChildrenFactory(), searchContext);
query.add("json.facet", strings.toString().replaceAll("=", ":"));
// facet Subdocument count
final String subdocumentFacetString = SolrUtils.Query.buildSubdocumentFacet(search, factory, searchContext);
if (Objects.nonNull(subdocumentFacetString)) {
query.add("json.facet", subdocumentFacetString);
}
}
// sorting
if (search.hasSorting()) {
final String sortString = SolrUtils.Query.buildSortString(search, search.getSorting(), factory);
query.set(CommonParams.SORT, sortString);
}
// TODO this is a mess
if (search.hasSorting()) {
query.set(DisMaxParams.BF, SolrUtils.Query.buildBoostFunction(search.getSorting(), searchContext));
}
// paging
switch(search.getResultSet().getType()) {
case page:
{
final Page resultSet = (Page) search.getResultSet();
query.setStart(resultSet.getOffset());
query.setRows(resultSet.getPagesize());
break;
}
case slice:
{
final Slice resultSet = (Slice) search.getResultSet();
query.setStart(resultSet.getOffset());
query.setRows(resultSet.getSliceSize());
break;
}
}
return query;
}
use of com.rbmhtechnology.vind.model.DocumentFactory in project vind by RBMHTechnology.
the class IntervalFacetsTest method testQueryBuilder.
@Test
public void testQueryBuilder() {
SolrClient client = Mockito.mock(SolrClient.class);
SolrSearchServer server = new SolrSearchServer(client, false);
FieldDescriptor<Integer> descriptor = Mockito.mock(FieldDescriptor.class);
when(descriptor.getType()).thenReturn(Integer.class);
when(descriptor.isFacet()).thenReturn(true);
DocumentFactory factory = Mockito.mock(DocumentFactory.class);
FulltextSearch search = Search.fulltext().facet(interval("quality", descriptor, Interval.numericInterval("low", 0, 2, true, false), Interval.numericInterval("high", 3, 4)));
SolrQuery query = server.buildSolrQuery(search, factory);
assertEquals("{!key=quality}dynamic_single_facet_int_null", query.get("facet.interval"));
// assertThat(Arrays.asList(query.getParams("f.dynamic_single_int_null.facet.interval.set")), contains("{!key=low}[0,2)", "{!key=high}[3,4]")); TODO fix hamcrest dependency
}
use of com.rbmhtechnology.vind.model.DocumentFactory in project vind by RBMHTechnology.
the class SolrSearchServerTest method testExecute.
@Test
public void testExecute() throws Exception {
Asset asset = new Asset();
// FIXME: Asset has no @Id field
server.indexBean(asset);
// query
BeanSearchResult<Asset> result = server.execute(Search.fulltext("hello world").filter(eq("category", "test")), Asset.class);
// suggestion
SuggestionResult suggestions = server.execute(Search.suggest("he").fields("category"), Asset.class);
FieldDescriptor<String> title = new FieldDescriptorBuilder().setBoost(2).setLanguage(Language.German).buildTextField("title");
// complex
DocumentFactory factory = new DocumentFactoryBuilder("asset").addField(title).build();
Document document = factory.createDoc("1234");
server.index(document);
// suggestion
SuggestionResult suggestionsFromFactory = server.execute(Search.suggest("he").fields("title"), factory);
}
Aggregations