public void GetPropertyMapping_ReturnsCorrectMappingForLanguage(string language, bool isAnalyzable, string expectedAnalyzer) { IndexMappingProperty result = Language.GetPropertyMapping(language, typeof(string), isAnalyzable); Assert.Equal(expectedAnalyzer, result.Analyzer); Assert.Equal(nameof(MappingType.Text).ToLower(), result.Type); }
internal static IndexMappingProperty GetPropertyMapping(string language, Type type, bool isAnalyzable) { string analyzer = null; if (isAnalyzable && language != null) { analyzer = GetLanguageAnalyzer(language); } IndexMappingProperty mapping = new IndexMappingProperty { Analyzer = analyzer, Type = Mapping.GetMappingTypeAsString(type) }; return(mapping); }
public void UpdateMapping(Type type, Type indexType, string index, string language, bool optIn) { if (type.Name.EndsWith("Proxy")) { type = type.BaseType; } language = language ?? _settings.GetLanguage(index); var indexableProperties = GetIndexableProperties(type, optIn); Logger.Information("IndexableProperties for " + type?.Name + ": " + String.Join(", ", indexableProperties.Select(p => p.Name))); // Get existing mapping IndexMapping mapping = _mapping.GetIndexMapping(indexType, null, index); // Ignore special mappings mapping.Properties.Remove(DefaultFields.AttachmentData); mapping.Properties.Remove(DefaultFields.BestBets); mapping.Properties.Remove(DefaultFields.DidYouMean); mapping.Properties.Remove(DefaultFields.Suggest); try { foreach (var prop in indexableProperties) { string propName = prop.Name; IndexMappingProperty propertyMapping = mapping.Properties.ContainsKey(prop.Name) ? mapping.Properties[prop.Name] : Language.GetPropertyMapping(language, prop.Type, prop.Analyzable); string mappingType = Mapping.GetMappingTypeAsString(prop.Type); // If mapping with same name exists, use its type. // Different name/type combos is not allowed. if (mapping.Properties.ContainsKey(prop.Name)) { string existingType = mapping.Properties[prop.Name].Type; if (mappingType != existingType) { Logger.Warning($"Conflicting mapping type '{mappingType}' for property '{propName}' detected. Using already mapped type '{existingType}'"); } mappingType = existingType; } var analyzerFull = Language.GetLanguageAnalyzer(language); var analyzerSimple = Language.GetSimpleLanguageAnalyzer(language); if (prop.Analyzable && language != null) { propertyMapping.Analyzer = analyzerFull; } else if (!WellKnownProperties.IgnoreAnalyzer.Contains(prop.Name) && language != null && mappingType == nameof(MappingType.Text).ToLower() && propertyMapping.Analyzer != analyzerFull) { propertyMapping.Analyzer = analyzerSimple; } // If mapping with different analyzer exists, use its analyzer. if (!WellKnownProperties.IgnoreAnalyzer.Contains(prop.Name) && mapping.Properties.ContainsKey(prop.Name)) { string existingAnalyzer = mapping.Properties[prop.Name].Analyzer; if (propertyMapping.Analyzer != existingAnalyzer) { Logger.Warning($"Conflicting mapping analyzer for property '{propName}' detected. Using already mapped analyzer '{existingAnalyzer}'"); } propertyMapping.Analyzer = existingAnalyzer; } if (String.IsNullOrEmpty(propertyMapping.Type) || propertyMapping.Type != mappingType) { propertyMapping.Type = mappingType; } mapping.AddOrUpdateProperty(propName, propertyMapping); if (Logger.IsDebugEnabled()) { Logger.Debug($"Property mapping for '{propName}'"); Logger.Debug(propertyMapping.ToString()); } } // Filter out properties with missing type mapping.Properties = mapping.Properties .Where(p => p.Value.Type != null) .ToDictionary(d => d.Key, d => d.Value); if (!mapping.IsDirty) { Logger.Debug("No change in mapping"); return; } var jsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; var json = JsonConvert.SerializeObject(mapping, jsonSettings); var data = Encoding.UTF8.GetBytes(json); var uri = $"{_settings.Host}/{index}/_mapping/{indexType.GetTypeName()}"; if (Server.Info.Version.Major >= 7) { uri += "?include_type_name=true"; } Logger.Information("Update mapping:\n" + JToken.Parse(json).ToString(Formatting.Indented)); _httpClientHelper.Put(new Uri(uri), data); } catch (Exception ex) { Logger.Error($"Failed to update mapping: {ex.Message}", ex); } }
public void CreateAnalyzedMappingsIfNeeded(Type type, string language, string indexName = null) { Logger.Debug("Checking if analyzable mappings needs updating"); string json = null; string oldJson = null; IndexMapping mapping = null; try { if (String.IsNullOrWhiteSpace(indexName)) { indexName = _settings.GetDefaultIndexName(language); } // Get mappings from server mapping = _mapping.GetIndexMapping(typeof(IndexItem), language, indexName); // Ignore special mappings mapping.Properties.Remove(DefaultFields.AttachmentData); mapping.Properties.Remove(DefaultFields.BestBets); mapping.Properties.Remove(DefaultFields.DidYouMean); mapping.Properties.Remove(DefaultFields.Suggest); mapping.Properties.Remove(nameof(IndexItem.attachment)); var jsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; oldJson = JsonConvert.SerializeObject(mapping, jsonSettings); var indexableProperties = GetIndexableProperties(type, false); // Get well-known and Stemmed property-names List <string> allAnalyzableProperties = indexableProperties.Where(i => i.Analyzable) .Select(i => i.Name) .ToList(); allAnalyzableProperties.ForEach(p => { IndexMappingProperty propertyMapping = Language.GetPropertyMapping(language, typeof(string), true); mapping.AddOrUpdateProperty(p, propertyMapping); }); if (!mapping.IsDirty) { // No change, quit. Logger.Debug("No change"); return; } json = JsonConvert.SerializeObject(mapping, jsonSettings); var data = Encoding.UTF8.GetBytes(json); var uri = $"{_settings.Host}/{indexName}/_mapping/{typeof(IndexItem).GetTypeName()}"; if (Server.Info.Version.Major >= 7) { uri += "?include_type_name=true"; } Logger.Debug("Update mapping:\n" + JToken.Parse(json).ToString(Formatting.Indented)); _httpClientHelper.Put(new Uri(uri), data); } catch (Exception ex) { HandleMappingError(type, ex, json, oldJson, mapping); } }
public void UpdateMapping(Type type, Type indexType, string index, string language, bool optIn) { if (type.Name.EndsWith("Proxy")) { type = type.BaseType; } language = language ?? _settings.GetLanguage(index); var indexableProperties = GetIndexableProperties(type, optIn); var typeName = type?.Name; _logger.Information("IndexableProperties for " + typeName + ": " + String.Join(", ", indexableProperties.Select(p => p.Name))); // Get existing mapping IndexMapping mapping = _mapping.GetIndexMapping(indexType, null, index); // Ignore special mappings mapping.Properties.Remove(DefaultFields.AttachmentData); mapping.Properties.Remove(DefaultFields.BestBets); mapping.Properties.Remove(DefaultFields.DidYouMean); mapping.Properties.Remove(DefaultFields.Suggest); foreach (IndexableProperty prop in indexableProperties) { string propName = prop.Name; IndexMappingProperty propertyMapping = GetPropertyMapping(prop, language, mapping, out _); mapping.AddOrUpdateProperty(propName, propertyMapping); if (_logger.IsDebugEnabled()) { _logger.Debug($"Property mapping for '{propName}'"); _logger.Debug(propertyMapping.ToString()); } } // Filter out properties with missing type mapping.Properties = mapping.Properties .Where(p => p.Value.Type != null) .ToDictionary(d => d.Key, d => d.Value); if (!mapping.IsDirty) { _logger.Debug("No change in mapping"); return; } var jsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; var json = JsonConvert.SerializeObject(mapping, jsonSettings); var data = Encoding.UTF8.GetBytes(json); var uri = $"{_settings.Host}/{index}/_mapping/{indexType.GetTypeName()}"; if (_serverInfo.Version >= Constants.IncludeTypeNameAddedVersion) { uri += "?include_type_name=true"; } _logger.Information("Update mapping:\n" + JToken.Parse(json).ToString(Formatting.Indented)); _httpClientHelper.Put(new Uri(uri), data); }
public void UpdateMapping(Type type, Type indexType, string index, string language, bool optIn) { if (type.Name.EndsWith("Proxy")) { type = type.BaseType; } language = language ?? _settings.GetLanguage(index); // Get indexable properties (string, XhtmlString, [Searchable(true)]) var indexableProperties = type.GetIndexableProps(optIn) .Select(p => new { p.Name, Type = p.PropertyType, Analyzable = ((p.PropertyType == typeof(string) || p.PropertyType == typeof(string[])) && (p.GetCustomAttributes(typeof(StemAttribute)).Any() || WellKnownProperties.Analyze .Select(w => w.ToLower()) .Contains(p.Name.ToLower()))) || (p.PropertyType == typeof(XhtmlString) && p.GetCustomAttributes(typeof(ExcludeFromSearchAttribute), true).Length == 0) }) .ToList(); // Custom properties marked for stemming indexableProperties.AddRange(Conventions.Indexing.CustomProperties .Select(c => new { c.Name, c.Type, Analyzable = WellKnownProperties.Analyze.Select(w => w.ToLower()).Contains(c.Name.ToLower()) })); Logger.Information("IndexableProperties for " + type?.Name + ": " + String.Join(", ", indexableProperties.Select(p => p.Name))); // Get existing mapping IndexMapping mapping = Mapping.GetIndexMapping(indexType, null, index); try { foreach (var prop in indexableProperties) { string propName = prop.Name; IndexMappingProperty propertyMapping = mapping.Properties.ContainsKey(prop.Name) ? mapping.Properties[prop.Name] : Language.GetPropertyMapping(language, prop.Type, prop.Analyzable); string mappingType = Mapping.GetMappingTypeAsString(prop.Type); // If mapping with same name exists, use its type. // Different name/type combos is not allowed. if (mapping.Properties.ContainsKey(prop.Name)) { string existingType = mapping.Properties[prop.Name].Type; if (mappingType != existingType) { Logger.Warning($"Conflicting mapping type for property '{propName}' detected. Using already mapped type '{existingType}'"); } mappingType = existingType; } if (prop.Analyzable && language != null) { propertyMapping.Analyzer = Language.GetLanguageAnalyzer(language); } else if (language != null && mappingType == nameof(MappingType.Text).ToLower()) { propertyMapping.Analyzer = Language.GetSimpleLanguageAnalyzer(language); } // If mapping with different analyzer exists, use its analyzer. if (mapping.Properties.ContainsKey(prop.Name)) { string existingAnalyzer = mapping.Properties[prop.Name].Analyzer; if (propertyMapping.Analyzer != existingAnalyzer) { Logger.Warning($"Conflicting mapping analyzer for property '{propName}' detected. Using already mapped analyzer '{existingAnalyzer}'"); } propertyMapping.Analyzer = existingAnalyzer; } if (String.IsNullOrEmpty(propertyMapping.Type) || propertyMapping.Type != mappingType) { propertyMapping.Type = mappingType; } if (WellKnownProperties.ExcludeFromAll.Contains(propName)) { propertyMapping.IncludeInAll = false; } mapping.AddOrUpdateProperty(propName, propertyMapping); if (Logger.IsDebugEnabled()) { Logger.Debug($"Property mapping for '{propName}'"); Logger.Debug(propertyMapping.ToString()); } } // Filter out properties with missing type mapping.Properties = mapping.Properties .Where(p => p.Value.Type != null) .ToDictionary(d => d.Key, d => d.Value); if (!mapping.IsDirty) { Logger.Debug("No change in mapping"); return; } var jsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; string json = JsonConvert.SerializeObject(mapping, jsonSettings); byte[] data = Encoding.UTF8.GetBytes(json); string uri = $"{_settings.Host}/{index}/_mapping/{indexType.GetTypeName()}"; Logger.Information("Update mapping:\n" + JToken.Parse(json).ToString(Formatting.Indented)); HttpClientHelper.Put(new Uri(uri), data); } catch (Exception ex) { Logger.Error($"Failed to update mapping: {ex.Message}", ex); } }