📄 storagequery.java
字号:
/** * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.lucene.gdata.storage.lucenestorage;import java.io.IOException;import java.io.Reader;import java.io.StringReader;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.lucene.document.Document;import org.apache.lucene.gdata.data.GDataAccount;import org.apache.lucene.gdata.server.GDataEntityBuilder;import org.apache.lucene.gdata.server.registry.ProvidedService;import org.apache.lucene.gdata.storage.StorageException;import org.apache.lucene.gdata.utils.ModifiedEntryFilter;import org.apache.lucene.index.Term;import org.apache.lucene.search.BooleanClause;import org.apache.lucene.search.BooleanQuery;import org.apache.lucene.search.Hit;import org.apache.lucene.search.Hits;import org.apache.lucene.search.Searcher;import org.apache.lucene.search.Sort;import org.apache.lucene.search.SortField;import org.apache.lucene.search.TermQuery;import org.apache.lucene.search.BooleanClause.Occur;import com.google.gdata.data.BaseEntry;import com.google.gdata.data.BaseFeed;import com.google.gdata.data.DateTime;import com.google.gdata.util.ParseException;/** * StorageQuery wraps a Lucene {@link org.apache.lucene.search.IndexSearcher} * and a {@link org.apache.lucene.gdata.storage.lucenestorage.StorageBuffer} to * perform all request on the lucene storage. The wrapped components are thread - * safe. * <p> * An instance of this class will serve all client requests. To obtain the * current instance of the {@link StorageQuery} the method * {@link org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController#getStorageQuery()} * has to be invoked. This method will release the current StorageQuery. * </p> * * @see org.apache.lucene.search.IndexSearcher * @see org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController * @see org.apache.lucene.gdata.storage.lucenestorage.StorageBuffer * * @author Simon Willnauer * */public class StorageQuery { private static final Log LOG = LogFactory.getLog(StorageQuery.class); private final StorageBuffer buffer; private final Searcher searcher; /* * Sort the result by timestamp desc */ private final Sort timeStampSort = new Sort(new SortField( StorageEntryWrapper.FIELD_TIMESTAMP, SortField.STRING, true)); /** * Creates a new StorageQuery * * @param buffer - * the buffer instance to get the buffered inserts, updates from. * @param searcher - * the searcher instance to use to query the storage index. * * */ protected StorageQuery(final StorageBuffer buffer, final Searcher searcher) { this.buffer = buffer; this.searcher = searcher; } private Hits storageQuery(List<String> entryId) throws IOException { BooleanQuery query = new BooleanQuery(); /* * query the index using a BooleanQuery */ for (String id : entryId) { TermQuery termQuery = new TermQuery(new Term( StorageEntryWrapper.FIELD_ENTRY_ID, id)); // use an OR query query.add(new BooleanClause(termQuery, Occur.SHOULD)); } return this.searcher.search(query, new ModifiedEntryFilter(this.buffer .getExculdList(),StorageEntryWrapper.FIELD_ENTRY_ID)); } /* * query the storage index for a entire feed. */ private Hits storageFeedQuery(final String feedId, final Sort sort) throws IOException { TermQuery query = new TermQuery(new Term( StorageEntryWrapper.FIELD_FEED_REFERENCE, feedId)); return this.searcher.search(query, new ModifiedEntryFilter(this.buffer .getExculdList(),StorageEntryWrapper.FIELD_ENTRY_ID), sort); } /* * get a single entry */ private Hits storageQuery(String entryId) throws IOException { TermQuery termQuery = new TermQuery(new Term( StorageEntryWrapper.FIELD_ENTRY_ID, entryId)); /* * Filter entries inside the buffer, buffered entries might contain * deleted entries. These entries must be found!! */ return this.searcher.search(termQuery, new ModifiedEntryFilter( this.buffer.getExculdList(),StorageEntryWrapper.FIELD_ENTRY_ID)); } /** * This method fetches the latest feed entries from the storage. Feed * usually requested via a search query or as a simple query to the REST * interface. * <p> * The REST interface requests all the entries from a Storage. The Storage * retrieves the entries corresponding to the parameters specified. This * method first requests the latest entries or updated entries from the * {@link StorageBuffer}. If the buffer already contains enough entries * for the the specified result count the entries will be returned. If not, * the underlying lucene index will be searcher for all documents of the * specified feed sorted by storing timestamp desc. * </p> * <p> * The entries will be searched in a feed context specified by the given * feed ID * </p> * * * @param feedId - * the requested feed, this id will be used to retrieve the * entries. * @param resultCount - * how many entries are requested * @param startIndex - * the offset of the entry to start from. * @param config - * the FeedInstanceConfiguration containing extension profile used * to create the entry instances * @return - an ordered list of {@link BaseEntry} objects, or an empty list * if no entries could be found * @throws IOException - * if the index could not be queries or the entries could not be * build * @throws ParseException - * if an entry could not be parsed while building it from the * Lucene Document. */ // TODO check input parameter @SuppressWarnings("unchecked") public BaseFeed getLatestFeedQuery(final String feedId, final int resultCount, final int startIndex, final ProvidedService config) throws IOException, ParseException { DateTime updated = null; Hits feedHits = storageFeedQuery(feedId); if (feedHits.length() == 0) return null; BaseFeed retVal = buildFeedFromLuceneDocument(feedHits.doc(0), config); List<BaseEntry> returnList = new ArrayList<BaseEntry>(resultCount); List<StorageEntryWrapper> bufferedWrapperList = this.buffer .getSortedEntries(feedId); int alreadyAdded = 0; int offset = startIndex - 1; if (bufferedWrapperList != null && bufferedWrapperList.size() >= startIndex) { updated = bufferedWrapperList.get(0).getEntry().getUpdated(); for (; alreadyAdded < resultCount; alreadyAdded++) { if ((bufferedWrapperList.size() - offset) > 0) { StorageEntryWrapper wrappedEntry = bufferedWrapperList .get(offset++); returnList.add(wrappedEntry.getEntry()); } else break; } // reset offset offset = startIndex - 1; if (alreadyAdded == resultCount) { retVal.getEntries().addAll(returnList); retVal.setUpdated(updated); return retVal; } } else { /* * if the buffer size is less than the start index the buffer size must * be considered. Sublists would not be a repeatable read part of * the whole list */ if (bufferedWrapperList != null) offset = startIndex - 1 - bufferedWrapperList.size(); } Hits hits = storageFeedQuery(feedId, this.timeStampSort); if (hits.length() > 0) { for (; (offset < hits.length()) && (alreadyAdded < resultCount); offset++, alreadyAdded++) { Document doc = hits.doc(offset); BaseEntry entry = buildEntryFromLuceneDocument(doc, config); returnList.add(entry); } if (updated == null) { try { long updatedTimeStamp = Long.parseLong(hits.doc(0).get( StorageEntryWrapper.FIELD_TIMESTAMP)); updated = new DateTime(updatedTimeStamp); } catch (Exception e) { LOG.warn("could not create DateTime -- " + e.getMessage(), e); updated = buildEntryFromLuceneDocument(hits.doc(0), config) .getUpdated(); } } } retVal.setUpdated(updated); retVal.getEntries().addAll(returnList); return retVal; } /** * This method retrieves a single entry from the storage. If the * {@link StorageBuffer} does not contain the requested entry the * underlying storage index will be searched. * <p> * The Entry will be searched in a feed context specified by the given feed * ID * </p> * * @param entryId - * the entry to fetch * @param feedId - * the feed id e.g. feed context * @param config - * the FeedInstanceConfiguration containing extension profile used * to create the entry instances * @return - the requested {@link BaseEntry} or <code>null</code> if the * entry can not be found * @throws IOException - * if the index could not be queries or the entries could not be * build * @throws ParseException - * if an entry could not be parsed while building it from the * Lucene Document.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -