public void TestAntiM() { _searcher = new IndexSearcher(_directory, true); const double miles = 6.0; Console.WriteLine("testAntiM"); // create a distance query var dq = new DistanceQueryBuilder(_lat, _lng, miles, LatField, LngField, CartesianTierPlotter.DefaltFieldPrefix, true); Console.WriteLine(dq); //create a term query to search against all documents Query tq = new TermQuery(new Term("metafile", "doc")); var dsort = new DistanceFieldComparatorSource(dq.DistanceFilter); Sort sort = new Sort(new SortField("foo", dsort, false)); // Perform the search, using the term query, the distance filter, and the // distance sort TopDocs hits = _searcher.Search(tq, dq.Filter, 1000, sort); int results = hits.totalHits; ScoreDoc[] scoreDocs = hits.scoreDocs; // Get a list of distances Dictionary <int, Double> distances = dq.DistanceFilter.Distances; Console.WriteLine("Distance Filter filtered: " + distances.Count); Console.WriteLine("Results: " + results); Console.WriteLine("============================="); Console.WriteLine("Distances should be 7 " + distances.Count); Console.WriteLine("Results should be 7 " + results); Assert.AreEqual(7, distances.Count); // fixed a store of only needed distances Assert.AreEqual(7, results); double lastDistance = 0; for (int i = 0; i < results; i++) { Document d = _searcher.Doc(scoreDocs[i].doc); String name = d.Get("name"); double rsLat = NumericUtils.PrefixCodedToDouble(d.Get(LatField)); double rsLng = NumericUtils.PrefixCodedToDouble(d.Get(LngField)); Double geo_distance = distances[scoreDocs[i].doc]; double distance = DistanceUtils.GetInstance().GetDistanceMi(_lat, _lng, rsLat, rsLng); double llm = DistanceUtils.GetInstance().GetLLMDistance(_lat, _lng, rsLat, rsLng); Console.WriteLine("Name: " + name + ", Distance " + distance); Assert.IsTrue(Math.Abs((distance - llm)) < 1); Assert.IsTrue((distance < miles)); Assert.IsTrue(geo_distance >= lastDistance); lastDistance = geo_distance; } }
public IEnumerable <Service> Execute(ISession session) { var serviceType = typeof(Service); var dq = new DistanceQueryBuilder(_userLocation.Y, _userLocation.X, _distance * MeterInMiles, "Location_Latitude", "Location_Longitude", CartesianTierPlotter.DefaltFieldPrefix, false); var metaTermQuery = new TermQuery(new Term("metafile", "doc")); var dsort = new DistanceFieldComparatorSource(dq.DistanceFilter); Sort sort = new Sort(new SortField("Location", dsort, false)); var booleanQuery = new BooleanQuery(); booleanQuery.Add(metaTermQuery, BooleanClause.Occur.SHOULD); if (!string.IsNullOrWhiteSpace(_searchModel.Terms)) { var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29); var queryParser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_29, new[] { "Title", "Body", "Category_Name" }, analyzer); var termQuery = queryParser.Parse(_searchModel.Terms); booleanQuery.Add(termQuery, BooleanClause.Occur.MUST); } if (_searchModel.CategoryId != null) { var categoryQuery = new TermQuery(new Term("Category_Id", _searchModel.CategoryId.Value.ToString())); booleanQuery.Add(categoryQuery, BooleanClause.Occur.MUST); } if (_searchModel.Type != null) { if (_searchModel.Type.Value == (byte)ServiceType.Offering) { serviceType = typeof(ServiceOffering); } else if (_searchModel.Type.Value == (byte)ServiceType.Request) { serviceType = typeof(ServiceRequest); } } return(session.FullTextSession().CreateFullTextQuery(booleanQuery, serviceType) .SetFilter(dq.Filter).SetFetchSize(PageSize).List <Service>()); }
/// <summary> /// Perform a Look search /// </summary> /// <param name="lookQuery">A LookQuery model for the search criteria</param> /// <returns>A LookResult model for the search response</returns> public static LookResult RunQuery(LookQuery lookQuery) { // flag to indicate whether there are any query clauses in the supplied LookQuery bool hasQuery = lookQuery?.Compiled != null ? true : false; if (lookQuery == null) { return(new LookResult("LookQuery object was null")); } if (lookQuery.SearchingContext == null) // supplied by unit test to skip examine dependency { // attempt to get searching context from examine searcher name lookQuery.SearchingContext = LookService.GetSearchingContext(lookQuery.SearcherName); if (lookQuery.SearchingContext == null) { return(new LookResult("SearchingContext was null")); } } if (lookQuery.Compiled == null) { BooleanQuery query = null; // the lucene query being built Filter filter = null; // used for geospatial queries Sort sort = null; Func <string, IHtmlString> getHighlight = x => null; Func <int, double?> getDistance = x => null; query = new BooleanQuery(); #region RawQuery if (!string.IsNullOrWhiteSpace(lookQuery.RawQuery)) { hasQuery = true; query.Add( new QueryParser(Lucene.Net.Util.Version.LUCENE_29, null, lookQuery.SearchingContext.Analyzer).Parse(lookQuery.RawQuery), BooleanClause.Occur.MUST); } #endregion #region ExamineQuery if (lookQuery.ExamineQuery != null) { var luceneSearchCriteria = lookQuery.ExamineQuery as LuceneSearchCriteria; if (luceneSearchCriteria.Query != null) { hasQuery = true; query.Add(luceneSearchCriteria.Query, BooleanClause.Occur.MUST); } } #endregion #region NodeQuery if (lookQuery.NodeQuery != null) { hasQuery = true; query.Add(new TermQuery(new Term(LookConstants.HasNodeField, "1")), BooleanClause.Occur.MUST); if (lookQuery.NodeQuery.Types != null && lookQuery.NodeQuery.Types.Any()) { var nodeTypeQuery = new BooleanQuery(); foreach (var nodeType in lookQuery.NodeQuery.Types) { nodeTypeQuery.Add( new TermQuery( new Term(LookConstants.NodeTypeField, nodeType.ToString())), BooleanClause.Occur.SHOULD); } query.Add(nodeTypeQuery, BooleanClause.Occur.MUST); } switch (lookQuery.NodeQuery.DetachedQuery) { case DetachedQuery.ExcludeDetached: query.Add( new TermQuery(new Term(LookConstants.IsDetachedField, "1")), BooleanClause.Occur.MUST_NOT); break; case DetachedQuery.OnlyDetached: query.Add( new TermQuery(new Term(LookConstants.IsDetachedField, "1")), BooleanClause.Occur.MUST); break; } if (lookQuery.NodeQuery.Cultures != null && lookQuery.NodeQuery.Cultures.Any()) { var nodeCultureQuery = new BooleanQuery(); foreach (var nodeCulture in lookQuery.NodeQuery.Cultures) { nodeCultureQuery.Add( new TermQuery( new Term(LookConstants.CultureField, nodeCulture.LCID.ToString())), BooleanClause.Occur.SHOULD); } query.Add(nodeCultureQuery, BooleanClause.Occur.MUST); } if (lookQuery.NodeQuery.Aliases != null && lookQuery.NodeQuery.Aliases.Any()) { var nodeAliasQuery = new BooleanQuery(); foreach (var typeAlias in lookQuery.NodeQuery.Aliases) { nodeAliasQuery.Add( new TermQuery(new Term(LookConstants.NodeAliasField, typeAlias.ToLower())), BooleanClause.Occur.SHOULD); } query.Add(nodeAliasQuery, BooleanClause.Occur.MUST); } if (lookQuery.NodeQuery.NotIds != null && lookQuery.NodeQuery.NotIds.Any()) { foreach (var exculudeId in lookQuery.NodeQuery.NotIds) { query.Add( new TermQuery(new Term(LookConstants.NodeIdField, exculudeId.ToString())), BooleanClause.Occur.MUST_NOT); } } if (lookQuery.NodeQuery.NotKeys != null && lookQuery.NodeQuery.NotKeys.Any()) { foreach (var excludeKey in lookQuery.NodeQuery.NotKeys) { query.Add( new TermQuery(new Term(LookConstants.NodeKeyField, excludeKey)), BooleanClause.Occur.MUST_NOT); } } } #endregion #region NameQuery if (lookQuery.NameQuery != null) { hasQuery = true; query.Add(new TermQuery(new Term(LookConstants.HasNameField, "1")), BooleanClause.Occur.MUST); string wildcard1 = null; string wildcard2 = null; // incase Contains specified with StartsWith and/or EndsWith if (!string.IsNullOrEmpty(lookQuery.NameQuery.StartsWith)) { if (!string.IsNullOrEmpty(lookQuery.NameQuery.Is)) { if (!lookQuery.NameQuery.Is.StartsWith(lookQuery.NameQuery.StartsWith)) { return(new LookResult("Conflict in NameQuery between Is and StartsWith")); } } else { wildcard1 = lookQuery.NameQuery.StartsWith + "*"; } } if (!string.IsNullOrEmpty(lookQuery.NameQuery.EndsWith)) { if (!string.IsNullOrEmpty(lookQuery.NameQuery.Is)) { if (!lookQuery.NameQuery.Is.EndsWith(lookQuery.NameQuery.EndsWith)) { return(new LookResult("Conflict in NameQuery between Is and EndsWith")); } } else { if (wildcard1 == null) { wildcard1 = "*" + lookQuery.NameQuery.EndsWith; } else { wildcard1 += lookQuery.NameQuery.EndsWith; } } } if (!string.IsNullOrEmpty(lookQuery.NameQuery.Contains)) { if (!string.IsNullOrEmpty(lookQuery.NameQuery.Is)) { if (!lookQuery.NameQuery.Is.Contains(lookQuery.NameQuery.Contains)) { return(new LookResult("Conflict in NameQuery between Is and Contains")); } } else { if (wildcard1 == null) { wildcard1 = "*" + lookQuery.NameQuery.Contains + "*"; } else { wildcard2 = "*" + lookQuery.NameQuery.Contains + "*"; } } } var nameField = lookQuery.NameQuery.CaseSensitive ? LookConstants.NameField : LookConstants.NameField + "_Lowered"; if (wildcard1 != null) { var wildcard = lookQuery.NameQuery.CaseSensitive ? wildcard1 : wildcard1.ToLower(); query.Add(new WildcardQuery(new Term(nameField, wildcard)), BooleanClause.Occur.MUST); if (wildcard2 != null) { wildcard = lookQuery.NameQuery.CaseSensitive ? wildcard2 : wildcard2.ToLower(); query.Add(new WildcardQuery(new Term(nameField, wildcard)), BooleanClause.Occur.MUST); } } if (!string.IsNullOrEmpty(lookQuery.NameQuery.Is)) { var isText = lookQuery.NameQuery.CaseSensitive ? lookQuery.NameQuery.Is : lookQuery.NameQuery.Is.ToLower(); query.Add(new TermQuery(new Term(nameField, isText)), BooleanClause.Occur.MUST); } } #endregion #region DateQuery if (lookQuery.DateQuery != null) { hasQuery = true; query.Add(new TermQuery(new Term(LookConstants.HasDateField, "1")), BooleanClause.Occur.MUST); if (lookQuery.DateQuery.After.HasValue || lookQuery.DateQuery.Before.HasValue) { var includeLower = lookQuery.DateQuery.After == null || lookQuery.DateQuery.Boundary == DateBoundary.Inclusive || lookQuery.DateQuery.Boundary == DateBoundary.BeforeExclusiveAfterInclusive; var includeUpper = lookQuery.DateQuery.Before == null || lookQuery.DateQuery.Boundary == DateBoundary.Inclusive || lookQuery.DateQuery.Boundary == DateBoundary.BeforeInclusiveAfterExclusive; query.Add( new TermRangeQuery( LookConstants.DateField, lookQuery.DateQuery.After.DateToLuceneString() ?? DateTime.MinValue.DateToLuceneString(), lookQuery.DateQuery.Before.DateToLuceneString() ?? DateTime.MaxValue.DateToLuceneString(), includeLower, includeUpper), BooleanClause.Occur.MUST); } } #endregion #region TextQuery if (lookQuery.TextQuery != null) { hasQuery = true; query.Add(new TermQuery(new Term(LookConstants.HasTextField, "1")), BooleanClause.Occur.MUST); if (!string.IsNullOrWhiteSpace(lookQuery.TextQuery.SearchText)) { var queryParser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, LookConstants.TextField, lookQuery.SearchingContext.Analyzer); Query searchTextQuery = null; try { searchTextQuery = queryParser.Parse(lookQuery.TextQuery.SearchText); } catch { return(new LookResult($"Unable to parse LookQuery.TextQuery.SearchText: '{ lookQuery.TextQuery.SearchText }' into a Lucene query")); } if (searchTextQuery != null) { query.Add(searchTextQuery, BooleanClause.Occur.MUST); if (lookQuery.TextQuery.GetHighlight) { var queryScorer = new QueryScorer(searchTextQuery.Rewrite(lookQuery.SearchingContext.IndexSearcher.GetIndexReader())); var highlighter = new Highlighter(new SimpleHTMLFormatter("<strong>", "</strong>"), queryScorer); getHighlight = (x) => { var tokenStream = lookQuery.SearchingContext.Analyzer.TokenStream(LookConstants.TextField, new StringReader(x)); var highlight = highlighter.GetBestFragments( tokenStream, x, 1, // max number of fragments "..."); return(new HtmlString(highlight)); }; } } } } #endregion #region TagQuery if (lookQuery.TagQuery != null) { hasQuery = true; query.Add(new TermQuery(new Term(LookConstants.HasTagsField, "1")), BooleanClause.Occur.MUST); if (lookQuery.TagQuery.All != null) { if (lookQuery.TagQuery.Not != null) { var conflictTags = lookQuery.TagQuery.All.Where(x => !lookQuery.TagQuery.Not.Contains(x)); if (conflictTags.Any()) { return(new LookResult($"Conflict in TagQuery, tags: '{ string.Join(",", conflictTags) }' are in both AllTags and NotTags")); } } if (lookQuery.TagQuery.All.Any()) { foreach (var tag in lookQuery.TagQuery.All) { query.Add( new TermQuery(new Term(LookConstants.TagsField + tag.Group, tag.Name)), BooleanClause.Occur.MUST); } } } if (lookQuery.TagQuery.Any != null) { if (lookQuery.TagQuery.Not != null) { var conflictTags = lookQuery.TagQuery.Any.Where(x => !lookQuery.TagQuery.Not.Contains(x)); if (conflictTags.Any()) { return(new LookResult($"Conflict in TagQuery, tags: '{ string.Join(",", conflictTags) }' are in both AnyTags and NotTags")); } } if (lookQuery.TagQuery.Any.Any()) { var anyTagQuery = new BooleanQuery(); foreach (var tag in lookQuery.TagQuery.Any) { anyTagQuery.Add( new TermQuery(new Term(LookConstants.TagsField + tag.Group, tag.Name)), BooleanClause.Occur.SHOULD); } query.Add(anyTagQuery, BooleanClause.Occur.MUST); } } if (lookQuery.TagQuery.Not != null && lookQuery.TagQuery.Not.Any()) { foreach (var tag in lookQuery.TagQuery.Not) { query.Add( new TermQuery(new Term(LookConstants.TagsField + tag.Group, tag.Name)), BooleanClause.Occur.MUST_NOT); } } } #endregion #region LocationQuery if (lookQuery.LocationQuery != null) { hasQuery = true; query.Add(new TermQuery(new Term(LookConstants.HasLocationField, "1")), BooleanClause.Occur.MUST); if (lookQuery.LocationQuery.Location != null) { double maxDistance = LookService.MaxDistance; if (lookQuery.LocationQuery.MaxDistance != null) { maxDistance = Math.Min(lookQuery.LocationQuery.MaxDistance.GetMiles(), maxDistance); } var distanceQueryBuilder = new DistanceQueryBuilder( lookQuery.LocationQuery.Location.Latitude, lookQuery.LocationQuery.Location.Longitude, maxDistance, LookConstants.LocationField + "_Latitude", LookConstants.LocationField + "_Longitude", LookConstants.LocationTierFieldPrefix, true); filter = distanceQueryBuilder.Filter; if (lookQuery.SortOn == SortOn.Distance) { sort = new Sort( new SortField( LookConstants.DistanceField, new DistanceFieldComparatorSource(distanceQueryBuilder.DistanceFilter))); } getDistance = new Func <int, double?>(x => { if (distanceQueryBuilder.DistanceFilter.Distances.ContainsKey(x)) { return(distanceQueryBuilder.DistanceFilter.Distances[x]); } return(null); }); } } #endregion if (hasQuery) { switch (lookQuery.SortOn) { case SortOn.Name: // a -> z sort = new Sort(new SortField(LuceneIndexer.SortedFieldNamePrefix + LookConstants.NameField, SortField.STRING)); break; case SortOn.DateAscending: // oldest -> newest sort = new Sort(new SortField(LuceneIndexer.SortedFieldNamePrefix + LookConstants.DateField, SortField.LONG, false)); break; case SortOn.DateDescending: // newest -> oldest sort = new Sort(new SortField(LuceneIndexer.SortedFieldNamePrefix + LookConstants.DateField, SortField.LONG, true)); break; // SortOn.Distance already set (if valid) } lookQuery.Compiled = new LookQueryCompiled( lookQuery, query, filter, sort ?? new Sort(SortField.FIELD_SCORE), getHighlight, getDistance); } } if (!hasQuery) { return(new LookResult("No query clauses supplied")); // empty failure } TopDocs topDocs = lookQuery .SearchingContext .IndexSearcher .Search( lookQuery.Compiled.Query, lookQuery.Compiled.Filter, LookService.MaxLuceneResults, lookQuery.Compiled.Sort); if (topDocs.TotalHits > 0) { List <Facet> facets = null; if (lookQuery.TagQuery != null && lookQuery.TagQuery.FacetOn != null) { facets = new List <Facet>(); Query facetQuery = lookQuery.Compiled.Filter != null ? (Query) new FilteredQuery(lookQuery.Compiled.Query, lookQuery.Compiled.Filter) : lookQuery.Compiled.Query; // do a facet query for each group in the array foreach (var group in lookQuery.TagQuery.FacetOn.TagGroups) { var simpleFacetedSearch = new SimpleFacetedSearch( lookQuery.SearchingContext.IndexSearcher.GetIndexReader(), LookConstants.TagsField + group); var facetResult = simpleFacetedSearch.Search(facetQuery); facets.AddRange( facetResult .HitsPerFacet .Select( x => new Facet() { Tags = new LookTag[] { new LookTag(group, x.Name.ToString()) }, Count = Convert.ToInt32(x.HitCount) } )); } } return(new LookResult( LookService.GetLookMatches( lookQuery.SearchingContext.IndexSearcher, topDocs, lookQuery.RequestFields ?? LookService.Instance.RequestFields, lookQuery.Compiled.GetHighlight, lookQuery.Compiled.GetDistance), topDocs.TotalHits, facets != null ? facets.ToArray() : new Facet[] { })); } return(new LookResult()); // empty success }
/// <summary> /// /// </summary> /// <param name="lookQuery">The query to parse</param> /// <param name="parsingContext"></param> private static void ParseLocationQuery(ParsingContext parsingContext, LookQuery lookQuery) { if (lookQuery.LocationQuery == null) { return; } parsingContext.QueryAdd(new TermQuery(new Term(LookConstants.HasLocationField, "1")), BooleanClause.Occur.MUST); if (lookQuery.LocationQuery.Boundary != null) // limit results within an lat lng fixed view (eg, typical map bounds) { parsingContext.QueryAdd( new TermRangeQuery( LookConstants.LocationField + "_Latitude", NumericUtils.DoubleToPrefixCoded(lookQuery.LocationQuery.Boundary.LatitudeMin), NumericUtils.DoubleToPrefixCoded(lookQuery.LocationQuery.Boundary.LatitudeMax), true, true), BooleanClause.Occur.MUST); parsingContext.QueryAdd( new TermRangeQuery( LookConstants.LocationField + "_Longitude", NumericUtils.DoubleToPrefixCoded(lookQuery.LocationQuery.Boundary.LongitudeMin), NumericUtils.DoubleToPrefixCoded(lookQuery.LocationQuery.Boundary.LongitudeMax), true, true), BooleanClause.Occur.MUST); } if (lookQuery.LocationQuery.Location != null) // location set, so can calculate distance { double maxDistance = LookService._maxDistance; if (lookQuery.LocationQuery.MaxDistance != null) { maxDistance = Math.Min(lookQuery.LocationQuery.MaxDistance.GetMiles(), maxDistance); } var distanceQueryBuilder = new DistanceQueryBuilder( lookQuery.LocationQuery.Location.Latitude, lookQuery.LocationQuery.Location.Longitude, maxDistance, LookConstants.LocationField + "_Latitude", LookConstants.LocationField + "_Longitude", LookConstants.LocationTierFieldPrefix, true); parsingContext.Filter = distanceQueryBuilder.Filter; if (lookQuery.SortOn == SortOn.Distance) { parsingContext.Sort = new Sort( new SortField( LookConstants.DistanceField, new DistanceFieldComparatorSource(distanceQueryBuilder.DistanceFilter))); } parsingContext.GetDistance = new Func <int, double?>(x => { if (distanceQueryBuilder.DistanceFilter.Distances.ContainsKey(x)) { return(distanceQueryBuilder.DistanceFilter.Distances[x]); } return(null); }); } }
/// <summary> /// Searches the lucene index with the search text. /// </summary> /// <param name="searchText">The text to search with.</param> /// <remarks>Syntax reference: http://lucene.apache.org/java/2_3_2/queryparsersyntax.html#Wildcard</remarks> /// <exception cref="SpatialSearchException">An error occured searching the lucene.net index.</exception> public SpatialSearchResultsModel SearchIndex(double lat, double @long, double miles) { // This check is for the benefit of the CI builds if (!Directory.Exists(_indexPath)) { CreateIndex(); } EnsureDistanceMatrixReady(); var model = new SpatialSearchResultsModel(); //StandardAnalyzer analyzer = new StandardAnalyzer(); try { IndexSearcher searcher = new IndexSearcher(_indexPath, true); // Build query var dq = new DistanceQueryBuilder(lat, @long, miles, LatField, LngField, CartesianTierPlotter.DefaltFieldPrefix, true); //create a term query to search against all documents Query tq = new TermQuery(new Term("metafile", "doc")); var dsort = new DistanceFieldComparatorSource(dq.DistanceFilter); Sort sort = new Sort(new SortField("foo", dsort, false)); // Perform the search, using the term query, the distance filter, and the // distance sort TopDocs hits = searcher.Search(tq, dq.Filter, 1000, sort); int results = hits.totalHits; ScoreDoc[] scoreDocs = hits.scoreDocs; // Get a list of distances Dictionary <int, Double> distances = dq.DistanceFilter.Distances; model.QueryLat = lat; model.QueryLong = @long; model.QueryMiles = miles; //double lastDistance = 0; for (int i = 0; i < results; i++) { Document d = searcher.Doc(scoreDocs[i].doc); String name = d.Get("name"); double rsLat = NumericUtils.PrefixCodedToDouble(d.Get(LatField)); double rsLng = NumericUtils.PrefixCodedToDouble(d.Get(LngField)); int id = int.Parse(d.Get("PostID")); Double geo_distance = distances[scoreDocs[i].doc]; double distance = DistanceUtils.GetInstance().GetDistanceMi(lat, @long, rsLat, rsLng); double llm = DistanceUtils.GetInstance().GetLLMDistance(lat, @long, rsLat, rsLng); model.Results.Add(new SpatialResult() { title = name, instrumentID = id, dist = distance, lat = rsLat, lng = rsLng, resultNum = i + 1 }); //lastDistance = geo_distance; } } catch (Exception ex) { throw new SpatialSearchException(ex, "An error occurred while searching the spatial index."); } return(model); }
/// <summary> /// Main searching method /// </summary> /// <param name="lookQuery"></param> /// <returns>an IEnumerableWithTotal</returns> public static IEnumerableWithTotal <LookMatch> Query(LookQuery lookQuery) { IEnumerableWithTotal <LookMatch> lookMatches = null; // prepare return value if (lookQuery == null) { LogHelper.Warn(typeof(LookService), "Supplied search query was null"); } else { var searchProvider = LookService.Searcher; var searchCriteria = searchProvider.CreateSearchCriteria(); var query = searchCriteria.Field(string.Empty, string.Empty); // Text if (!string.IsNullOrWhiteSpace(lookQuery.TextQuery.SearchText)) { if (lookQuery.TextQuery.Fuzzyness > 0) { query.And().Field(LookService.TextField, lookQuery.TextQuery.SearchText.Fuzzy(lookQuery.TextQuery.Fuzzyness)); } else { query.And().Field(LookService.TextField, lookQuery.TextQuery.SearchText); } } // Tags if (lookQuery.TagQuery != null) { var allTags = new List <string>(); var anyTags = new List <string>(); if (lookQuery.TagQuery.AllTags != null) { allTags.AddRange(lookQuery.TagQuery.AllTags); allTags.RemoveAll(x => string.IsNullOrWhiteSpace(x)); } if (lookQuery.TagQuery.AnyTags != null) { anyTags.AddRange(lookQuery.TagQuery.AnyTags); anyTags.RemoveAll(x => string.IsNullOrWhiteSpace(x)); } if (allTags.Any()) { query.And().GroupedAnd(allTags.Select(x => LookService.TagsField), allTags.ToArray()); } if (anyTags.Any()) { query.And().GroupedOr(allTags.Select(x => LookService.TagsField), anyTags.ToArray()); } } // TODO: Date // TODO: Name // Nodes if (lookQuery.NodeQuery != null) { if (lookQuery.NodeQuery.TypeAliases != null) { var typeAliases = new List <string>(); typeAliases.AddRange(lookQuery.NodeQuery.TypeAliases); typeAliases.RemoveAll(x => string.IsNullOrWhiteSpace(x)); if (typeAliases.Any()) { query.And().GroupedOr(typeAliases.Select(x => UmbracoContentIndexer.NodeTypeAliasFieldName), typeAliases.ToArray()); } } if (lookQuery.NodeQuery.ExcludeIds != null) { foreach (var excudeId in lookQuery.NodeQuery.ExcludeIds.Distinct()) { query.Not().Id(excudeId); } } } try { searchCriteria = query.Compile(); } catch (Exception exception) { LogHelper.WarnWithException(typeof(LookService), "Could not compile the Examine query", exception); } if (searchCriteria != null && searchCriteria is LuceneSearchCriteria) { Sort sort = null; Filter filter = null; Func <int, double?> getDistance = x => null; Func <string, IHtmlString> getHighlight = null; TopDocs topDocs = null; switch (lookQuery.SortOn) { case SortOn.Date: // newest -> oldest sort = new Sort(new SortField(LuceneIndexer.SortedFieldNamePrefix + LookService.DateField, SortField.LONG, true)); break; case SortOn.Name: // a -> z sort = new Sort(new SortField(LuceneIndexer.SortedFieldNamePrefix + LookService.NameField, SortField.STRING)); break; } if (lookQuery.LocationQuery != null && lookQuery.LocationQuery.Location != null) { double maxDistance = LookService.MaxDistance; if (lookQuery.LocationQuery.MaxDistance != null) { maxDistance = Math.Min(lookQuery.LocationQuery.MaxDistance.GetMiles(), maxDistance); } var distanceQueryBuilder = new DistanceQueryBuilder( lookQuery.LocationQuery.Location.Latitude, lookQuery.LocationQuery.Location.Longitude, maxDistance, LookService.LocationField + "_Latitude", LookService.LocationField + "_Longitude", CartesianTierPlotter.DefaltFieldPrefix, true); // update filter filter = distanceQueryBuilder.Filter; if (lookQuery.SortOn == SortOn.Distance) { // update sort sort = new Sort( new SortField( LookService.DistanceField, new DistanceFieldComparatorSource(distanceQueryBuilder.DistanceFilter))); } // raw data for the getDistance func var distances = distanceQueryBuilder.DistanceFilter.Distances; // update getDistance func getDistance = new Func <int, double?>(x => { if (distances.ContainsKey(x)) { return(distances[x]); } return(null); }); } var indexSearcher = new IndexSearcher(((LuceneIndexer)LookService.Indexer).GetLuceneDirectory(), false); var luceneSearchCriteria = (LuceneSearchCriteria)searchCriteria; // Do the Lucene search topDocs = indexSearcher.Search( luceneSearchCriteria.Query, // the query build by Examine filter ?? new QueryWrapperFilter(luceneSearchCriteria.Query), LookService.MaxLuceneResults, sort ?? new Sort(SortField.FIELD_SCORE)); if (topDocs.TotalHits > 0) { // setup the highlighing func if required if (lookQuery.TextQuery.HighlightFragments > 0 && !string.IsNullOrWhiteSpace(lookQuery.TextQuery.SearchText)) { var version = Lucene.Net.Util.Version.LUCENE_29; Analyzer analyzer = new StandardAnalyzer(version); var queryParser = new QueryParser(version, LookService.TextField, analyzer); var queryScorer = new QueryScorer(queryParser .Parse(lookQuery.TextQuery.SearchText) .Rewrite(indexSearcher.GetIndexReader())); Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter("<strong>", "</strong>"), queryScorer); // update the func so it does real highlighting work getHighlight = (x) => { var tokenStream = analyzer.TokenStream(LookService.TextField, new StringReader(x)); var highlight = highlighter.GetBestFragments( tokenStream, x, lookQuery.TextQuery.HighlightFragments, // max number of fragments lookQuery.TextQuery.HighlightSeparator); // fragment separator return(new HtmlString(highlight)); }; } lookMatches = new EnumerableWithTotal <LookMatch>( LookSearchService.GetLookMatches( lookQuery, indexSearcher, topDocs, getHighlight, getDistance), topDocs.TotalHits); } } } return(lookMatches ?? new EnumerableWithTotal <LookMatch>(Enumerable.Empty <LookMatch>(), 0)); }