diff --git a/src/Nest/Ingest/ProcessorFormatter.cs b/src/Nest/Ingest/ProcessorFormatter.cs index 3ad481b1b55..b127b45a464 100644 --- a/src/Nest/Ingest/ProcessorFormatter.cs +++ b/src/Nest/Ingest/ProcessorFormatter.cs @@ -46,7 +46,8 @@ internal class ProcessorFormatter : IJsonFormatter { "circle", 30 }, { "enrich", 31 }, { "csv", 32 }, - { "uri_parts", 33 } + { "uri_parts", 33 }, + { "fingerprint", 34 } }; public IProcessor Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) @@ -169,6 +170,9 @@ public IProcessor Deserialize(ref JsonReader reader, IJsonFormatterResolver form case 33: processor = Deserialize(ref reader, formatterResolver); break; + case 34: + processor = Deserialize(ref reader, formatterResolver); + break; } } else @@ -292,6 +296,9 @@ public void Serialize(ref JsonWriter writer, IProcessor value, IJsonFormatterRes case "uri_parts": Serialize(ref writer, value, formatterResolver); break; + case "fingerprint": + Serialize(ref writer, value, formatterResolver); + break; default: var formatter = DynamicObjectResolver.ExcludeNullCamelCase.GetFormatter(); formatter.Serialize(ref writer, value, formatterResolver); diff --git a/src/Nest/Ingest/Processors/FingerprintProcessor.cs b/src/Nest/Ingest/Processors/FingerprintProcessor.cs new file mode 100644 index 00000000000..9eeb7bbaaf6 --- /dev/null +++ b/src/Nest/Ingest/Processors/FingerprintProcessor.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq.Expressions; +using System.Runtime.Serialization; +using Elasticsearch.Net.Utf8Json; + +namespace Nest +{ + [InterfaceDataContract] + public interface IFingerprintProcessor : IProcessor + { + [DataMember(Name = "fields")] + Fields Fields { get; set; } + + [DataMember(Name = "ignore_missing")] + bool? IgnoreMissing { get; set; } + + [DataMember(Name = "method")] + string Method { get; set; } + + [DataMember(Name = "salt")] + string Salt { get; set; } + + [DataMember(Name = "target_field")] + Field TargetField { get; set; } + } + + public class FingerprintProcessor : ProcessorBase, IFingerprintProcessor + { + protected override string Name => "fingerprint"; + + /// + public Fields Fields { get; set; } + + /// + public bool? IgnoreMissing { get; set; } + + /// + public string Method { get; set; } + + /// + public string Salt { get; set; } + + /// + public Field TargetField { get; set; } + } + + /// + public class FingerprintProcessorDescriptor + : ProcessorDescriptorBase, IFingerprintProcessor>, IFingerprintProcessor + where T : class + { + protected override string Name => "fingerprint"; + + Fields IFingerprintProcessor.Fields { get; set; } + + string IFingerprintProcessor.Method { get; set; } + + string IFingerprintProcessor.Salt { get; set; } + + Field IFingerprintProcessor.TargetField { get; set; } + + bool? IFingerprintProcessor.IgnoreMissing { get; set; } + + /// + public FingerprintProcessorDescriptor Fields(Fields fields) => Assign(fields, (a, v) => a.Fields = v); + + /// + public FingerprintProcessorDescriptor Fields(Func, IPromise> selector) => + Assign(selector, (a, v) => a.Fields = v?.Invoke(new FieldsDescriptor())?.Value); + + /// + public FingerprintProcessorDescriptor IgnoreMissing(bool? ignoreMissing = true) => Assign(ignoreMissing, (a, v) => a.IgnoreMissing = v); + + /// + public FingerprintProcessorDescriptor Method(string method) => Assign(method, (a, v) => a.Method = v); + + /// + public FingerprintProcessorDescriptor Salt(string salt) => Assign(salt, (a, v) => a.Salt = v); + + /// + public FingerprintProcessorDescriptor TargetField(Field field) => Assign(field, (a, v) => a.TargetField = v); + + /// + public FingerprintProcessorDescriptor TargetField(Expression> objectPath) => + Assign(objectPath, (a, v) => a.TargetField = v); + } +} diff --git a/src/Nest/Ingest/ProcessorsDescriptor.cs b/src/Nest/Ingest/ProcessorsDescriptor.cs index 9793144d993..cdd0ea4ca00 100644 --- a/src/Nest/Ingest/ProcessorsDescriptor.cs +++ b/src/Nest/Ingest/ProcessorsDescriptor.cs @@ -181,5 +181,9 @@ public ProcessorsDescriptor Circle(Func, ICircle /// public ProcessorsDescriptor UriParts(Func, IUriPartsProcessor> selector) where T : class => Assign(selector, (a, v) => a.AddIfNotNull(v?.Invoke(new UriPartsProcessorDescriptor()))); + + /// + public ProcessorsDescriptor Fingerprint(Func, IFingerprintProcessor> selector) where T : class => + Assign(selector, (a, v) => a.AddIfNotNull(v?.Invoke(new FingerprintProcessorDescriptor()))); } } diff --git a/tests/Tests/Ingest/ProcessorAssertions.cs b/tests/Tests/Ingest/ProcessorAssertions.cs index eab82b93620..b844a86043a 100644 --- a/tests/Tests/Ingest/ProcessorAssertions.cs +++ b/tests/Tests/Ingest/ProcessorAssertions.cs @@ -716,5 +716,21 @@ public class UriParts : ProcessorAssertion public override object Json => new { field = "description", keep_original = true, remove_if_successful = true }; public override string Key => "uri_parts"; } + + [SkipVersion("<7.12.0", "Uses fingerprint processor which was introduced in 7.12.0")] + public class Fingerprint : ProcessorAssertion + { + public override Func>> Fluent => d => d + .Fingerprint(ud => ud + .Fields(p => p.Fields(f => f.Labels)) + .Method("MD5") + .Salt("ThisIsASalt!") + .TargetField(p => p.Description) + .IgnoreMissing()); + + public override IProcessor Initializer => new FingerprintProcessor { Fields = "labels", Method = "MD5", Salt = "ThisIsASalt!", TargetField = "description", IgnoreMissing = true }; + public override object Json => new { fields = new[] { "labels" }, method = "MD5", salt = "ThisIsASalt!", target_field = "description", ignore_missing = true }; + public override string Key => "fingerprint"; + } } }