/** * A custom serializer would not know how to serialize `QueryContainer` or other NEST types that could appear as part of * the `_source` of a document, therefore a custom serializer needs to have a way to delegate serialization of NEST types * back to NEST's built-in serializer. */ /** * ==== JsonNetSerializer * * We ship a separate {nuget}/NEST.JsonNetSerializer[NEST.JsonNetSerializer] package that helps in composing a custom `SourceSerializer` * using `Json.NET`, that is smart enough to delegate the serialization of known NEST types back to the built-in * `RequestResponseSerializer`. This package is also useful if * * . You want to control how your documents and values are stored and retrieved from Elasticsearch using `Json.NET` * . You want to use `Newtonsoft.Json.Linq` types such as `JObject` within your documents * * The easiest way to hook this custom source serializer up is as follows */ public void DefaultJsonNetSerializer() { var pool = new SingleNodePool(new Uri("http://localhost:9200")); var connectionSettings = new ElasticsearchClientSettings(pool, sourceSerializer: JsonNetSerializer.Default); var client = new ElasticsearchClient(connectionSettings); }
/** * Hooking up the serializer is performed in the `ConnectionSettings` constructor */ public void TheNewContract() { var pool = new SingleNodePool(new Uri("http://localhost:9200")); var connectionSettings = new ElasticsearchClientSettings( pool, sourceSerializer: (builtin, settings) => new VanillaSerializer()); // <1> what the Func? var client = new ElasticsearchClient(connectionSettings); }
public void CanDeserialize() { var json = @"{ ""took"": 61, ""errors"": false, ""items"": [{ ""update"": { ""_index"": ""test"", ""_type"": ""_doc"", ""_id"": ""1"", ""_version"": 2, ""result"": ""updated"", ""_shards"": { ""total"": 2, ""successful"": 1, ""failed"": 0 }, ""_seq_no"": 3, ""_primary_term"": 1, ""get"": { ""_seq_no"": 3, ""_primary_term"": 1, ""found"": true, ""_source"": { ""field1"": ""value1"", ""field2"": ""value2"" } }, ""status"": 200 } }] }" ; var pool = new SingleNodePool(new Uri("http://localhost:9200")); var connection = new InMemoryConnection(Encoding.UTF8.GetBytes(json)); var settings = new ElasticsearchClientSettings(pool, connection); var client = new ElasticsearchClient(settings); var bulkResponse = client.Bulk(new BulkRequest()); bulkResponse.ShouldBeValid(); var item1 = bulkResponse.Items[0].Get; item1.SeqNo.Should().Be(3); item1.PrimaryTerm.Should().Be(1); item1.Found.Should().Be(true); var simpleObject = bulkResponse.Items[0].Get.Source.As <SimpleObject>(); simpleObject.Field1.Should().Be("value1"); simpleObject.Field2.Should().Be("value2"); }
static VerifySerializerTestBase() { var settings = new ElasticsearchClientSettings(); settings.ApplyDomainSettings(); var client = new ElasticsearchClient(settings); _requestResponseSerializer = client.RequestResponseSerializer; _settings = client.ElasticsearchClientSettings; }
/** * ==== Determining ingest capability * * In complex cluster configurations it can be easier to use a sniffing connection pool along with a node predicate to * filter out the nodes that have ingest capabilities. This allows you to customise the cluster and not have to reconfigure * the client. */ public void SniffingNodePool() { var pool = new SniffingNodePool(new [] //<1> list of cluster nodes { new Uri("http://node1:9200"), new Uri("http://node2:9200"), new Uri("http://node3:9200") }); var settings = new ElasticsearchClientSettings(pool).NodePredicate(n => n.HasFeature(IngestEnabled)); //<2> predicate to select only nodes with ingest capabilities var indexingClient = new ElasticsearchClient(settings); }
/** * ==== Custom indexing client * * Since Elasticsearch will automatically reroute ingest requests to ingest nodes, you don't have to specify or configure any routing * information. However, if you're doing heavy ingestion and have dedicated ingest nodes, it makes sense to send index requests to * these nodes directly, to avoid any extra hops in the cluster. * * The simplest way to achieve this is to create a dedicated "indexing" client instance, and use it for indexing requests. */ public void CustomClient() { var pool = new StaticNodePool(new [] //<1> list of ingest nodes { new Uri("http://ingestnode1:9200"), new Uri("http://ingestnode2:9200"), new Uri("http://ingestnode3:9200") }); var settings = new ElasticsearchClientSettings(pool); var indexingClient = new ElasticsearchClient(settings); }
protected string SerializeAndGetJsonString <T>(T data, ElasticsearchClientSettings settings) { var client = new ElasticsearchClient(settings); var serializer = client.RequestResponseSerializer; var stream = new MemoryStream(); serializer.Serialize(data, stream); stream.Position = 0; var reader = new StreamReader(stream); return(reader.ReadToEnd()); }
/** * `RelationName` uses the `DefaultTypeNameInferrer` to translate CLR types to a string representation. * * Explicit `TypeName` configuration does not affect how the default relation for the CLR type * is represented though */ [U] public void TypeNameExplicitConfigurationDoesNotAffectRelationName() { var settings = new ElasticsearchClientSettings() .DefaultMappingFor <Project>(m => m .IndexName("projects-and-commits") ); var resolver = new RelationNameResolver(settings); var relation = resolver.Resolve <Project>(); relation.Should().Be("project"); }
/** * `JsonNetSerializer`'s constructor takes several methods that allow you to control the `JsonSerializerSettings` and modify * the contract resolver from `Json.NET`. */ public void DefaultJsonNetSerializerFactoryMethods() { var pool = new SingleNodePool(new Uri("http://localhost:9200")); var connectionSettings = new ElasticsearchClientSettings(pool, sourceSerializer: (builtin, settings) => new JsonNetSerializer( builtin, settings, () => new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include }, resolver => resolver.NamingStrategy = new SnakeCaseNamingStrategy() )); var client = new ElasticsearchClient(connectionSettings); }
public async Task BulkRequestWithDeleteOperations_ObjectInitializer_SerializesCorrectly() { var settings = new ElasticsearchClientSettings(); settings.DefaultMappingFor <Inferrable>(m => m.IdProperty(p => p.Name).RoutingProperty(r => r.Name).IndexName("test-index")); var ms = new MemoryStream(); var request = new BulkRequest("index-from-request") { Operations = new BulkOperationsCollection { new BulkDeleteOperation("123"), new BulkDeleteOperation("123") { Routing = "ConfiguredRoute", Index = "configured-index", RequireAlias = false, Version = 1, VersionType = VersionType.External }, new BulkDeleteOperation <Inferrable>(Inferrable.Instance), new BulkDeleteOperation <Inferrable>(Inferrable.Instance) { Id = "OverriddenId", Routing = "OverriddenRoute", Index = "overridden-index", IfPrimaryTerm = 100, IfSequenceNumber = 10, RequireAlias = false, } } }; await request.SerializeAsync(ms, settings); ms.Position = 0; var reader = new StreamReader(ms); var ndjson = reader.ReadToEnd(); await Verifier.Verify(ndjson, _verifySettings); ms = new MemoryStream(); request.Serialize(ms, settings); ms.Position = 0; reader = new StreamReader(ms); ndjson = reader.ReadToEnd(); await Verifier.Verify(ndjson, _verifySettings); }
protected InstanceSerializerTestBase(ElasticsearchClientSettings settings, bool applyDomainSettings = false) { if (applyDomainSettings) { settings.ApplyDomainSettings(); } var client = new ElasticsearchClient(settings); _requestResponseSerializer = client.RequestResponseSerializer; _sourceSerializer = client.SourceSerializer; _settings = client.ElasticsearchClientSettings; }
public async Task BulkRequestWithCreateOperations_Descriptor_SerializesCorrectly() { var settings = new ElasticsearchClientSettings(); settings.DefaultMappingFor <Inferrable>(m => m.IdProperty(p => p.Name).RoutingProperty(r => r.Name).IndexName("test-index")); var ms = new MemoryStream(); var fluentRequest = new BulkRequestDescriptor(b => b .Index("index-from-request") .Create(Inferrable.Instance) .Create(Inferrable.Instance, i => i .Id("OverriddenId") .Routing("OverriddenRoute") .Index("overridden-index") .Pipeline("my-pipeline") .RequireAlias(false) .Version(1) .VersionType(VersionType.External) .DynamicTemplates(d => d.Add("t1", "v1"))) .Create(NonInferrable.Instance) .Create(NonInferrable.Instance, "configured-index") .Create(NonInferrable.Instance, i => i .Id("ConfiguredId") .Routing("ConfiguredRoute") .Index("configured-index") .IfPrimaryTerm(100) .IfSequenceNumber(10) .Pipeline("my-pipeline") .RequireAlias(false) .DynamicTemplates(d => d.Add("t1", "v1")))); await fluentRequest.SerializeAsync(ms, settings); ms.Position = 0; var reader = new StreamReader(ms); var ndjson = reader.ReadToEnd(); await Verifier.Verify(ndjson, _verifySettings); ms = new MemoryStream(); fluentRequest.Serialize(ms, settings); ms.Position = 0; reader = new StreamReader(ms); ndjson = reader.ReadToEnd(); await Verifier.Verify(ndjson, _verifySettings); }
public static ElasticsearchClientSettings CreateConnectionSettings( object response, int statusCode = 200, Func <ElasticsearchClientSettings, ElasticsearchClientSettings> modifySettings = null, string contentType = RequestData.MimeType, Exception exception = null, Serializer serializer = null ) { serializer ??= TestClient.Default.RequestResponseSerializer; byte[] responseBytes; switch (response) { case string s: responseBytes = Encoding.UTF8.GetBytes(s); break; case byte[] b: responseBytes = b; break; default: { responseBytes = contentType == RequestData.MimeType ? serializer.SerializeToBytes(response, TestClient.Default.ElasticsearchClientSettings.MemoryStreamFactory) : Encoding.UTF8.GetBytes(response.ToString()); break; } } var headers = new Dictionary <string, IEnumerable <string> > { { "x-elastic-product", new[] { "Elasticsearch" } } }; var connection = new InMemoryConnection(responseBytes, statusCode, exception, contentType, headers); var nodePool = new SingleNodePool(new Uri("http://localhost:9200")); var defaultSettings = new ElasticsearchClientSettings(nodePool, connection) .DefaultIndex("default-index"); var settings = modifySettings != null?modifySettings(defaultSettings) : defaultSettings; return(settings); }
/** * Hooking up the serializer and using it is as follows */ [U] public void UsingJsonNetSerializer() { var pool = new SingleNodePool(new Uri("http://localhost:9200")); var connectionSettings = new ElasticsearchClientSettings( pool, connection: new InMemoryConnection(), // <1> an _in-memory_ connection is used here for example purposes. In your production application, you would use an `ITransportClient` implementation that actually sends a request. sourceSerializer: (builtin, settings) => new MyFirstCustomJsonNetSerializer(builtin, settings)) .DefaultIndex("my-index"); //hide connectionSettings.DisableDirectStreaming(); var client = new ElasticsearchClient(connectionSettings); /** Now, if we index an instance of our document type */ var document = new MyDocument { Id = 1, Name = "My first document", OwnerId = 2 }; var indexResponse = client.Index(document, d => { }); /** it serializes to */ //json var expected = new { id = 1, name = "My first document", file_path = (string)null, owner_id = 2, sub_documents = (object)null }; /** * which adheres to the conventions of our configured `MyCustomJsonNetSerializer` serializer. */ // hide Expect(expected, preserveNullInExpected: true).FromRequest(indexResponse); }
/** * [[relation-names]] * [float] * === Relation names * * Prior to Elasticsearch 6.x you could have multiple types per index. They acted as a discrimatory column but were often * confused with tables. The fact that the mapping API's treated them as seperate entities did not help. * * The general guideline has always been to use a single type per index. Starting from 6.x this is also enforced. * Some features still need to store multiple types in a single index such as Parent/Child join relations. * * Both `Parent` and `Child` will need to have resolve to the same typename to be indexed into the same index. * * Therefore in 6.x we need a different type that translates a CLR type to a join relation. This can be configured seperately * using `.RelationName()` */ [U] public void RelationNameConfiguration() { var settings = new ElasticsearchClientSettings() .DefaultMappingFor <CommitActivity>(m => m .IndexName("projects-and-commits") .RelationName("commits") ) .DefaultMappingFor <Project>(m => m .IndexName("projects-and-commits") .RelationName("projects") ); var resolver = new RelationNameResolver(settings); var relation = resolver.Resolve <Project>(); relation.Should().Be("projects"); relation = resolver.Resolve <CommitActivity>(); relation.Should().Be("commits"); }
public static ElasticsearchClientSettings ApplyDomainSettings(this ElasticsearchClientSettings settings) => settings .Authentication(new BasicAuthentication("elastic", "password")) .DefaultIndex("default-index") .DefaultMappingFor <Project>(map => map .IndexName(TestValueHelper.ProjectsIndex) .IdProperty(p => p.Name) .RelationName("project")) .DefaultMappingFor <CommitActivity>(map => map .IndexName(TestValueHelper.ProjectsIndex) .RelationName("commits") ) .DefaultMappingFor <Developer>(map => map .IndexName("devs") .Ignore(p => p.PrivateValue) .PropertyName(p => p.OnlineHandle, "nickname") ) .DefaultMappingFor <ProjectPercolation>(map => map .IndexName("queries") );
protected virtual ElasticsearchClientSettings ConnectionSettings(ElasticsearchClientSettings s) => s;
protected virtual ElasticsearchClientSettings Authenticate(ElasticsearchClientSettings s) => s .Authentication(new BasicAuthentication(ClusterAuthentication.Admin.Username, ClusterAuthentication.Admin.Password));
public async Task BulkRequestWithUpdateOperations_ObjectInitializer_SerializesCorrectly() { var settings = new ElasticsearchClientSettings(); settings.DefaultMappingFor <Inferrable>(m => m.IdProperty(p => p.Name).RoutingProperty(r => r.Name).IndexName("test-index")); var ms = new MemoryStream(); var request = new BulkRequest("index-from-request") { Operations = new BulkOperationsCollection { BulkUpdateOperationFactory.WithScript("123", "test-index", new StoredScriptId("my-script-id") { Params = new Dictionary <string, object> { { "param1", "paramvalue1" } } }), BulkUpdateOperationFactory.WithScript("123", new InlineScript("ctx._source.counter += params.param1") { Language = ScriptLanguage.Painless, Params = new Dictionary <string, object> { { "param1", 1 } }, Options = new Dictionary <string, string> { { "option1", "optionvalue1" } } }), BulkUpdateOperationFactory.WithScript("123", new InlineScript("ctx._source.counter += params.param1") { Language = ScriptLanguage.Painless, Params = new Dictionary <string, object> { { "param1", 1 } }, Options = new Dictionary <string, string> { { "option1", "optionvalue1" } } }, Inferrable.Instance), BulkUpdateOperationFactory.WithScript("123", "configured-index", new InlineScript("ctx._source.counter += params.param1") { Language = ScriptLanguage.Painless, Params = new Dictionary <string, object> { { "param1", 1 } }, Options = new Dictionary <string, string> { { "option1", "optionvalue1" } } }, Inferrable.Instance), // TODO - Partial // TODO - Full operation } }; await request.SerializeAsync(ms, settings); ms.Position = 0; var reader = new StreamReader(ms); var ndjson = reader.ReadToEnd(); await Verifier.Verify(ndjson, _verifySettings); ms = new MemoryStream(); request.Serialize(ms, settings); ms.Position = 0; reader = new StreamReader(ms); ndjson = reader.ReadToEnd(); await Verifier.Verify(ndjson, _verifySettings); }
protected virtual ElasticsearchClientSettings ConnectionSettings(ElasticsearchClientSettings s) => s .ServerCertificateValidationCallback(CertificateValidations.AllowAll);