Esempio n. 1
0
        public static AutoIndexDefinition GetAutoIndexDefinition(AutoIndexDefinitionBaseServerSide 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,
            });
        }
Esempio n. 2
0
        public static IndexType GetAutoIndexType(AutoIndexDefinitionBaseServerSide 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);
        }
Esempio n. 3
0
 public FaultyAutoIndexDefinition(string name, HashSet <string> collections, IndexLockMode lockMode, IndexPriority priority, IndexState state, IndexField[] mapFields, AutoIndexDefinitionBaseServerSide definition)
     : base(name, collections, lockMode, priority, state, mapFields, definition.Version, definition.DeploymentMode, definition.ClusterState)
 {
     Definition = definition;
 }
Esempio n. 4
0
 public FaultyInMemoryIndex(Exception e, string name, IndexingConfiguration configuration, AutoIndexDefinitionBaseServerSide definition)
     : this(e, configuration, new FaultyAutoIndexDefinition(name, new HashSet <string> { "@FaultyIndexes" }, IndexLockMode.Unlock, IndexPriority.Normal, IndexState.Normal, new IndexField[0], definition))
 {
 }
Esempio n. 5
0
        internal DynamicQueryMatchResult ConsiderUsageOfIndex(DynamicQueryMapping query, AutoIndexDefinitionBaseServerSide 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;
            }

            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
            });
        }
Esempio n. 6
0
        public static PutAutoIndexCommand Create(AutoIndexDefinitionBaseServerSide definition, string databaseName, string raftRequestId, IndexDeploymentMode mode)
        {
            var indexType = GetAutoIndexType(definition);

            return(new PutAutoIndexCommand(GetAutoIndexDefinition(definition, indexType), databaseName, raftRequestId, mode, SystemTime.UtcNow));
        }
Esempio n. 7
0
        public void ExtendMappingBasedOn(AutoIndexDefinitionBaseServerSide 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,
                            hasHighlighting : queryField.HasHighlighting || indexField.Indexing.HasFlag(AutoFieldIndexing.Highlighting),
                            hasSuggestions : queryField.HasSuggestions || indexField.HasSuggestions,
                            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),
                                       hasHighlighting: indexField.Indexing.HasFlag(AutoFieldIndexing.Highlighting),
                                       hasSuggestions: indexField.HasSuggestions,
                                       spatial: indexField.Spatial));
                    }
                }
            }
        }