public void ExtendMappingBasedOn(AutoIndexDefinitionBase definitionOfExistingIndex)
        {
            Debug.Assert(definitionOfExistingIndex is AutoMapIndexDefinition || definitionOfExistingIndex is AutoMapReduceIndexDefinition, "Dynamic queries are handled only by auto indexes");

            switch (definitionOfExistingIndex)
            {
            case AutoMapIndexDefinition def:
                Update(MapFields, def.MapFields, isGroupBy: false);
                break;

            case AutoMapReduceIndexDefinition def:
                Update(MapFields, def.MapFields, isGroupBy: false);
                Update(GroupByFields, def.GroupByFields, isGroupBy: true);
                break;
            }

            void Update <T>(Dictionary <string, DynamicQueryMappingItem> fields, Dictionary <string, T> indexFields, bool isGroupBy) where T : IndexFieldBase
            {
                foreach (var f in indexFields.Values)
                {
                    var indexField = f.As <AutoIndexField>();

                    if (fields.TryGetValue(indexField.Name, out var queryField))
                    {
                        var isFullTextSearch = queryField.IsFullTextSearch || indexField.Indexing.HasFlag(AutoFieldIndexing.Search);
                        var isExactSearch    = queryField.IsExactSearch || indexField.Indexing.HasFlag(AutoFieldIndexing.Exact);

                        var field = isGroupBy == false
                            ? DynamicQueryMappingItem.Create(
                            queryField.Name,
                            queryField.AggregationOperation,
                            isFullTextSearch : isFullTextSearch,
                            isExactSearch : isExactSearch,
                            spatial : queryField.Spatial ?? indexField.Spatial)
                            : DynamicQueryMappingItem.CreateGroupBy(
                            queryField.Name,
                            queryField.GroupByArrayBehavior,
                            isSpecifiedInWhere: queryField.IsSpecifiedInWhere,
                            isFullTextSearch: isFullTextSearch,
                            isExactSearch: isExactSearch);

                        fields[queryField.Name] = field;
                    }
                    else
                    {
                        if (isGroupBy)
                        {
                            throw new InvalidOperationException("Cannot create new GroupBy field when extending mapping");
                        }

                        fields.Add(indexField.Name, DynamicQueryMappingItem.Create(
                                       new QueryFieldName(indexField.Name, indexField.HasQuotedName),
                                       indexField.Aggregation,
                                       isFullTextSearch: indexField.Indexing.HasFlag(AutoFieldIndexing.Search),
                                       isExactSearch: indexField.Indexing.HasFlag(AutoFieldIndexing.Exact),
                                       spatial: indexField.Spatial));
                    }
                }
            }
        }
Beispiel #2
0
        private void HandleAutoIndexChange(string name, AutoIndexDefinitionBase definition)
        {
            var creationOptions = IndexCreationOptions.Create;
            var existingIndex   = GetIndex(name);
            IndexDefinitionCompareDifferences differences = IndexDefinitionCompareDifferences.None;

            if (existingIndex != null)
            {
                creationOptions = GetIndexCreationOptions(definition, existingIndex, out differences);
            }

            if (creationOptions == IndexCreationOptions.Noop)
            {
                Debug.Assert(existingIndex != null);

                return;
            }

            if (creationOptions == IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex || creationOptions == IndexCreationOptions.Update)
            {
                Debug.Assert(existingIndex != null);

                if ((differences & IndexDefinitionCompareDifferences.LockMode) != 0)
                {
                    existingIndex.SetLock(definition.LockMode);
                }

                if ((differences & IndexDefinitionCompareDifferences.Priority) != 0)
                {
                    existingIndex.SetPriority(definition.Priority);
                }

                existingIndex.Update(definition, existingIndex.Configuration);

                return;
            }

            Index index;

            if (definition is AutoMapIndexDefinition)
            {
                index = AutoMapIndex.CreateNew((AutoMapIndexDefinition)definition, _documentDatabase);
            }
            else if (definition is AutoMapReduceIndexDefinition)
            {
                index = AutoMapReduceIndex.CreateNew((AutoMapReduceIndexDefinition)definition, _documentDatabase);
            }
            else
            {
                throw new NotImplementedException($"Unknown index definition type: {definition.GetType().FullName}");
            }

            CreateIndexInternal(index);
        }
        public static AutoIndexDefinition GetAutoIndexDefinition(AutoIndexDefinitionBase definition, IndexType indexType)
        {
            Debug.Assert(indexType == IndexType.AutoMap || indexType == IndexType.AutoMapReduce);

            return(new AutoIndexDefinition
            {
                Collection = definition.Collections.First(),
                MapFields = CreateFields(definition.MapFields.ToDictionary(x => x.Key, x => x.Value.As <AutoIndexField>())),
                GroupByFields = indexType == IndexType.AutoMap ? null : CreateFields(((AutoMapReduceIndexDefinition)definition).GroupByFields),
                Priority = definition.Priority,
                Name = definition.Name,
                Type = indexType
            });
        }
        public static IndexType GetAutoIndexType(AutoIndexDefinitionBase definition)
        {
            var indexType = IndexType.None;

            if (definition is AutoMapIndexDefinition)
            {
                indexType = IndexType.AutoMap;
            }

            if (definition is AutoMapReduceIndexDefinition)
            {
                indexType = IndexType.AutoMapReduce;
            }

            if (indexType == IndexType.None)
            {
                throw new RachisApplyException($"Invalid definition type: {definition.GetType()}");
            }

            return(indexType);
        }
Beispiel #5
0
        public void ExtendMappingBasedOn(AutoIndexDefinitionBase definitionOfExistingIndex)
        {
            Debug.Assert(definitionOfExistingIndex is AutoMapIndexDefinition || definitionOfExistingIndex is AutoMapReduceIndexDefinition, "Dynamic queries are handled only by auto indexes");

            switch (definitionOfExistingIndex)
            {
            case AutoMapIndexDefinition def:
                Update(MapFields, def.MapFields);
                break;

            case AutoMapReduceIndexDefinition def:
                Update(MapFields, def.MapFields);
                Update(GroupByFields, def.GroupByFields);
                break;
            }

            void Update <T>(Dictionary <string, DynamicQueryMappingItem> mappingFields, Dictionary <string, T> indexFields) where T : IndexFieldBase
            {
                foreach (var f in indexFields.Values)
                {
                    var indexField = f.As <AutoIndexField>();

                    if (mappingFields.TryGetValue(indexField.Name, out var queryField))
                    {
                        mappingFields[queryField.Name] = DynamicQueryMappingItem.Create(queryField.Name, queryField.AggregationOperation,
                                                                                        isFullTextSearch: queryField.IsFullTextSearch || indexField.Indexing.HasFlag(AutoFieldIndexing.Search),
                                                                                        isExactSearch: queryField.IsExactSearch || indexField.Indexing.HasFlag(AutoFieldIndexing.Exact),
                                                                                        spatial: queryField.Spatial ?? indexField.Spatial);
                    }
                    else
                    {
                        mappingFields.Add(indexField.Name, DynamicQueryMappingItem.Create(new QueryFieldName(indexField.Name, indexField.HasQuotedName), indexField.Aggregation,
                                                                                          isFullTextSearch: indexField.Indexing.HasFlag(AutoFieldIndexing.Search),
                                                                                          isExactSearch: indexField.Indexing.HasFlag(AutoFieldIndexing.Exact),
                                                                                          spatial: indexField.Spatial));
                    }
                }
            }
        }
        public static PutAutoIndexCommand Create(AutoIndexDefinitionBase definition, string databaseName)
        {
            var indexType = IndexType.None;
            var map       = definition as AutoMapIndexDefinition;

            if (map != null)
            {
                indexType = IndexType.AutoMap;
            }

            var reduce = definition as AutoMapReduceIndexDefinition;

            if (reduce != null)
            {
                indexType = IndexType.AutoMapReduce;
            }

            if (indexType == IndexType.None)
            {
                throw new NotSupportedException("Invalid definition type: " + definition.GetType());
            }

            return(new PutAutoIndexCommand(GetAutoIndexDefinition(definition, indexType), databaseName));
        }
        public static PutAutoIndexCommand Create(AutoIndexDefinitionBase definition, string databaseName, string raftRequestId)
        {
            var indexType = GetAutoIndexType(definition);

            return(new PutAutoIndexCommand(GetAutoIndexDefinition(definition, indexType), databaseName, raftRequestId));
        }
Beispiel #8
0
 public FaultyInMemoryIndex(Exception e, string name, IndexingConfiguration configuration, AutoIndexDefinitionBase definition)
     : this(e, configuration, new FaultyAutoIndexDefinition(name, new HashSet <string> { "@FaultyIndexes" }, IndexLockMode.Unlock, IndexPriority.Normal, IndexState.Normal, new IndexField[0], definition))
 {
 }
        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
            });
        }
 public FaultyAutoIndexDefinition(string name, HashSet <string> collections, IndexLockMode lockMode, IndexPriority priority, IndexState state, IndexField[] mapFields, AutoIndexDefinitionBase definition)
     : base(name, collections, lockMode, priority, state, mapFields, definition.Version)
 {
     Definition = definition;
 }