Пример #1
0
		private void HandleTermsFacet(string index, Facet facet, IndexQuery indexQuery, IndexSearcher currentIndexSearcher, Dictionary<string, IEnumerable<FacetValue>> results)
		{
			var terms = database.ExecuteGetTermsQuery(index,
													  facet.Name, null,
													  database.Configuration.MaxPageSize);
			var termResults = new List<FacetValue>();
			var baseQuery = database.IndexStorage.GetLuceneQuery(index, indexQuery, database.IndexQueryTriggers);
			foreach (var term in terms)
			{
				var termQuery = new TermQuery(new Term(facet.Name, term));

				var joinedQuery = new BooleanQuery();
				joinedQuery.Add(baseQuery, BooleanClause.Occur.MUST);
				joinedQuery.Add(termQuery, BooleanClause.Occur.MUST);

				var topDocs = currentIndexSearcher.Search(joinedQuery, null, 1);

				if (topDocs.TotalHits > 0)
				{
					termResults.Add(new FacetValue
					{
						Count = topDocs.TotalHits,
						Range = term
					});
				}
			}

			results[facet.Name] = termResults;
		}
Пример #2
0
		private void HandleRangeFacet(string index, Facet facet, IndexQuery indexQuery, IndexSearcher currentIndexSearcher, Dictionary<string, IEnumerable<FacetValue>> results)
		{
			var rangeResults = new List<FacetValue>();
			foreach (var range in facet.Ranges)
			{
				var baseQuery = database.IndexStorage.GetLuceneQuery(index, indexQuery, database.IndexQueryTriggers);
				//TODO the built-in parser can't handle [NULL TO 100.0}, i.e. a mix of [ and }
				//so we need to handle this ourselves (greater and less-than-or-equal)
				var rangeQuery = database.IndexStorage.GetLuceneQuery(index, new IndexQuery
				{
					Query = facet.Name + ":" + range
				}, database.IndexQueryTriggers);

				var joinedQuery = new BooleanQuery();
				joinedQuery.Add(baseQuery, BooleanClause.Occur.MUST);
				joinedQuery.Add(rangeQuery, BooleanClause.Occur.MUST);

				var topDocs = currentIndexSearcher.Search(joinedQuery, null, 1);

				if (topDocs.TotalHits > 0)
				{
					rangeResults.Add(new FacetValue
					{
						Count = topDocs.TotalHits,
						Range = range
					});
				}
			}

			results[facet.Name] = rangeResults;
		}
Пример #3
0
		public void CanUseNullablesForFacets()
		{
			Facet facet = new Facet<Thread>()
			{
				Name = t => t.CreationDate,
				Ranges =
					{
						t => t.CreationDate.Value < new DateTime(2012,1,1),
					}
			};

			Assert.Equal(@"[NULL TO 2012\-01\-01T00\:00\:00.0000000]", facet.Ranges[0]);
		}
Пример #4
0
        public void AdvancedAPIAdvancedEdgeCases()
        {
            var testDateTime = new DateTime(2001, 12, 5);
            var edgeCaseFacet = new Facet<Test>
            {
                Name = x => x.Date,
                Ranges =
                {
                    x => x.Date < DateTime.Now,
                    x => x.Date > new DateTime(2010, 12, 5) && x.Date < testDateTime
                }
            };

            var facet = TriggerConversion(edgeCaseFacet);
            Assert.Equal(2, facet.Ranges.Count);
            Assert.False(String.IsNullOrWhiteSpace(facet.Ranges[0]));
            Assert.Equal(@"[2010\-12\-05T00\:00\:00.0000000 TO 2001\-12\-05T00\:00\:00.0000000]", facet.Ranges[1]);
        }
Пример #5
0
		public static Facet[] GetFacetsFromHttpContext(this IHttpContext context)
		{
			var dictionary = new Dictionary<string, Facet>();

			foreach (var facetString in context.Request.QueryString.AllKeys
				.Where(x=>x.StartsWith("facet.", StringComparison.OrdinalIgnoreCase))
				.ToArray())
			{
				var parts = facetString.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
				if (parts.Length != 3)
					throw new InvalidOperationException("Could not parse query parameter: " + facetString);

				var fieldName = parts[1];

				Facet facet;
				if (dictionary.TryGetValue(fieldName, out facet) == false)
					dictionary[fieldName] = facet = new Facet { Name = fieldName };

				foreach (var value in context.Request.QueryString.GetValues(facetString) ?? Enumerable.Empty<string>())
				{
					switch (parts[2].ToLowerInvariant())
					{
						case "mode":
							FacetMode mode;
							if (Enum.TryParse(value, true, out mode) == false)
								throw new InvalidOperationException("Could not parse " + facetString + "=" + value);

							facet.Mode = mode;
							break;
						case "range":
							facet.Ranges.Add(value);
							break;
					}
				}
			}
			return dictionary.Values.ToArray();
		}
Пример #6
0
			private void ApplyAggregation(Facet facet, FacetValue value, List<int> docsInQuery, IndexReader indexReader, int docBase)
			{
			    var sortOptionsForFacet = GetSortOptionsForFacet(facet.AggregationField);
			    switch (sortOptionsForFacet)
				{
					case SortOptions.String:
					case SortOptions.StringVal:
					case SortOptions.Byte:
					case SortOptions.Short:
					case SortOptions.Custom:
					case SortOptions.None:
						throw new InvalidOperationException(string.Format("Cannot perform numeric aggregation on index field '{0}'. You must set the Sort mode of the field to Int, Float, Long or Double.", TryTrimRangeSuffix(facet.AggregationField)));
					case SortOptions.Int:
                        int[] ints = FieldCache_Fields.DEFAULT.GetInts(indexReader, facet.AggregationField);
				        foreach (var doc in docsInQuery)
				        {
                            var currentVal = ints[doc - docBase];
                            if (facet.Aggregation.HasFlag(FacetAggregation.Max))
                            {
                                value.Max = Math.Max(value.Max ?? Double.MinValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Min))
                            {
                                value.Min = Math.Min(value.Min ?? Double.MaxValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Sum))
                            {
                                value.Sum = currentVal + (value.Sum ?? 0d);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Average))
                            {
                                value.Average = currentVal + (value.Average ?? 0d);
                            }
				        }
				        break;
					case SortOptions.Float:
						var floats = FieldCache_Fields.DEFAULT.GetFloats(indexReader, facet.AggregationField);
				        foreach (var doc in docsInQuery)
				        {
                            var currentVal = floats[doc - docBase];
                            if (facet.Aggregation.HasFlag(FacetAggregation.Max))
                            {
                                value.Max = Math.Max(value.Max ?? Double.MinValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Min))
                            {
                                value.Min = Math.Min(value.Min ?? Double.MaxValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Sum))
                            {
                                value.Sum = currentVal + (value.Sum ?? 0d);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Average))
                            {
                                value.Average = currentVal + (value.Average ?? 0d);
                            }
				        }
				        break;
					case SortOptions.Long:
						var longs = FieldCache_Fields.DEFAULT.GetLongs(indexReader, facet.AggregationField);
				        foreach (var doc in docsInQuery)
				        {
                            var currentVal = longs[doc - docBase];
                            if (facet.Aggregation.HasFlag(FacetAggregation.Max))
                            {
                                value.Max = Math.Max(value.Max ?? Double.MinValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Min))
                            {
                                value.Min = Math.Min(value.Min ?? Double.MaxValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Sum))
                            {
                                value.Sum = currentVal + (value.Sum ?? 0d);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Average))
                            {
                                value.Average = currentVal + (value.Average ?? 0d);
                            }
				        }
				        break;
					case SortOptions.Double:
						var doubles = FieldCache_Fields.DEFAULT.GetDoubles(indexReader, facet.AggregationField);
				        foreach (var doc in docsInQuery)
				        {
                            var currentVal = doubles[doc - docBase];
                            if (facet.Aggregation.HasFlag(FacetAggregation.Max))
                            {
                                value.Max = Math.Max(value.Max ?? Double.MinValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Min))
                            {
                                value.Min = Math.Min(value.Min ?? Double.MaxValue, currentVal);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Sum))
                            {
                                value.Sum = currentVal + (value.Sum ?? 0d);
                            }

                            if (facet.Aggregation.HasFlag(FacetAggregation.Average))
                            {
                                value.Average = currentVal + (value.Average ?? 0d);
                            }
				        }
				        break;
					default:
                        throw new ArgumentOutOfRangeException("Cannot understand " + sortOptionsForFacet);
				}
			}
Пример #7
0
 private void ApplyFacetValueHit(FacetValue facetValue, Facet value, int docId, ParsedRange parsedRange)
 {
     facetValue.Hits++;
     if (value.Aggregation == FacetAggregation.Count || value.Aggregation == FacetAggregation.None)
     {
         return;
     }
     FacetValueState set;
     if (matches.TryGetValue(facetValue, out set) == false)
     {
         matches[facetValue] = set = new FacetValueState
         {
             Docs = new HashSet<int>(),
             Facet = value,
             Range = parsedRange
         };
     }
     set.Docs.Add(docId);
 }
Пример #8
0
            private void ApplyAggregation(Facet facet, FacetValue value, double currentVal)
            {
                if (facet.Aggregation.HasFlag(FacetAggregation.Max))
                {
                    value.Max = Math.Max(value.Max ?? Double.MinValue, currentVal);
                }

                if (facet.Aggregation.HasFlag(FacetAggregation.Min))
                {
                    value.Min = Math.Min(value.Min ?? Double.MaxValue, currentVal);
                }

                if (facet.Aggregation.HasFlag(FacetAggregation.Sum))
                {
                    value.Sum = currentVal + (value.Sum ?? 0d);
                }

                if (facet.Aggregation.HasFlag(FacetAggregation.Average))
                {
                    value.Average = currentVal + (value.Average ?? 0d);
                }
            }
Пример #9
0
 private Facet TriggerConversion(Facet<Test> facet)
 {
     //The conversion is done with an implicit cast,
     //so we remain compatible with the original facet API
     return (Facet)facet;
 }
Пример #10
0
 private bool AreFacetsEqual(Facet left, Facet right)
 {
     return left.Name == right.Name &&
         left.Mode == right.Mode &&
         left.Ranges.Count == right.Ranges.Count &&
         left.Ranges.All(x => right.Ranges.Contains(x));
 }
Пример #11
0
            private void ApplyFacetValueHit(FacetValue facetValue, Facet value, int docId, ParsedRange parsedRange, IndexReader indexReader)
            {
                facetValue.Hits++;
                if (
					IndexQuery.IsDistinct == false &&
					(value.Aggregation == FacetAggregation.Count || value.Aggregation == FacetAggregation.None)
				   )
                {
                    return;
                }
                FacetValueState set;
                if (matches.TryGetValue(facetValue, out set) == false)
                {
                    matches[facetValue] = set = new FacetValueState
                    {
                        Docs = new HashSet<int>(),
                        Facet = value,
                        Range = parsedRange
                    };
                }
	            if (IndexQuery.IsDistinct)
	            {
					if(IndexQuery.FieldsToFetch.Length == 0)
						throw new InvalidOperationException("Cannot process distinct facet query without specifying which fields to distinct upon.");

		            if (set.AlreadySeen == null)
			            set.AlreadySeen = new HashSet<StringCollectionValue>();

		            var document = indexReader.Document(docId);
		            var fields = new List<string>();
					foreach (var fieldName in IndexQuery.FieldsToFetch)
		            {
						foreach (var field in document.GetFields(fieldName))
						{
							if (field.StringValue == null)
								continue;
				            fields.Add(field.StringValue);
			            }
		            }
		            if (fields.Count == 0)
			            throw new InvalidOperationException("Cannot apply distinct facet on [" + string.Join(", ", IndexQuery.FieldsToFetch) +
							"], did you forget to store them in the index? ");

		            if (set.AlreadySeen.Add(new StringCollectionValue(fields)) == false)
		            {
			            facetValue.Hits--;// already seen, cancel this
			            return;
		            }
	            }
                set.Docs.Add(docId);
            }