📄 cmssearchindex.java
字号:
}
// add the calculated phrase query for the root path
query.add(pathQuery, BooleanClause.Occur.MUST);
if ((params.getCategories() != null) && (params.getCategories().size() > 0)) {
// add query categories (if required)
BooleanQuery categoryQuery = new BooleanQuery();
for (int i = 0; i < params.getCategories().size(); i++) {
Term term = new Term(I_CmsDocumentFactory.DOC_CATEGORY, (String)params.getCategories().get(i));
TermQuery termQuery = new TermQuery(term);
categoryQuery.add(termQuery, BooleanClause.Occur.SHOULD);
}
query.add(categoryQuery, BooleanClause.Occur.MUST);
}
if ((params.getFields() != null) && (params.getFields().size() > 0)) {
// this is a "regular" query over one or more fields
BooleanQuery fieldsQuery = new BooleanQuery();
// add one sub-query for each of the selected fields, e.g. "content", "title" etc.
for (int i = 0; i < params.getFields().size(); i++) {
QueryParser p = new QueryParser((String)params.getFields().get(i), languageAnalyzer);
fieldsQuery.add(p.parse(params.getQuery()), BooleanClause.Occur.SHOULD);
}
// finally add the field queries to the main query
query.add(fieldsQuery, BooleanClause.Occur.MUST);
} else {
// if no fields are provided, just use the "content" field by default
QueryParser p = new QueryParser(I_CmsDocumentFactory.DOC_CONTENT, languageAnalyzer);
query.add(p.parse(params.getQuery()), BooleanClause.Occur.MUST);
}
// create the index searcher
searcher = new IndexSearcher(m_path);
Query finalQuery;
if (m_createExcerpt || LOG.isDebugEnabled()) {
// we re-write the query because this enables highlighting of wildcard terms in excerpts
finalQuery = searcher.rewrite(query);
} else {
finalQuery = query;
}
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_BASE_QUERY_1, query));
LOG.debug(Messages.get().getBundle().key(Messages.LOG_REWRITTEN_QUERY_1, finalQuery));
}
// collect the categories
CmsSearchCategoryCollector categoryCollector;
if (params.isCalculateCategories()) {
// USE THIS OPTION WITH CAUTION
// this may slow down searched by an order of magnitude
categoryCollector = new CmsSearchCategoryCollector(searcher);
// perform a first search to collect the categories
searcher.search(finalQuery, categoryCollector);
// store the result
searchResults.setCategories(categoryCollector.getCategoryCountResult());
}
// perform the search operation
hits = searcher.search(finalQuery, params.getSort());
int hitCount = hits.length();
timeLucene += System.currentTimeMillis();
timeResultProcessing = -System.currentTimeMillis();
Document doc;
CmsSearchResult searchResult;
String excerpt = null;
if (hits != null) {
int page = params.getSearchPage();
int start = -1, end = -1;
if (matchesPerPage > 0 && page > 0 && hitCount > 0) {
// calculate the final size of the search result
start = matchesPerPage * (page - 1);
end = start + matchesPerPage;
// ensure that both i and n are inside the range of foundDocuments.size()
start = (start > hitCount) ? hitCount : start;
end = (end > hitCount) ? hitCount : end;
} else {
// return all found documents in the search result
start = 0;
end = hitCount;
}
int visibleHitCount = hitCount;
for (int i = 0, cnt = 0; i < hitCount && cnt < end; i++) {
try {
doc = hits.doc(i);
if (hasReadPermission(cms, doc)) {
// user has read permission
if (cnt >= start) {
// do not use the resource to obtain the raw content, read it from the lucene document !
// documents must not have content (i.e. images), so check if the content field exists
if (m_createExcerpt && doc.getField(I_CmsDocumentFactory.DOC_CONTENT) != null) {
excerpt = getExcerpt(
doc.getField(I_CmsDocumentFactory.DOC_CONTENT).stringValue(),
finalQuery,
languageAnalyzer);
}
searchResult = new CmsSearchResult(Math.round(hits.score(i) * 100f), doc, excerpt);
searchResults.add(searchResult);
}
cnt++;
} else {
visibleHitCount--;
}
} catch (Exception e) {
// should not happen, but if it does we want to go on with the next result nevertheless
if (LOG.isWarnEnabled()) {
LOG.warn(Messages.get().getBundle().key(Messages.LOG_RESULT_ITERATION_FAILED_0), e);
}
}
}
// save the total count of search results at the last index of the search result
searchResults.setHitCount(visibleHitCount);
} else {
searchResults.setHitCount(0);
}
timeResultProcessing += System.currentTimeMillis();
} catch (Exception exc) {
throw new CmsSearchException(Messages.get().container(Messages.ERR_SEARCH_PARAMS_1, params), exc);
} finally {
// re-set thread to previous priority
Thread.currentThread().setPriority(previousPriority);
if (searcher != null) {
try {
searcher.close();
} catch (IOException exc) {
// noop
}
}
// switch back to the original project
context.setCurrentProject(currentProject);
}
timeTotal += System.currentTimeMillis();
Object[] logParams = new Object[] {
new Integer(hits.length()),
new Long(timeTotal),
new Long(timeLucene),
new Long(timeResultProcessing)};
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_STAT_RESULTS_TIME_4, logParams));
}
return searchResults;
}
/**
* Can be used to enable / disable this index.<p>
*
* @param enabled the state of the index to set
*/
public void setEnabled(boolean enabled) {
m_enabled = enabled;
}
/**
* Sets the locale to index resources.<p>
*
* @param locale the locale to index resources
*/
public void setLocale(String locale) {
m_locale = locale;
}
/**
* Sets the logical key/name of this search index.<p>
*
* @param name the logical key/name of this search index
*
* @throws org.opencms.main.CmsIllegalArgumentException
* if the given name is null, empty or already taken
* by another search index.
*/
public void setName(String name) throws CmsIllegalArgumentException {
if (CmsStringUtil.isEmptyOrWhitespaceOnly(name)) {
throw new CmsIllegalArgumentException(Messages.get().container(
Messages.ERR_SEARCHINDEX_CREATE_MISSING_NAME_0));
} else {
// check if already used, but only if the name was modified:
// this is important as unmodifiable DisplayWidgets will also invoke this...
if (!name.equals(m_name)) {
// don't mess with xml-configuration
if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) {
// Not needed at startup and additionally getSearchManager may return null
Iterator itIdxNames = OpenCms.getSearchManager().getIndexNames().iterator();
while (itIdxNames.hasNext()) {
if (itIdxNames.next().equals(name)) {
throw new CmsIllegalArgumentException(Messages.get().container(
Messages.ERR_SEARCHINDEX_CREATE_INVALID_NAME_1,
name));
}
}
}
}
}
m_name = name;
}
/**
* Sets the name of the project used to index resources.<p>
*
* A duplicate method of <code>{@link #setProjectName(String)}</code> that allows
* to use instances of this class as a widget object (bean convention,
* cp.: <code>{@link #getProject()}</code>.<p>
*
* @param projectName the name of the project used to index resources
*/
public void setProject(String projectName) {
setProjectName(projectName);
}
/**
* Sets the name of the project used to index resources.<p>
*
* @param projectName the name of the project used to index resources
*/
public void setProjectName(String projectName) {
m_project = projectName;
}
/**
* Sets the rebuild mode of this search index.<p>
*
* @param rebuildMode the rebuild mode of this search index {auto|manual}
*/
public void setRebuildMode(String rebuildMode) {
m_rebuild = rebuildMode;
}
/**
* Returns the name (<code>{@link #getName()}</code>) of this search index.<p>
*
* @return the name (<code>{@link #getName()}</code>) of this search index
*
* @see java.lang.Object#toString()
*/
public String toString() {
return getName();
}
/**
* Returns an excerpt of the given content related to the given search query.<p>
*
* @param content the content
* @param searchQuery the search query
* @param analyzer the analyzer used
*
* @return an excerpt of the content
*
* @throws IOException if something goes wrong
*/
protected String getExcerpt(String content, Query searchQuery, Analyzer analyzer) throws IOException {
if (content == null) {
return null;
}
CmsHighlightFinder highlighter = new CmsHighlightFinder(
OpenCms.getSearchManager().getHighlighter(),
searchQuery,
analyzer);
String excerpt = highlighter.getBestFragments(
content,
EXCERPT_FRAGMENT_SIZE,
EXCERPT_REQUIRED_FRAGMENTS,
EXCERPT_FRAGMENT_SEPARATOR);
// kill all unwanted chars in the excerpt
excerpt = excerpt.replace('\t', ' ');
excerpt = excerpt.replace('\n', ' ');
excerpt = excerpt.replace('\r', ' ');
excerpt = excerpt.replace('\f', ' ');
int maxLength = OpenCms.getSearchManager().getMaxExcerptLength();
if (excerpt != null && excerpt.length() > maxLength) {
excerpt = excerpt.substring(0, maxLength);
}
return excerpt;
}
/**
* Checks if the OpenCms resource referenced by the result document can be read
* be the user of the given OpenCms context.<p>
*
* @param cms the OpenCms user context to use for permission testing
* @param doc the search result document to check
* @return <code>true</code> if the user has read permissions to the resource
*/
protected boolean hasReadPermission(CmsObject cms, Document doc) {
if (m_dontCheckPermissions) {
// no permission check is performed at all
return true;
}
Field typeField = doc.getField(I_CmsDocumentFactory.DOC_TYPE);
Field pathField = doc.getField(I_CmsDocumentFactory.DOC_PATH);
if ((typeField == null) || (pathField == null)) {
// permission check needs only to be performed for VFS documents that contain both fields
return true;
}
String rootPath = cms.getRequestContext().removeSiteRoot(pathField.stringValue());
// check if the resource "exits", this will implicitly check read permission and if the resource was deleted
return cms.existsResource(rootPath);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -