searchindex.java
来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 1,046 行 · 第 1/3 页
JAVA
1,046 行
* @throws RepositoryException if an error occurs while indexing a node. * @throws IOException if an error occurs while updating the index. */ public void updateNodes(NodeIdIterator remove, NodeStateIterator add) throws RepositoryException, IOException { checkOpen(); index.update(new AbstractIteratorDecorator(remove) { public Object next() { return ((NodeId) super.next()).getUUID(); } }, new AbstractIteratorDecorator(add) { public Object next() { NodeState state = (NodeState) super.next(); if (state == null) { return null; } Document doc = null; try { doc = createDocument(state, getNamespaceMappings()); } catch (RepositoryException e) { log.warn("Exception while creating document for node: " + state.getNodeId() + ": " + e.toString()); } return doc; } }); } /** * Creates a new query by specifying the query statement itself and the * language in which the query is stated. If the query statement is * syntactically invalid, given the language specified, an * InvalidQueryException is thrown. <code>language</code> must specify a query language * string from among those returned by QueryManager.getSupportedQueryLanguages(); if it is not * then an <code>InvalidQueryException</code> is thrown. * * @param session the session of the current user creating the query object. * @param itemMgr the item manager of the current user. * @param statement the query statement. * @param language the syntax of the query statement. * @throws InvalidQueryException if statement is invalid or language is unsupported. * @return A <code>Query</code> object. */ public ExecutableQuery createExecutableQuery(SessionImpl session, ItemManager itemMgr, String statement, String language) throws InvalidQueryException { QueryImpl query = new QueryImpl(session, itemMgr, this, getContext().getPropertyTypeRegistry(), statement, language); query.setRespectDocumentOrder(documentOrder); return query; } /** * Closes this <code>QueryHandler</code> and frees resources attached * to this handler. */ public void close() { // shutdown extractor if (extractor instanceof PooledTextExtractor) { ((PooledTextExtractor) extractor).shutdown(); } index.close(); getContext().destroy(); closed = true; log.info("Index closed: " + path); } /** * Executes the query on the search index. * @param queryImpl the query impl. * @param query the lucene query. * @param orderProps name of the properties for sort order. * @param orderSpecs the order specs for the sort order properties. * <code>true</code> indicates ascending order, <code>false</code> indicates * descending. * @return the lucene Hits object. * @throws IOException if an error occurs while searching the index. */ public QueryHits executeQuery(QueryImpl queryImpl, Query query, QName[] orderProps, boolean[] orderSpecs) throws IOException { checkOpen(); SortField[] sortFields = createSortFields(orderProps, orderSpecs); IndexReader reader = getIndexReader(); IndexSearcher searcher = new IndexSearcher(reader); Hits hits; if (sortFields.length > 0) { hits = searcher.search(query, new Sort(sortFields)); } else { hits = searcher.search(query); } return new QueryHits(hits, reader); } /** * Creates an excerpt provider for the given <code>query</code>. * * @param query the query. * @return an excerpt provider for the given <code>query</code>. * @throws IOException if the provider cannot be created. */ public ExcerptProvider createExcerptProvider(Query query) throws IOException { ExcerptProvider ep; try { ep = (ExcerptProvider) excerptProviderClass.newInstance(); } catch (Exception e) { IOException ex = new IOException(); ex.initCause(e); throw ex; } ep.init(query, this); return ep; } /** * Returns the analyzer in use for indexing. * @return the analyzer in use for indexing. */ public Analyzer getTextAnalyzer() { return analyzer; } /** * Returns the text extractor in use for indexing. * * @return the text extractor in use for indexing. */ public TextExtractor getTextExtractor() { return extractor; } /** * Returns the namespace mappings for the internal representation. * @return the namespace mappings for the internal representation. */ public NamespaceMappings getNamespaceMappings() { return index.getNamespaceMappings(); } /** * Returns an index reader for this search index. The caller of this method * is responsible for closing the index reader when he is finished using * it. * * @return an index reader for this search index. * @throws IOException the index reader cannot be obtained. */ public IndexReader getIndexReader() throws IOException { QueryHandler parentHandler = getContext().getParentHandler(); IndexReader parentReader = null; if (parentHandler instanceof SearchIndex) { parentReader = ((SearchIndex) parentHandler).index.getIndexReader(); } IndexReader reader = index.getIndexReader(); if (parentReader != null) { // todo FIXME not type safe CachingMultiReader[] readers = {(CachingMultiReader) reader, (CachingMultiReader) parentReader}; reader = new CombinedIndexReader(readers); } return reader; } /** * Creates the SortFields for the order properties. * * @param orderProps the order properties. * @param orderSpecs the order specs for the properties. * @return an array of sort fields */ protected SortField[] createSortFields(QName[] orderProps, boolean[] orderSpecs) { List sortFields = new ArrayList(); for (int i = 0; i < orderProps.length; i++) { String prop = null; if (QName.JCR_SCORE.equals(orderProps[i])) { // order on jcr:score does not use the natural order as // implemented in lucene. score ascending in lucene means that // higher scores are first. JCR specs that lower score values // are first. sortFields.add(new SortField(null, SortField.SCORE, orderSpecs[i])); } else { try { prop = NameFormat.format(orderProps[i], getNamespaceMappings()); } catch (NoPrefixDeclaredException e) { // will never happen } sortFields.add(new SortField(prop, SharedFieldSortComparator.PROPERTIES, !orderSpecs[i])); } } return (SortField[]) sortFields.toArray(new SortField[sortFields.size()]); } /** * Creates a lucene <code>Document</code> for a node state using the * namespace mappings <code>nsMappings</code>. * * @param node the node state to index. * @param nsMappings the namespace mappings of the search index. * @return a lucene <code>Document</code> that contains all properties of * <code>node</code>. * @throws RepositoryException if an error occurs while indexing the * <code>node</code>. */ protected Document createDocument(NodeState node, NamespaceMappings nsMappings) throws RepositoryException { NodeIndexer indexer = new NodeIndexer(node, getContext().getItemStateManager(), nsMappings, extractor); indexer.setSupportHighlighting(supportHighlighting); return indexer.createDoc(); } /** * Returns the actual index. * * @return the actual index. */ protected MultiIndex getIndex() { return index; } /** * Factory method to create the <code>TextExtractor</code> instance. * * @return the <code>TextExtractor</code> instance this index should use. */ protected TextExtractor createTextExtractor() { TextExtractor txtExtr = new JackrabbitTextExtractor(textFilterClasses); if (extractorPoolSize > 0) { // wrap with pool txtExtr = new PooledTextExtractor(txtExtr, extractorPoolSize, extractorBackLog, extractorTimeout); } return txtExtr; } //----------------------------< internal >---------------------------------- /** * Combines multiple {@link CachingMultiReader} into a <code>MultiReader</code> * with {@link HierarchyResolver} support. */ protected static final class CombinedIndexReader extends MultiReader implements HierarchyResolver, MultiIndexReader { /** * The sub readers. */ final private CachingMultiReader[] subReaders; /** * Doc number starts for each sub reader */ private int[] starts; public CombinedIndexReader(CachingMultiReader[] indexReaders) throws IOException { super(indexReaders); this.subReaders = indexReaders; this.starts = new int[subReaders.length + 1]; int maxDoc = 0; for (int i = 0; i < subReaders.length; i++) { starts[i] = maxDoc; maxDoc += subReaders[i].maxDoc(); } starts[subReaders.length] = maxDoc; } /** * @inheritDoc */ public int getParent(int n) throws IOException { int i = readerIndex(n); DocId id = subReaders[i].getParentDocId(n - starts[i]); id = id.applyOffset(starts[i]); return id.getDocumentNumber(this); } //-------------------------< MultiIndexReader >------------------------- /** * {@inheritDoc} */ public IndexReader[] getIndexReaders() { IndexReader readers[] = new IndexReader[subReaders.length]; System.arraycopy(subReaders, 0, readers, 0, subReaders.length); return readers; } //---------------------------< internal >------------------------------- /** * Returns the reader index for document <code>n</code>. * Implementation copied from lucene MultiReader class. * * @param n document number. * @return the reader index. */ private int readerIndex(int n) { int lo = 0; // search starts array int hi = subReaders.length - 1; // for first element less while (hi >= lo) { int mid = (lo + hi) >> 1; int midValue = starts[mid]; if (n < midValue) { hi = mid - 1; } else if (n > midValue) { lo = mid + 1; } else { // found a match while (mid + 1 < subReaders.length && starts[mid + 1] == midValue) { mid++; // scan to last match } return mid; } } return hi; } public boolean equals(Object obj) { if (obj instanceof CombinedIndexReader) { CombinedIndexReader other = (CombinedIndexReader) obj; return Arrays.equals(subReaders, other.subReaders); } return false; } public int hashCode() { int hash = 0; for (int i = 0; i < subReaders.length; i++) { hash = 31 * hash + subReaders[i].hashCode(); } return hash; } } //--------------------------< properties >---------------------------------- /** * Sets the analyzer in use for indexing. The given analyzer class name * must satisfy the following conditions:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?