/// <summary>
        /// A fuzzy based query that uses similarity based on Levenshtein (edit distance) algorithm.
        /// Warning: this query is not very scalable with its default prefix length of 0 – in this case,
        /// every term will be enumerated and cause an edit score calculation or max_expansions is not set.
        /// </summary>
        public QueryContainer Fuzzy(Action <FuzzyQueryDescriptor <T> > selector)
        {
            var query = new FuzzyQueryDescriptor <T>();

            selector(query);

            return(this.New(query, q => q.Fuzzy = query));
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var j = JObject.Load(reader);

            if (!j.HasValues)
            {
                return(null);
            }

            var firstProp = j.Properties().FirstOrDefault();

            if (firstProp == null)
            {
                return(null);
            }

            var field = firstProp.Name;
            var jo    = firstProp.Value.Value <JObject>();

            if (jo == null)
            {
                return(null);
            }

            JToken v = null;

            if (!jo.TryGetValue("value", out v))
            {
                return(null);
            }

            IFuzzyQuery fq = null;

            if (v.Type == JTokenType.Date)
            {
                fq = new FuzzyDateQueryDescriptor <object>();
            }
            else if (v.Type == JTokenType.String)
            {
                fq = new FuzzyQueryDescriptor <object>();
            }
            else if (v.Type == JTokenType.Integer || v.Type == JTokenType.Float)
            {
                fq = new FuzzyNumericQueryDescriptor <object>();
            }
            else
            {
                return(null);
            }

            fq.Field          = field;
            fq.Boost          = GetPropValue <double?>(jo, "boost");
            fq.Fuzziness      = GetPropValue <string>(jo, "fuzziness");
            fq.MaxExpansions  = GetPropValue <int?>(jo, "max_expansions");
            fq.UnicodeAware   = GetPropValue <bool?>(jo, "unicode_aware");
            fq.Transpositions = GetPropValue <bool?>(jo, "transpositions");
            var rewriteString = GetPropValue <string>(jo, "rewrite");

            if (!rewriteString.IsNullOrEmpty())
            {
                fq.Rewrite = Enum.Parse(typeof(RewriteMultiTerm), rewriteString) as RewriteMultiTerm?;
            }

            if (fq is IStringFuzzyQuery)
            {
                var fqs = fq as IStringFuzzyQuery;
                fqs.PrefixLength = GetPropValue <int?>(jo, "prefix_length");
                fqs.Value        = GetPropValue <string>(jo, "value");
            }
            if (fq is IFuzzyDateQuery)
            {
                var fdq = fq as IFuzzyDateQuery;
                fdq.Value = GetPropValue <DateTime?>(jo, "value");
            }
            if (fq is IFuzzyNumericQuery)
            {
                var fnq = fq as IFuzzyNumericQuery;
                fnq.Value = GetPropValue <double?>(jo, "value");
            }

            return(fq);
        }