private SearchFilter GetSearchFilter(string q, string sortOrder, int page) { var searchFilter = new SearchFilter { SearchTerm = q, Skip = (page - 1) * 20, // pages are 1-based. Take = 20, IncludePrerelease = false }; searchFilter.SortProperty = SortProperty.Hit; return searchFilter; }
public IQueryable<OutDoor> Search(IQueryable<OutDoor> OutDoors, SearchFilter searchFilter, out int totalHits) { if (OutDoors == null) { throw new ArgumentNullException("OutDoors"); } if (searchFilter == null) { throw new ArgumentNullException("searchFilter"); } if (searchFilter.Skip < 0) { throw new ArgumentOutOfRangeException("searchFilter"); } if (searchFilter.Take < 0) { throw new ArgumentOutOfRangeException("searchFilter"); } // For the given search term, find the keys that match. var keys = SearchCore(searchFilter, out totalHits); if (keys.Count == 0 || searchFilter.CountOnly) { return Enumerable.Empty<OutDoor>().AsQueryable(); } // Query the source for each of the keys that need to be taken. var results = OutDoors.Where(p => keys.Contains(p.MediaID)); // When querying the database, these keys are returned in no particular order. We use the original order of queries // and retrieve each of the OutDoors from the result in the same order. var lookup = results.ToDictionary(p => p.MediaID, p => p); return keys.Select(key => LookupOutDoor(lookup, key)) .Where(p => p != null) .AsQueryable(); }
private static Query ParseQuery(SearchFilter searchFilter) { if (String.IsNullOrWhiteSpace(searchFilter.SearchTerm)) { return new MatchAllDocsQuery(); } var fields = new[] { "Title", "Description", "MediaCateName", "CityName" }; var analyzer = new ChineseAnalyzer(); //var analyzer = new StandardAnalyzer(LuceneCommon.LuceneVersion); var queryParser = new MultiFieldQueryParser(LuceneCommon.LuceneVersion, fields, analyzer); var query = queryParser.Parse(searchFilter.SearchTerm); // All terms in the multi-term query appear in at least one of the fields. var conjuctionQuery = new BooleanQuery(); conjuctionQuery.Boost = 2.0f; // Some terms in the multi-term query appear in at least one of the fields. var disjunctionQuery = new BooleanQuery(); disjunctionQuery.Boost = 0.1f; // Suffix wildcard search e.g. jquer* var wildCardQuery = new BooleanQuery(); wildCardQuery.Boost = 0.5f; //// Escape the entire term we use for exact searches. var escapedSearchTerm = Escape(searchFilter.SearchTerm); var exactIdQuery = new TermQuery(new Term("Title", escapedSearchTerm)); exactIdQuery.Boost = 2.5f; var wildCardIdQuery = new WildcardQuery(new Term("Title", "*" + escapedSearchTerm + "*")); foreach (var term in GetSearchTerms(searchFilter.SearchTerm)) { var termQuery = queryParser.Parse(term); conjuctionQuery.Add(termQuery, Occur.MUST); disjunctionQuery.Add(termQuery, Occur.SHOULD); foreach (var field in fields) { var wildCardTermQuery = new WildcardQuery(new Term(field, term + "*")); wildCardTermQuery.Boost = 0.7f; wildCardQuery.Add(wildCardTermQuery, Occur.SHOULD); } } //var combinedQuery = // conjuctionQuery.Combine(new Query[] { exactIdQuery, conjuctionQuery }); //// Create an OR of all the queries that we have var combinedQuery = conjuctionQuery.Combine(new Query[] { exactIdQuery, wildCardIdQuery, conjuctionQuery, disjunctionQuery, wildCardQuery }); if (searchFilter.SortProperty == SortProperty.Hit) { // If searching by relevance, boost scores by download count. var downloadCountBooster = new FieldScoreQuery("Hit", FieldScoreQuery.Type.INT); return new CustomScoreQuery(combinedQuery, downloadCountBooster); } return combinedQuery; }
private static IList<int> SearchCore(SearchFilter searchFilter, out int totalHits) { if (!Directory.Exists(LuceneCommon.IndexDirectory)) { totalHits = 0; return new int[0]; } SortField sortField = GetSortField(searchFilter); int numRecords = searchFilter.Skip + searchFilter.Take; using (var directory = new LuceneFileSystem(LuceneCommon.IndexDirectory)) { var searcher = new IndexSearcher(directory, readOnly: true); var query = ParseQuery(searchFilter); //var analyzer = new ChineseAnalyzer(); //QueryParser parser = new QueryParser(LuceneCommon.LuceneVersion, searchFilter.SearchTerm, analyzer); //Query query = parser.Parse(searchFilter.SearchTerm); var filterTerm = searchFilter.IncludePrerelease ? "IsLatest" : "IsLatestStable"; var termQuery = new TermQuery(new Term(filterTerm, Boolean.TrueString)); Filter filter = new QueryWrapperFilter(termQuery); var results = searcher.Search(query, filter: null, n: numRecords, sort: new Sort(sortField)); var keys = results.ScoreDocs.Skip(searchFilter.Skip) .Select(c => ParseKey(searcher.Doc(c.Doc).Get("MediaID"))) .ToList(); totalHits = results.TotalHits; searcher.Close(); return keys; } }
private static SortField GetSortField(SearchFilter searchFilter) { switch (searchFilter.SortProperty) { case SortProperty.DisplayName: return new SortField("DisplayName", SortField.STRING, reverse: searchFilter.SortDirection == SortDirection.Descending); case SortProperty.Hit: return new SortField("Hit", SortField.INT, reverse: true); case SortProperty.Price: return new SortField("Price", SortField.INT, reverse: true); case SortProperty.Published: return new SortField("Published", SortField.LONG, reverse: true); } return SortField.FIELD_SCORE; }