internal DynamicQueryMatchResult ConsiderUsageOfIndex(DynamicQueryMapping query, AutoIndexDefinitionBase definition, List <Explanation> explanations = null)
        {
            var collection = query.ForCollection;
            var indexName  = definition.Name;

            if (definition.Collections.Contains(collection) == false)
            {
                explanations?.Add(new Explanation(indexName,
                                                  definition.Collections.Count == 0
                        ? "Query is specific for collection, but the index searches across all of them, may result in a different type being returned."
                        : $"Index does not apply to collection '{collection}'"));

                return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Failure));
            }

            if (definition.Collections.Count > 1) // we only allow indexes with a single entity name
            {
                explanations?.Add(new Explanation(indexName, "Index contains more than a single entity name, may result in a different type being returned."));
                return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Failure));
            }

            var index = _indexStore.GetIndex(definition.Name);

            if (index == null)
            {
                return(new DynamicQueryMatchResult(definition.Name, DynamicQueryMatchType.Failure));
            }

            var  state = index.State;
            bool isInvalidStats;

            try
            {
                isInvalidStats = index.IsInvalidIndex();
            }
            catch (OperationCanceledException)
            {
                return(new DynamicQueryMatchResult(definition.Name, DynamicQueryMatchType.Failure));
            }
            if (state == IndexState.Error || state == IndexState.Disabled || isInvalidStats)
            {
                explanations?.Add(new Explanation(indexName, $"Cannot do dynamic queries on disabled index or index with errors (index name = {indexName})"));
                return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Failure));
            }

            var currentBestState = DynamicQueryMatchType.Complete;

            foreach (var field in query.MapFields.Values)
            {
                if (definition.TryGetField(field.Name, out var indexField))
                {
                    if (field.IsFullTextSearch && indexField.Indexing.HasFlag(AutoFieldIndexing.Search) == false)
                    {
                        explanations?.Add(new Explanation(indexName, $"The following field is not searchable {indexField.Name}, while the query needs to search() on it"));
                        return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Partial));
                    }

                    if (field.HasHighlighting && indexField.Indexing.HasFlag(AutoFieldIndexing.Highlighting) == false)
                    {
                        explanations?.Add(new Explanation(indexName, $"The following field does not have highlighting {indexField.Name}, while the query needs to do highlight() on it"));
                        return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Partial));
                    }

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

                    if (field.Spatial != null)
                    {
                        if (field.Spatial.Equals(indexField.Spatial) == false)
                        {
                            explanations?.Add(new Explanation(indexName, $"The following field is not a spatial field {indexField.Name}, while the query needs to perform spatial() on it"));
                            return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Failure));
                        }
                    }

                    if (field.HasSuggestions && indexField.HasSuggestions == false)
                    {
                        explanations?.Add(new Explanation(indexName, $"The following field does not have suggestions enabled {indexField.Name}, while the query needs to perform suggest() on it"));
                        return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Partial));
                    }
                }
                else
                {
                    explanations?.Add(new Explanation(indexName, $"The following field is missing: {field.Name}"));
                    currentBestState = DynamicQueryMatchType.Partial;
                }
            }

            if (currentBestState == DynamicQueryMatchType.Complete && state == IndexState.Idle)
            {
                currentBestState = DynamicQueryMatchType.CompleteButIdle;
                explanations?.Add(new Explanation(indexName, $"The index (name = {indexName}) is idle. The preference is for active indexes - making a complete match but marking the index is idle"));
            }

            if (currentBestState != DynamicQueryMatchType.Failure && query.IsGroupBy)
            {
                var bestMapReduceMatch = AssertMapReduceFields(query, (AutoMapReduceIndexDefinition)definition, currentBestState, explanations);

                if (bestMapReduceMatch != DynamicQueryMatchType.Complete)
                {
                    return(new DynamicQueryMatchResult(indexName, bestMapReduceMatch));
                }
            }

            long lastMappedEtagFor;

            try
            {
                lastMappedEtagFor = index.GetLastMappedEtagFor(collection);
            }
            catch (OperationCanceledException)
            {
                // the index was disposed while we were reading it, just ignore it
                // probably dynamic index that was disposed by the auto cleaner
                return(new DynamicQueryMatchResult(indexName, DynamicQueryMatchType.Failure));
            }

            return(new DynamicQueryMatchResult(indexName, currentBestState)
            {
                LastMappedEtag = lastMappedEtagFor,
                NumberOfMappedFields = definition.MapFields.Count
            });
        }