/// <summary>
        /// Toes the index definition.
        /// </summary>
        public IndexDefinition ToIndexDefinition(DocumentConvention convention, bool validateMap = true)
        {
            if (Map == null && validateMap)
            {
                throw new InvalidOperationException(
                          string.Format("Map is required to generate an index, you cannot create an index without a valid Map property (in index {0}).", indexName));
            }

            try
            {
                if (Reduce != null)
                {
                    IndexDefinitionHelper.ValidateReduce(Reduce);
                }

                string querySource     = (typeof(TDocument) == typeof(object) || ContainsWhereEntityIs()) ? "docs" : "docs." + convention.GetTypeTagName(typeof(TDocument));
                var    indexDefinition = new IndexDefinition
                {
                    Reduce   = IndexDefinitionHelper.PruneToFailureLinqQueryAsStringToWorkableCode <TDocument, TReduceResult>(Reduce, convention, "results", translateIdentityProperty: false),
                    LockMode = LockMode
                };

                if (MaxIndexOutputsPerDocument.HasValue)
                {
                    indexDefinition.Configuration.MaxIndexOutputsPerDocument = MaxIndexOutputsPerDocument;
                }

                var indexes            = ConvertToStringDictionary(Indexes);
                var stores             = ConvertToStringDictionary(Stores);
                var sortOptions        = ConvertToStringDictionary(SortOptions);
                var analyzers          = ConvertToStringDictionary(Analyzers);
                var suggestionsOptions = ConvertToStringSet(SuggestionsOptions).ToDictionary(x => x, x => true);
                var termVectors        = ConvertToStringDictionary(TermVectors);
                var spatialOptions     = ConvertToStringDictionary(SpatialIndexes);

                if (convention.PrettifyGeneratedLinqExpressions)
                {
                    indexDefinition.Reduce = IndexPrettyPrinter.TryFormat(indexDefinition.Reduce);
                }

                foreach (var indexesString in IndexesStrings)
                {
                    if (indexes.ContainsKey(indexesString.Key))
                    {
                        throw new InvalidOperationException("There is a duplicate key in indexes: " + indexesString.Key);
                    }
                    indexes.Add(indexesString);
                }

                foreach (var storeString in StoresStrings)
                {
                    if (stores.ContainsKey(storeString.Key))
                    {
                        throw new InvalidOperationException("There is a duplicate key in stores: " + storeString.Key);
                    }
                    stores.Add(storeString);
                }

                foreach (var analyzerString in AnalyzersStrings)
                {
                    if (analyzers.ContainsKey(analyzerString.Key))
                    {
                        throw new InvalidOperationException("There is a duplicate key in analyzers: " + analyzerString.Key);
                    }
                    analyzers.Add(analyzerString);
                }

                foreach (var termVectorString in TermVectorsStrings)
                {
                    if (termVectors.ContainsKey(termVectorString.Key))
                    {
                        throw new InvalidOperationException("There is a duplicate key in term vectors: " + termVectorString.Key);
                    }
                    termVectors.Add(termVectorString);
                }

                foreach (var spatialString in SpatialIndexesStrings)
                {
                    if (spatialOptions.ContainsKey(spatialString.Key))
                    {
                        throw new InvalidOperationException("There is a duplicate key in spatial indexes: " + spatialString.Key);
                    }
                    spatialOptions.Add(spatialString);
                }

                foreach (var sortOption in SortOptionsStrings)
                {
                    if (sortOptions.ContainsKey(sortOption.Key))
                    {
                        throw new InvalidOperationException("There is a duplicate key in sort options: " + sortOption.Key);
                    }
                    sortOptions.Add(sortOption);
                }

                ApplyValues(indexDefinition, indexes, (options, value) => options.Indexing               = value);
                ApplyValues(indexDefinition, stores, (options, value) => options.Storage                 = value);
                ApplyValues(indexDefinition, sortOptions, (options, value) => options.Sort               = value);
                ApplyValues(indexDefinition, analyzers, (options, value) => options.Analyzer             = value);
                ApplyValues(indexDefinition, termVectors, (options, value) => options.TermVector         = value);
                ApplyValues(indexDefinition, spatialOptions, (options, value) => options.Spatial         = value);
                ApplyValues(indexDefinition, suggestionsOptions, (options, value) => options.Suggestions = value);

                if (Map != null)
                {
                    var map = IndexDefinitionHelper.PruneToFailureLinqQueryAsStringToWorkableCode <TDocument, TReduceResult>(
                        Map,
                        convention,
                        querySource,
                        translateIdentityProperty: true);

                    indexDefinition.Maps.Add(convention.PrettifyGeneratedLinqExpressions ? IndexPrettyPrinter.TryFormat(map) : map);
                }

                return(indexDefinition);
            }
            catch (Exception e)
            {
                throw new IndexCompilationException("Failed to create index " + indexName, e);
            }
        }