/**
   * 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;
  }
示例#4
0
  @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());
    }
  }