Пример #1
0
        public static Filter CreateRangeFilterForValue(string fieldName, string lower, string upper, bool includeLower, bool includeUpper)
        {
            Filter result = null;

            // If both bounds are empty, ignore this range
            if (!string.IsNullOrEmpty(lower) || !string.IsNullOrEmpty(upper))
            {
                var lowerLong = ConvertToDateTimeTicks(lower);
                var upperLong = ConvertToDateTimeTicks(upper);
                if (lowerLong != null || upperLong != null)
                {
                    result = NumericRangeFilter.NewInt64Range(fieldName, lowerLong, upperLong, includeLower, includeUpper);
                }
                else
                {
                    var lowerDouble = ConvertToDouble(lower);
                    var upperDouble = ConvertToDouble(upper);
                    if (lowerDouble != null || upperDouble != null)
                    {
                        result = NumericRangeFilter.NewDoubleRange(fieldName, lowerDouble, upperDouble, includeLower, includeUpper);
                    }
                    else
                    {
                        result = TermRangeFilter.NewStringRange(fieldName, lower, upper, includeLower, includeUpper);
                    }
                }
            }

            return(result);
        }
Пример #2
0
        public virtual Filter GetFilter(XmlElement e)
        {
            string field          = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
            string lowerTerm      = DOMUtils.GetAttributeOrFail(e, "lowerTerm");
            string upperTerm      = DOMUtils.GetAttributeOrFail(e, "upperTerm");
            bool   lowerInclusive = DOMUtils.GetAttribute(e, "includeLower", true);
            bool   upperInclusive = DOMUtils.GetAttribute(e, "includeUpper", true);
            int    precisionStep  = DOMUtils.GetAttribute(e, "precisionStep", NumericUtils.PRECISION_STEP_DEFAULT);

            string type = DOMUtils.GetAttribute(e, "type", "int");

            try
            {
                Filter filter;
                if (type.Equals("int", StringComparison.OrdinalIgnoreCase))
                {
                    filter = NumericRangeFilter.NewInt32Range(field, precisionStep, Convert
                                                              .ToInt32(lowerTerm, CultureInfo.InvariantCulture), Convert.ToInt32(upperTerm, CultureInfo.InvariantCulture), lowerInclusive,
                                                              upperInclusive);
                }
                else if (type.Equals("long", StringComparison.OrdinalIgnoreCase))
                {
                    filter = NumericRangeFilter.NewInt64Range(field, precisionStep, Convert
                                                              .ToInt64(lowerTerm, CultureInfo.InvariantCulture), Convert.ToInt64(upperTerm, CultureInfo.InvariantCulture), lowerInclusive,
                                                              upperInclusive);
                }
                else if (type.Equals("double", StringComparison.OrdinalIgnoreCase))
                {
                    filter = NumericRangeFilter.NewDoubleRange(field, precisionStep, Convert
                                                               .ToDouble(lowerTerm, CultureInfo.InvariantCulture), Convert.ToDouble(upperTerm, CultureInfo.InvariantCulture), lowerInclusive,
                                                               upperInclusive);
                }
                else if (type.Equals("float", StringComparison.OrdinalIgnoreCase))
                {
                    filter = NumericRangeFilter.NewSingleRange(field, precisionStep, Convert
                                                               .ToSingle(lowerTerm, CultureInfo.InvariantCulture), Convert.ToSingle(upperTerm, CultureInfo.InvariantCulture), lowerInclusive,
                                                               upperInclusive);
                }
                else
                {
                    throw new ParserException("type attribute must be one of: [long, int, double, float]");
                }
                return(filter);
            }
            catch (FormatException nfe)
            {
                if (strictMode)
                {
                    throw new ParserException("Could not parse lowerTerm or upperTerm into a number", nfe);
                }
                return(NO_MATCH_FILTER);
            }
        }
Пример #3
0
 /// <summary>
 /// 通过类型来获取
 /// </summary>
 /// <param name="property"></param>
 /// <param name="min"></param>
 /// <param name="max"></param>
 /// <returns></returns>
 public static Filter GetNumberFilter(PropertyInfo property, double min, double max)
 {
     if (property.PropertyType == typeof(double) || property.PropertyType == typeof(decimal))
     {
         return(NumericRangeFilter.NewDoubleRange(property.Name, min, max, true, true));
     }
     else if (property.PropertyType == typeof(float))
     {
         return(NumericRangeFilter.NewFloatRange(property.Name, (float)min, (float)max, true, true));
     }
     else if (property.PropertyType == typeof(int))
     {
         return(NumericRangeFilter.NewIntRange(property.Name, (int)min, (int)max, true, true));
     }
     else
     {
         return(null);
     }
 }
        public NumericRangeFilterInstance <Double> CreateDoubleRangeFilter(string fieldName, int precisionStep, object min, object max, bool minInclusive, bool maxInclusive)
        {
            double?doubleMin = null;

            if (min != null && min != Null.Value && min != Undefined.Value && min is int)
            {
                doubleMin = Convert.ToDouble(min);
            }

            double?doubleMax = null;

            if (max != null && max != Null.Value && max != Undefined.Value && max is int)
            {
                doubleMax = Convert.ToDouble(max);
            }

            var filter = NumericRangeFilter.NewDoubleRange(fieldName, precisionStep, doubleMin, doubleMax, minInclusive, maxInclusive);

            return(new NumericRangeFilterInstance <double>(this.Engine.Object.InstancePrototype, filter));
        }
Пример #5
0
        public virtual void TestRandomDoubles()
        {
            Directory         dir = NewDirectory();
            RandomIndexWriter w   = new RandomIndexWriter(Random(), dir, Similarity, TimeZone);

            int numDocs = AtLeast(1000);

            double[] values   = new double[numDocs];
            double   minValue = double.PositiveInfinity;
            double   maxValue = double.NegativeInfinity;

            for (int i = 0; i < numDocs; i++)
            {
                Document doc = new Document();
                double   v   = Random().NextDouble();
                values[i] = v;
                doc.Add(new DoubleDocValuesField("field", v));
                doc.Add(new DoubleField("field", v, Field.Store.NO));
                w.AddDocument(doc);
                minValue = Math.Min(minValue, v);
                maxValue = Math.Max(maxValue, v);
            }
            IndexReader r = w.Reader;

            IndexSearcher s      = NewSearcher(r);
            FacetsConfig  config = new FacetsConfig();

            int numIters = AtLeast(10);

            for (int iter = 0; iter < numIters; iter++)
            {
                if (VERBOSE)
                {
                    Console.WriteLine("TEST: iter=" + iter);
                }
                int           numRange         = TestUtil.NextInt(Random(), 1, 5);
                DoubleRange[] ranges           = new DoubleRange[numRange];
                int[]         expectedCounts   = new int[numRange];
                double        minAcceptedValue = double.PositiveInfinity;
                double        maxAcceptedValue = double.NegativeInfinity;
                for (int rangeID = 0; rangeID < numRange; rangeID++)
                {
                    double min;
                    if (rangeID > 0 && Random().Next(10) == 7)
                    {
                        // Use an existing boundary:
                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
                        if (Random().NextBoolean())
                        {
                            min = prevRange.Min;
                        }
                        else
                        {
                            min = prevRange.Max;
                        }
                    }
                    else
                    {
                        min = Random().NextDouble();
                    }
                    double max;
                    if (rangeID > 0 && Random().Next(10) == 7)
                    {
                        // Use an existing boundary:
                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
                        if (Random().NextBoolean())
                        {
                            max = prevRange.Min;
                        }
                        else
                        {
                            max = prevRange.Max;
                        }
                    }
                    else
                    {
                        max = Random().NextDouble();
                    }

                    if (min > max)
                    {
                        double x = min;
                        min = max;
                        max = x;
                    }

                    bool minIncl;
                    bool maxIncl;
                    if (min == max)
                    {
                        minIncl = true;
                        maxIncl = true;
                    }
                    else
                    {
                        minIncl = Random().NextBoolean();
                        maxIncl = Random().NextBoolean();
                    }
                    ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);

                    // Do "slow but hopefully correct" computation of
                    // expected count:
                    for (int i = 0; i < numDocs; i++)
                    {
                        bool accept = true;
                        if (minIncl)
                        {
                            accept &= values[i] >= min;
                        }
                        else
                        {
                            accept &= values[i] > min;
                        }
                        if (maxIncl)
                        {
                            accept &= values[i] <= max;
                        }
                        else
                        {
                            accept &= values[i] < max;
                        }
                        if (accept)
                        {
                            expectedCounts[rangeID]++;
                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
                        }
                    }
                }

                FacetsCollector sfc = new FacetsCollector();
                s.Search(new MatchAllDocsQuery(), sfc);
                Filter fastMatchFilter;
                if (Random().NextBoolean())
                {
                    if (Random().NextBoolean())
                    {
                        fastMatchFilter = NumericRangeFilter.NewDoubleRange("field", minValue, maxValue, true, true);
                    }
                    else
                    {
                        fastMatchFilter = NumericRangeFilter.NewDoubleRange("field", minAcceptedValue, maxAcceptedValue, true, true);
                    }
                }
                else
                {
                    fastMatchFilter = null;
                }
                ValueSource vs     = new DoubleFieldSource("field");
                Facets      facets = new DoubleRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
                FacetResult result = facets.GetTopChildren(10, "field");
                Assert.AreEqual(numRange, result.LabelValues.Length);
                for (int rangeID = 0; rangeID < numRange; rangeID++)
                {
                    if (VERBOSE)
                    {
                        Console.WriteLine("  range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
                    }
                    LabelAndValue subNode = result.LabelValues[rangeID];
                    Assert.AreEqual("r" + rangeID, subNode.Label);
                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.Value);

                    DoubleRange range = ranges[rangeID];

                    // Test drill-down:
                    DrillDownQuery ddq = new DrillDownQuery(config);
                    if (Random().NextBoolean())
                    {
                        if (Random().NextBoolean())
                        {
                            ddq.Add("field", NumericRangeFilter.NewDoubleRange("field", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
                        }
                        else
                        {
                            ddq.Add("field", NumericRangeQuery.NewDoubleRange("field", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
                        }
                    }
                    else
                    {
                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
                    }

                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
                }
            }

            IOUtils.Close(w, r, dir);
        }
Пример #6
0
        /// <summary>
        /// Given a latitude and longitude (in degrees) and the
        /// maximum great circle (surface of the earth) distance,
        /// returns a simple Filter bounding box to "fast match"
        /// candidates.
        /// </summary>
        public static Filter GetBoundingBoxFilter(double originLat, double originLng, double maxDistanceKM)
        {
            // Basic bounding box geo math from
            // http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates,
            // licensed under creative commons 3.0:
            // http://creativecommons.org/licenses/by/3.0

            // TODO: maybe switch to recursive prefix tree instead
            // (in lucene/spatial)?  It should be more efficient
            // since it's a 2D trie...

            // Degrees -> Radians:
            double originLatRadians = originLat.ToRadians();
            double originLngRadians = originLng.ToRadians();

            double angle = maxDistanceKM / (SloppyMath.EarthDiameter(originLat) / 2.0);

            double minLat = originLatRadians - angle;
            double maxLat = originLatRadians + angle;

            double minLng;
            double maxLng;

            if (minLat > -90.ToRadians() && maxLat < 90.ToRadians())
            {
                double delta = Math.Asin(Math.Sin(angle) / Math.Cos(originLatRadians));
                minLng = originLngRadians - delta;
                if (minLng < -180.ToRadians())
                {
                    minLng += 2 * Math.PI;
                }
                maxLng = originLngRadians + delta;
                if (maxLng > 180.ToRadians())
                {
                    maxLng -= 2 * Math.PI;
                }
            }
            else
            {
                // The query includes a pole!
                minLat = Math.Max(minLat, -90.ToRadians());
                maxLat = Math.Min(maxLat, 90.ToRadians());
                minLng = -180.ToRadians();
                maxLng = 180.ToRadians();
            }

            BooleanFilter f = new BooleanFilter();

            // Add latitude range filter:
            f.Add(NumericRangeFilter.NewDoubleRange("latitude", minLat.ToDegrees(), maxLat.ToDegrees(), true, true),
                  Occur.MUST);

            // Add longitude range filter:
            if (minLng > maxLng)
            {
                // The bounding box crosses the international date
                // line:
                BooleanFilter lonF = new BooleanFilter();
                lonF.Add(NumericRangeFilter.NewDoubleRange("longitude", minLng.ToDegrees(), null, true, true),
                         Occur.SHOULD);
                lonF.Add(NumericRangeFilter.NewDoubleRange("longitude", null, maxLng.ToDegrees(), true, true),
                         Occur.SHOULD);
                f.Add(lonF, Occur.MUST);
            }
            else
            {
                f.Add(NumericRangeFilter.NewDoubleRange("longitude", minLng.ToDegrees(), maxLng.ToDegrees(), true, true),
                      Occur.MUST);
            }

            return(f);
        }