/** * Process a query string to search using Solr. * * @param request * @param query * @param asAnon * @param rs * @return * @throws SolrSearchException */ private SolrSearchResultSet processSolrQuery( SlingHttpServletRequest request, Query query, boolean asAnon) throws StorageClientException, AccessDeniedException, SolrServerException { String queryString = query.getQueryString(); // apply readers restrictions. if (asAnon) { queryString = "(" + queryString + ") AND readers:" + User.ANON_USER; } else { Session session = StorageClientUtils.adaptToSession( request.getResourceResolver().adaptTo(javax.jcr.Session.class)); if (!User.ADMIN_USER.equals(session.getUserId())) { AuthorizableManager am = session.getAuthorizableManager(); Authorizable user = am.findAuthorizable(session.getUserId()); Set<String> readers = Sets.newHashSet(); for (Iterator<Group> gi = user.memberOf(am); gi.hasNext(); ) { readers.add(gi.next().getId()); } readers.add(session.getUserId()); queryString = "(" + queryString + ") AND readers:(" + StringUtils.join(readers, " OR ") + ")"; } } SolrQuery solrQuery = buildQuery(request, queryString, query.getOptions()); SolrServer solrServer = solrSearchService.getServer(); try { LOGGER.info("Performing Query {} ", URLDecoder.decode(solrQuery.toString(), "UTF-8")); } catch (UnsupportedEncodingException e) { } QueryResponse response = solrServer.query(solrQuery); SolrDocumentList resultList = response.getResults(); LOGGER.info("Got {} hits in {} ms", resultList.size(), response.getElapsedTime()); return new SolrSearchResultSetImpl(response); }
public SolrSearchResultSet getSearchResultSet( SlingHttpServletRequest request, Query query, boolean asAnon) throws SolrSearchException { try { SolrSearchResultSet rs = null; if (query.getType() == Type.SOLR) { rs = processSolrQuery(request, query, asAnon); } else if (query.getType() == Type.SPARSE) { rs = processSparseQuery(request, query, asAnon); } return rs; } catch (SolrServerException e) { LOGGER.warn(e.getMessage(), e); throw new SolrSearchException(500, e.getMessage()); } catch (ParseException e) { LOGGER.warn(e.getMessage(), e); throw new SolrSearchException(500, e.getMessage()); } catch (StorageClientException e) { LOGGER.warn(e.getMessage(), e); throw new SolrSearchException(500, e.getMessage()); } catch (AccessDeniedException e) { LOGGER.warn(e.getMessage(), e); throw new SolrSearchException(403, e.getMessage()); } }
/** * Process properties to query sparse content directly. * * @param request * @param query * @param asAnon * @return * @throws StorageClientException * @throws AccessDeniedException */ private SolrSearchResultSet processSparseQuery( SlingHttpServletRequest request, Query query, boolean asAnon) throws StorageClientException, AccessDeniedException, ParseException { // use solr parsing to get the terms from the query string QueryParser parser = new QueryParser(Version.LUCENE_40, "id", new TextField().getQueryAnalyzer()); org.apache.lucene.search.Query luceneQuery = parser.parse(query.getQueryString()); Set<Term> terms = Sets.newHashSet(); luceneQuery.extractTerms(terms); Map<String, Object> props = Maps.newHashMap(); for (Term term : terms) { props.put(term.field(), term.text()); } Session session = StorageClientUtils.adaptToSession( request.getResourceResolver().adaptTo(javax.jcr.Session.class)); ContentManager cm = session.getContentManager(); Iterable<Content> items = cm.find(props); SolrSearchResultSet rs = new SparseSearchResultSet(items); return rs; }
@Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { try { Resource resource = request.getResource(); if (!resource.getPath().startsWith(SEARCH_PATH_PREFIX)) { response.sendError( HttpServletResponse.SC_FORBIDDEN, "Search templates can only be executed if they are located under " + SEARCH_PATH_PREFIX); return; } Node node = resource.adaptTo(Node.class); if (node != null && node.hasProperty(SAKAI_QUERY_TEMPLATE)) { // TODO: we might want to use this ? @SuppressWarnings("unused") boolean limitResults = true; if (node.hasProperty(SAKAI_LIMIT_RESULTS)) { limitResults = node.getProperty(SAKAI_LIMIT_RESULTS).getBoolean(); } // KERN-1147 Respond better when all parameters haven't been provided for a query Query query = null; try { query = processQuery(request, node); } catch (MissingParameterException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); return; } long nitems = SolrSearchUtil.longRequestParameter( request, PARAMS_ITEMS_PER_PAGE, DEFAULT_PAGED_ITEMS); long page = SolrSearchUtil.longRequestParameter(request, PARAMS_PAGE, 0); // allow number of items to be specified in sakai:query-template-options if (query.getOptions().containsKey(PARAMS_ITEMS_PER_PAGE)) { nitems = Long.valueOf(query.getOptions().get(PARAMS_ITEMS_PER_PAGE)); } else { // add this to the options so that all queries are constrained to a limited // number of returns per page. query.getOptions().put(PARAMS_ITEMS_PER_PAGE, Long.toString(nitems)); } if (query.getOptions().containsKey(PARAMS_PAGE)) { page = Long.valueOf(query.getOptions().get(PARAMS_PAGE)); } else { // add this to the options so that all queries are constrained to a limited // number of returns per page. query.getOptions().put(PARAMS_PAGE, Long.toString(page)); } boolean useBatch = false; // Get the SolrSearchBatchResultProcessor searchBatchProcessor = defaultSearchBatchProcessor; if (node.hasProperty(SAKAI_BATCHRESULTPROCESSOR)) { searchBatchProcessor = batchProcessors.get(node.getProperty(SAKAI_BATCHRESULTPROCESSOR).getString()); useBatch = true; if (searchBatchProcessor == null) { searchBatchProcessor = defaultSearchBatchProcessor; } } SolrSearchResultProcessor searchProcessor = defaultSearchProcessor; if (node.hasProperty(SAKAI_RESULTPROCESSOR)) { searchProcessor = processors.get(node.getProperty(SAKAI_RESULTPROCESSOR).getString()); if (searchProcessor == null) { searchProcessor = defaultSearchProcessor; } } SolrSearchResultSet rs = null; try { // Prepare the result set. // This allows a processor to do other queries and manipulate the results. if (useBatch) { rs = searchBatchProcessor.getSearchResultSet(request, query); } else { rs = searchProcessor.getSearchResultSet(request, query); } } catch (SolrSearchException e) { response.sendError(e.getCode(), e.getMessage()); return; } response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); ExtendedJSONWriter write = new ExtendedJSONWriter(response.getWriter()); write.setTidy(isTidy(request)); write.object(); write.key(PARAMS_ITEMS_PER_PAGE); write.value(nitems); write.key(JSON_RESULTS); write.array(); Iterator<Result> iterator = rs.getResultSetIterator(); if (useBatch) { LOGGER.info("Using batch processor for results"); searchBatchProcessor.writeResults(request, write, iterator); } else { LOGGER.info("Using regular processor for results"); // We don't skip any rows ourselves here. // We expect a rowIterator coming from a resultset to be at the right place. for (long i = 0; i < nitems && iterator.hasNext(); i++) { // Get the next row. Result result = iterator.next(); // Write the result for this row. searchProcessor.writeResult(request, write, result); } } write.endArray(); // write the total out after processing the list to give the underlying iterator // a chance to walk the results then report how many there were. write.key(TOTAL); write.value(rs.getSize()); write.endObject(); } } catch (RepositoryException e) { LOGGER.error(e.getMessage(), e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } catch (JSONException e) { LOGGER.error(e.getMessage(), e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } }
/** * Process properties to query sparse content directly. * * @param request * @param query * @param asAnon * @return * @throws StorageClientException * @throws AccessDeniedException */ public SolrSearchResultSet processQuery( SlingHttpServletRequest request, Query query, boolean asAnon) throws SolrSearchException { try { // use solr parsing to get the terms from the query string QueryParser parser = new QueryParser(Version.LUCENE_40, "id", new TextField().getQueryAnalyzer()); org.apache.lucene.search.Query luceneQuery = parser.parse(query.getQueryString()); Map<String, Object> props = Maps.newHashMap(); if (luceneQuery instanceof BooleanQuery) { BooleanQuery boolLucQuery = (BooleanQuery) luceneQuery; int orCount = 0; List<BooleanClause> clauses = boolLucQuery.clauses(); for (BooleanClause clause : clauses) { org.apache.lucene.search.Query clauseQuery = clause.getQuery(); Map<String, Object> subOrs = Maps.newHashMap(); // we support 1 level of nesting for OR clauses if (clauseQuery instanceof BooleanQuery) { for (BooleanClause subclause : ((BooleanQuery) clauseQuery).clauses()) { org.apache.lucene.search.Query subclauseQuery = subclause.getQuery(); extractTerms(subclause, subclauseQuery, props, subOrs); } props.put("orset" + orCount, subOrs); orCount++; } else { extractTerms(clause, clauseQuery, props, subOrs); if (!subOrs.isEmpty()) { props.put("orset" + orCount, subOrs); orCount++; } } } } else { extractTerms(null, luceneQuery, props, null); } // add the options to the parameters but prepend _ to avoid collision for (Entry<String, String> option : query.getOptions().entrySet()) { props.put("_" + option.getKey(), option.getValue()); } Session session = StorageClientUtils.adaptToSession( request.getResourceResolver().adaptTo(javax.jcr.Session.class)); ContentManager cm = session.getContentManager(); long tquery = System.currentTimeMillis(); Iterable<Content> items = cm.find(props); tquery = System.currentTimeMillis() - tquery; try { if (tquery > verySlowQueryThreshold) { SLOW_QUERY_LOGGER.error( "Very slow sparse query {} ms {} ", tquery, URLDecoder.decode(query.toString(), "UTF-8")); } else if (tquery > slowQueryThreshold) { SLOW_QUERY_LOGGER.warn( "Slow sparse query {} ms {} ", tquery, URLDecoder.decode(query.toString(), "UTF-8")); } } catch (UnsupportedEncodingException e) { // quietly swallow this exception LOGGER.debug(e.getLocalizedMessage(), e); } SolrSearchResultSet rs = new SparseSearchResultSet(items, defaultMaxResults); return rs; } catch (AccessDeniedException e) { throw new SolrSearchException(500, e.getMessage()); } catch (StorageClientException e) { throw new SolrSearchException(500, e.getMessage()); } catch (ParseException e) { throw new SolrSearchException(500, e.getMessage()); } }