예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
            }
        }