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)); } } } }
private static Dictionary <string, DynamicQueryMappingItem> CreateGroupByFields(IndexQueryServerSide query, Dictionary <string, DynamicQueryMappingItem> mapFields) { var groupByFields = query.Metadata.GroupBy; if (query.Metadata.SelectFields != null) { foreach (var field in query.Metadata.SelectFields) { if (field.IsGroupByKey) { continue; } var fieldName = field.Name; if (mapFields.TryGetValue(fieldName, out var existingField) == false) { switch (field.AggregationOperation) { case AggregationOperation.None: break; case AggregationOperation.Count: case AggregationOperation.Sum: mapFields.Add(fieldName, DynamicQueryMappingItem.Create(fieldName, field.AggregationOperation)); break; default: ThrowUnknownAggregationOperation(field.AggregationOperation); break; } } else if (field.AggregationOperation != AggregationOperation.None) { existingField.SetAggregation(field.AggregationOperation); } } } var result = new Dictionary <string, DynamicQueryMappingItem>(groupByFields.Length, StringComparer.Ordinal); for (int i = 0; i < groupByFields.Length; i++) { var groupByField = groupByFields[i]; result[groupByField.Name] = DynamicQueryMappingItem.CreateGroupBy(groupByField.Name, groupByField.GroupByArrayBehavior, query.Metadata.WhereFields); mapFields.Remove(groupByField.Name); // ensure we don't have duplicated group by fields } return(result); }
public static DynamicQueryMapping Create(Index index) { if (index.Type.IsAuto() == false) { throw new InvalidOperationException(); } var mapping = new DynamicQueryMapping { ForCollection = index.Collections.First(), MapFields = new Dictionary <string, DynamicQueryMappingItem>(StringComparer.Ordinal) }; var definition = (AutoIndexDefinitionBase)index.Definition; foreach (var field in definition.MapFields) { var autoField = (AutoIndexField)field.Value; mapping.MapFields[field.Key] = DynamicQueryMappingItem.Create( new QueryFieldName(autoField.Name, autoField.HasQuotedName), autoField.Aggregation, isFullTextSearch: autoField.Indexing.HasFlag(AutoFieldIndexing.Search), isExactSearch: autoField.Indexing.HasFlag(AutoFieldIndexing.Exact), hasHighlighting: autoField.Indexing.HasFlag(AutoFieldIndexing.Highlighting), hasSuggestions: autoField.HasSuggestions, spatial: autoField.Spatial); } if (index.Type.IsMapReduce()) { mapping.IsGroupBy = true; var mapReduceDefinition = (AutoMapReduceIndexDefinition)definition; mapping.GroupByFields = new Dictionary <string, DynamicQueryMappingItem>(StringComparer.Ordinal); foreach (var field in mapReduceDefinition.GroupByFields) { var autoField = field.Value; mapping.GroupByFields[field.Key] = DynamicQueryMappingItem.CreateGroupBy( new QueryFieldName(autoField.Name, autoField.HasQuotedName), autoField.GroupByArrayBehavior, isSpecifiedInWhere: true, isFullTextSearch: autoField.Indexing.HasFlag(AutoFieldIndexing.Search), isExactSearch: autoField.Indexing.HasFlag(AutoFieldIndexing.Exact)); } } return(mapping); }
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 DynamicQueryMapping Create(IndexQueryServerSide query) { var result = new DynamicQueryMapping { ForCollection = query.Metadata.CollectionName }; var mapFields = new Dictionary <string, DynamicQueryMappingItem>(StringComparer.Ordinal); foreach (var field in query.Metadata.IndexFieldNames) { if (field == Constants.Documents.Indexing.Fields.DocumentIdFieldName) { continue; } mapFields[field] = DynamicQueryMappingItem.Create(field, AggregationOperation.None, query.Metadata.WhereFields); } if (query.Metadata.OrderBy != null) { foreach (var field in query.Metadata.OrderBy) { if (field.OrderingType == OrderByFieldType.Random) { continue; } if (field.OrderingType == OrderByFieldType.Score) { continue; } if (field.Name == Constants.Documents.Indexing.Fields.DocumentIdFieldName) { continue; } var fieldName = field.Name; #if FEATURE_CUSTOM_SORTING if (fieldName.Value.StartsWith(Constants.Documents.Indexing.Fields.CustomSortFieldName)) { continue; } #endif if (mapFields.ContainsKey(field.Name)) { continue; } mapFields.Add(field.Name, DynamicQueryMappingItem.Create(fieldName, field.AggregationOperation)); } } if (query.Metadata.IsGroupBy) { result.IsGroupBy = true; result.GroupByFields = CreateGroupByFields(query, mapFields); foreach (var field in mapFields) { if (field.Value.AggregationOperation == AggregationOperation.None) { throw new InvalidQueryException($"Field '{field.Key}' isn't neither an aggregation operation nor part of the group by key", query.Metadata.QueryText, query.QueryParameters); } } } if (query.Metadata.HasHighlightings) { foreach (var highlighting in query.Metadata.Highlightings) { var fieldName = highlighting.Field; if (mapFields.TryGetValue(fieldName, out var value)) { value.HasHighlighting = true; } else { mapFields[fieldName] = DynamicQueryMappingItem.Create(fieldName, AggregationOperation.None, isFullTextSearch: true, isExactSearch: false, hasHighlighting: true, hasSuggestions: false, spatial: null); } } } if (query.Metadata.HasSuggest) { foreach (var selectField in query.Metadata.SelectFields) { var fieldName = selectField.Name; if (mapFields.TryGetValue(fieldName, out var value)) { value.HasSuggestions = true; } else { mapFields[fieldName] = DynamicQueryMappingItem.Create(fieldName, AggregationOperation.None, isFullTextSearch: false, isExactSearch: false, hasHighlighting: false, hasSuggestions: true, spatial: null); } } } result.MapFields = mapFields; return(result); }
public static DynamicQueryMapping Create(IndexQueryServerSide query) { var result = new DynamicQueryMapping { ForCollection = query.Metadata.CollectionName }; var mapFields = new Dictionary <string, DynamicQueryMappingItem>(StringComparer.Ordinal); foreach (var field in query.Metadata.IndexFieldNames) { if (field == Constants.Documents.Indexing.Fields.DocumentIdFieldName) { continue; } mapFields[field] = DynamicQueryMappingItem.Create(field, AggregationOperation.None, query.Metadata.WhereFields); } if (query.Metadata.OrderBy != null) { foreach (var field in query.Metadata.OrderBy) { if (field.OrderingType == OrderByFieldType.Random) { continue; } if (field.OrderingType == OrderByFieldType.Score) { continue; } var fieldName = field.Name; if (fieldName.Value.StartsWith(Constants.Documents.Indexing.Fields.CustomSortFieldName)) { continue; } if (mapFields.ContainsKey(field.Name)) { continue; } mapFields.Add(field.Name, DynamicQueryMappingItem.Create(fieldName, field.AggregationOperation)); } } if (query.Metadata.IsGroupBy) { result.IsGroupBy = true; result.GroupByFields = CreateGroupByFields(query, mapFields); foreach (var field in mapFields) { if (field.Value.AggregationOperation == AggregationOperation.None) { throw new InvalidQueryException($"Field '{field.Key}' isn't neither an aggregation operation nor part of the group by key", query.Metadata.QueryText, query.QueryParameters); } } } result.MapFields = mapFields; return(result); }