private bool AssertMapReduceFields(DynamicQueryMapping query, AutoMapReduceIndexDefinition definition, DynamicQueryMatchType currentBestState, List <Explanation> explanations)
        {
            var indexName = definition.Name;

            foreach (var mapField in query.MapFields)
            {
                if (definition.ContainsField(mapField.Name) == false)
                {
                    Debug.Assert(currentBestState == DynamicQueryMatchType.Partial);
                    continue;
                }

                var field = definition.GetField(mapField.Name);

                if (field.MapReduceOperation != mapField.MapReduceOperation)
                {
                    explanations?.Add(new Explanation(indexName, $"The following field {field.Name} has {field.MapReduceOperation} operation defined, while query required {mapField.MapReduceOperation}"));

                    return(false);
                }
            }

            if (query.GroupByFields.All(definition.ContainsGroupByField) == false)
            {
                if (explanations != null)
                {
                    var missingFields = query.GroupByFields.Where(x => definition.ContainsGroupByField(x) == false);
                    explanations?.Add(new Explanation(indexName, $"The following group by fields are missing: {string.Join(", ", missingFields)}"));
                }

                return(false);
            }

            if (query.GroupByFields.Length != definition.GroupByFields.Count)
            {
                if (explanations != null)
                {
                    var extraFields = definition.GroupByFields.Where(x => query.GroupByFields.Contains(x.Key) == false);
                    explanations?.Add(new Explanation(indexName, $"Index {indexName} has additional group by fields: {string.Join(", ", extraFields)}"));
                }

                return(false);
            }

            return(true);
        }
        private static DynamicQueryMatchType AssertMapReduceFields(DynamicQueryMapping query, AutoMapReduceIndexDefinition definition, DynamicQueryMatchType currentBestState,
                                                                   List <Explanation> explanations)
        {
            var indexName = definition.Name;

            foreach (var mapField in query.MapFields.Values)
            {
                if (definition.ContainsField(mapField.Name) == false)
                {
                    Debug.Assert(currentBestState == DynamicQueryMatchType.Partial);
                    continue;
                }

                var field = definition.GetField(mapField.Name);

                if (field.Aggregation != mapField.AggregationOperation)
                {
                    explanations?.Add(new Explanation(indexName,
                                                      $"The following field {field.Name} has {field.Aggregation} operation defined, while query required {mapField.AggregationOperation}"));

                    return(DynamicQueryMatchType.Failure);
                }
            }

            foreach (var groupByField in query.GroupByFields.Values)
            {
                if (definition.GroupByFields.TryGetValue(groupByField.Name, out var indexField))
                {
                    if (groupByField.GroupByArrayBehavior != indexField.GroupByArrayBehavior)
                    {
                        explanations?.Add(new Explanation(indexName,
                                                          $"The following group by field {indexField.Name} is grouping by '{indexField.GroupByArrayBehavior}', while the query needs to perform '{groupByField.GroupByArrayBehavior}' grouping"));

                        return(DynamicQueryMatchType.Failure);
                    }

                    if (groupByField.IsSpecifiedInWhere == false)
                    {
                        continue;
                    }

                    if (groupByField.IsFullTextSearch && indexField.Indexing.HasFlag(AutoFieldIndexing.Search) == false)
                    {
                        explanations?.Add(new Explanation(indexName,
                                                          $"The following group by field is not searchable {indexField.Name}, while the query needs to perform search() on it"));

                        return(DynamicQueryMatchType.Partial);
                    }

                    if (groupByField.IsExactSearch && indexField.Indexing.HasFlag(AutoFieldIndexing.Exact) == false)
                    {
                        explanations?.Add(new Explanation(indexName,
                                                          $"The following group by field is not exactable {indexField.Name}, while the query needs to perform exact() on it"));

                        return(DynamicQueryMatchType.Partial);
                    }
                }
                else
                {
                    if (explanations != null)
                    {
                        var missingFields = query.GroupByFields.Where(x => definition.GroupByFields.ContainsKey(x.Value.Name) == false);
                        explanations.Add(new Explanation(indexName, $"The following group by fields are missing: {string.Join(", ", missingFields)}"));
                    }

                    return(DynamicQueryMatchType.Failure);
                }
            }


            if (query.GroupByFields.Count != definition.GroupByFields.Count)
            {
                if (explanations != null)
                {
                    var extraFields = definition.GroupByFields.Where(x => query.GroupByFields.Select(y => y.Value.Name.Value).Contains(x.Key) == false);
                    explanations.Add(new Explanation(indexName, $"Index {indexName} has additional group by fields: {string.Join(", ", extraFields)}"));
                }

                return(DynamicQueryMatchType.Failure);
            }

            return(DynamicQueryMatchType.Complete);
        }