public static PropertiesDescriptor <T> SetupDefaults <T>(this PropertiesDescriptor <T> pd) where T : class { var hasIdentity = typeof(IIdentity).IsAssignableFrom(typeof(T)); var hasDates = typeof(IHaveDates).IsAssignableFrom(typeof(T)); var hasCreatedDate = typeof(IHaveCreatedDate).IsAssignableFrom(typeof(T)); var supportsSoftDeletes = typeof(ISupportSoftDeletes).IsAssignableFrom(typeof(T)); if (hasIdentity) { pd.String(p => p.Name(d => (d as IIdentity).Id).IndexName("id").Index(FieldIndexOption.NotAnalyzed)); } if (supportsSoftDeletes) { pd.Boolean(p => p.Name(d => (d as ISupportSoftDeletes).IsDeleted).IndexName(SoftDeletesQueryBuilder.Fields.Deleted)); } if (hasCreatedDate) { pd.Date(p => p.Name(d => (d as IHaveCreatedDate).CreatedUtc).IndexName("created")); } if (hasDates) { pd.Date(p => p.Name(d => (d as IHaveDates).UpdatedUtc).IndexName("updated")); } return(pd); }
private void FromExamineType(PropertiesDescriptor <Document> descriptor, FieldDefinition field) { switch (field.Type.ToLowerInvariant()) { case "date": case "datetimeoffset": descriptor.Date(s => s.Name(field.Name)); break; case "double": descriptor.Number(s => s.Name(field.Name).Type(NumberType.Double)); break; case "float": descriptor.Number(s => s.Name(field.Name).Type(NumberType.Float)); break; case "long": descriptor.Number(s => s.Name(field.Name).Type(NumberType.Long)); break; case "int": case "number": descriptor.Number(s => s.Name(field.Name).Type(NumberType.Integer)); break; default: descriptor.Text(s => s.Name(field.Name).Analyzer(FromLuceneAnalyzer(Analyzer))); break; } }
public static PropertiesDescriptor <T> DateTimeOffset <T>(this PropertiesDescriptor <T> propertiesDescriptor, Func <DatePropertyDescriptor <T>, IDateProperty> selector) where T : class { // Validate parameters. if (propertiesDescriptor == null) { throw new ArgumentNullException(nameof(propertiesDescriptor)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } // Modify and return. return(propertiesDescriptor.Date(selector)); }
/// <summary> /// Obtient le mapping de champ Elastic pour une catégorie donnée. /// </summary> /// <param name="selector">Descripteur des propriétés.</param> /// <param name="field">Catégorie de champ.</param> /// <returns>Mapping de champ.</returns> /// <typeparam name="T">Type du document.</typeparam> public PropertiesDescriptor <T> AddField <T>(PropertiesDescriptor <T> selector, DocumentFieldDescriptor field) where T : class { var fieldName = field.FieldName; /* TODO Externaliser. */ switch (field.Category) { case SearchFieldCategory.Result: if (field.PropertyType == typeof(DateTime?)) { return(selector.Date(x => x .Name(fieldName) .Index(false) .Store(true))); } if (field.PropertyType == typeof(int?)) { return(selector.Number(x => x .Name(fieldName) .Type(NumberType.Integer) .Index(false) .Store(true))); } if (field.PropertyType == typeof(decimal?)) { return(selector.Number(x => x .Name(fieldName) .Type(NumberType.Double) .Index(false) .Store(true))); } return(selector.Text(x => x .Name(fieldName) .Index(false) .Store(true))); case SearchFieldCategory.Search: /* Champ de recherche textuelle full-text. */ return(selector.Text(x => x .Name(fieldName) .Index(true) .Store(false) .Analyzer("text_fr"))); case SearchFieldCategory.Security: /* Champ de filtrage de sécurité : listes de code. */ /* TODO : faire un mapping plus spécifique ? */ return(selector.Text(x => x .Name(fieldName) .Index(true) .Store(true) .Analyzer("text_fr"))); case SearchFieldCategory.Facet: /* Champ de facette. */ if (field.PropertyType == typeof(DateTime?)) { throw new ElasticException("Le type DateTime n'est pas supporté pour le champ de facette " + field.FieldName); } if (field.PropertyType == typeof(decimal?)) { return(selector.Number(x => x .Name(fieldName) .Index(true) .Store(false))); } return(selector.Keyword(x => x .Name(fieldName) .Index(true) .Store(false))); case SearchFieldCategory.ListFacet: return(selector.Text(x => x .Name(fieldName) .Index(true) .Store(false) .Analyzer("text_fr"))); case SearchFieldCategory.Sort: if (field.PropertyType == typeof(DateTime?)) { return(selector.Date(x => x .Name(fieldName) .Index(true) .Store(false))); } if (field.PropertyType == typeof(decimal?)) { return(selector.Number(x => x .Name(fieldName) .Index(true) .Store(false))); } return(selector.Keyword(x => x .Name(fieldName) .Index(true) .Store(false))); case SearchFieldCategory.Filter: /* Champ filtre. */ if (field.PropertyType == typeof(DateTime?)) { throw new ElasticException("Le type DateTime n'est pas supporté pour le champ de filtrage " + field.FieldName); } if (field.PropertyType == typeof(decimal?)) { return(selector.Number(x => x .Name(fieldName) .Index(true) .Store(false))); } return(selector.Keyword(x => x .Name(fieldName) .Index(true) .Store(false))); case SearchFieldCategory.Id: return(selector); default: throw new NotSupportedException("Category not supported : " + field.Category); } }
public static IPromise <IProperties> MapProperties(JToken node, PropertiesDescriptor <object> descriptor, PropertiesDescriptor <object> analyzers, List <string> interpretedFields, string path) { var properties = node.Children <JProperty>().ToList(); foreach (JProperty property in properties) { var name = property.Name; var fullPath = path.AppendSeparator(".") + name; var isInterpreted = interpretedFields.Contains(fullPath, StringComparer.OrdinalIgnoreCase); Func <PropertiesDescriptor <object>, IPromise <IProperties> > applyAnalyzerFields = field => isInterpreted ? analyzers : field; var tokenPrefix = string.Empty; var type = property.Value.SelectToken(SchemaHelper.Elements.Type)?.Value <string>(); var format = property.Value.SelectToken(SchemaHelper.Elements.Format)?.Value <string>(); if (string.IsNullOrEmpty(type)) { // Json schema validator should catch this throw new ArgumentNullException($"Elastic type is not provided"); } // Elastic nem kezel külön array-t, ezért ha így tartalmazza a schema az eleme típusát használjuk fel if (type == SchemaHelper.Types.Array) { tokenPrefix = $"{SchemaHelper.Elements.Items}."; type = property.Value.SelectToken($"{tokenPrefix}{SchemaHelper.Elements.Type}")?.Value <string>(); format = property.Value.SelectToken($"{tokenPrefix}{SchemaHelper.Elements.Format}")?.Value <string>(); } switch (type) { case SchemaHelper.Types.String: { descriptor.String(desc => desc .Name(name) .Fields(applyAnalyzerFields)); break; } case SchemaHelper.Types.Long: case SchemaHelper.Types.Integer: case SchemaHelper.Types.Short: case SchemaHelper.Types.Byte: case SchemaHelper.Types.Double: case SchemaHelper.Types.Float: { var numberType = (NumberType)Enum.Parse(typeof(NumberType), type, true); descriptor.Number(desc => desc .Name(name) .Type(numberType) .Fields(applyAnalyzerFields)); break; } case SchemaHelper.Types.Boolean: { descriptor.Boolean(desc => desc .Name(name) .Fields(applyAnalyzerFields)); break; } case SchemaHelper.Types.Date: { if (string.IsNullOrWhiteSpace(format)) { format = "strict_date_optional_time||epoch_millis"; } descriptor.Date(desc => desc .Name(name) .Format(format) .Fields(applyAnalyzerFields)); } break; case SchemaHelper.Types.Attachment: { descriptor.Attachment(desc => desc .Name(name) .FileField(d => d //ContentField .Store(true) .Fields(applyAnalyzerFields)) .ContentTypeField(d => d.Store(true)) .ContentLengthField(d => (d as NumberPropertyDescriptor <object>).Store(true)) .LanguageField(d => (d as StringPropertyDescriptor <object>).Store(true)) .KeywordsField(d => d.Store(true)) .AuthorField(d => d.Store(true)) .DateField(d => d.Store(true)) .TitleField(d => d.Store(true)) ); break; } case SchemaHelper.Types.Object: { descriptor.Object <object>(desc => desc .Name(name) .Properties(propDesc => MapProperties(property.Value.SelectToken($"{tokenPrefix}{SchemaHelper.Elements.Properties}"), propDesc, analyzers, interpretedFields, fullPath))); break; } default: { throw new NotImplementedException($"Elastic type '{type}' is not implemented"); } } } return(descriptor); }