Post data
editPost data
editThe low level client allows you to post a string
or byte[]
array directly. On top of this,
if you pass a collection of string
or object
they will be serialized using Elasticsearch’s special bulk/multi format.
Implicit Conversion
editEven though the argument for PostData on the low level client takes a PostData
,
You can rely on implicit conversion to abstract the notion of PostData for the most common two use cases:
-
A
string
-
A
byte[]
array
Let’s demonstrate each with some assertive examples
PostData fromString = @string; PostData fromByteArray = bytes; fromByteArray.WrittenBytes.Should().BeSameAs(bytes);
The Type
property is representative of the original type from which post data is constructed
fromString.Type.Should().Be(PostType.LiteralString); fromByteArray.Type.Should().Be(PostType.ByteArray);
and passing a PostData
instance to a method that accepts PostData
as an argument does not wrap it again
fromString = MethodThatAcceptsPostData(fromString); fromByteArray = MethodThatAcceptsPostData(fromByteArray); fromString.Type.Should().Be(PostType.LiteralString); fromByteArray.Type.Should().Be(PostType.ByteArray);
Other types of PostData
editYou can also pass the following objects directly to the low level client.
-
A Serializable
object
-
A collection of
object
as multi line json -
A collection of
string
as multi line json
Let’s demonstrate how to use the static helper on PostData
for these:
PostData fromObject = PostData.Serializable(@object); PostData fromListOfString = PostData.MultiJson(collectionOfStrings); PostData fromListOfObject = PostData.MultiJson(collectionOfObjects);
The Type
property is representative of the original type from which post data is constructed
fromListOfString.Type.Should().Be(PostType.EnumerableOfString); fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); fromObject.Type.Should().Be(PostType.Serializable);
and passing a PostData
instance to a method that accepts PostData
as an argument does not wrap it again
fromListOfString = MethodThatAcceptsPostData(fromListOfString); fromListOfObject = MethodThatAcceptsPostData(fromListOfObject); fromObject = MethodThatAcceptsPostData(fromObject); fromListOfString.Type.Should().Be(PostType.EnumerableOfString); fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); fromObject.Type.Should().Be(PostType.Serializable);
Each of the implicitly converted types behaves slightly differently.
For string
, the UTF-8 bytes are sent in the request and the WrittenBytes
property is assigned
the bytes
await Post(() => @string, writes: Utf8Bytes(@string), writtenBytesIsSet: true, settings: settings);
Similarly, for byte[]
, the bytes are sent verbatim and the WrittenBytes
property is assigned
the bytes
await Post(() => bytes, writes: bytes, writtenBytesIsSet: true, settings: settings);
On platforms that support ReadOnlyMemory<byte>
you can use PostData.ReadOnlyMemory
to pass this directly
await Post(() => PostData.ReadOnlyMemory(bytes.AsMemory()), writes: bytes, writtenBytesIsSet: false, settings: settings);
When passing a collection of string
, the client assumes that it’s a collection of valid serialized json,
so joins each with newline feeds, ensuring there is a trailing linefeed. As with string
and byte[]
,
the WrittenBytes
property is assigned the UTF-8 bytes of the collection of strings if DisableDirectStreaming
is set on ConnectionConfiguration
await Post(() => PostData.MultiJson(collectionOfStrings), writes: utf8BytesOfListOfStrings, writtenBytesIsSet: false, settings: settings);
When passing a collection of object
, the client assumes that it’s a collection of objects
that needs to be serialized individually to json and joined with newline feeds. As with the collection of strings, the client ensures that
there is a trailing linefeed.
await Post(() => PostData.MultiJson(collectionOfObjects), writes: utf8BytesOfCollectionOfObjects, writtenBytesIsSet: false, settings: settings);
In all other cases, Post data is serialized as is and WrittenBytes
is not assigned
await Post(() => PostData.Serializable(@object), writes: utf8ObjectBytes, writtenBytesIsSet: false, settings: settings);
If you want even more control over how your data is written to the stream consider PostData.StreamHandler
which allows you to inject your own writer routines
var streamHandler = PostData.StreamHandler(bytes, (b, s) => s.Write(b.AsSpan()), async (b, s, ctx) => await s.WriteAsync(b.AsMemory(), ctx) ); await Post(() => streamHandler, writes: bytes, writtenBytesIsSet: false, settings: settings);
Forcing WrittenBytes to be set
editIf you want to maintain a copy of the request that went out, you can set DisableDirectStreaming
on ConnectionConfiguration
.
In doing so, the serialized bytes are first written to a private MemoryStream
so that the client can get hold of the serialized bytes
settings = new ConnectionConfiguration().DisableDirectStreaming(); await Post(() => PostData.MultiJson(collectionOfObjects), writes: utf8BytesOfCollectionOfObjects, writtenBytesIsSet: true, settings: settings); await Post(() => PostData.MultiJson(collectionOfStrings), writes: utf8BytesOfListOfStrings, writtenBytesIsSet: true, settings: settings); await Post(() => PostData.ReadOnlyMemory(bytes.AsMemory()), writes: bytes, writtenBytesIsSet: true, settings: settings); await Post(() => streamHandler, writes: bytes, writtenBytesIsSet: true, settings: settings);
This behavior can also be observed when serializing a simple object using DisableDirectStreaming
enabled
await Post(() => PostData.Serializable(@object), writes: utf8ObjectBytes, writtenBytesIsSet: true, settings: settings);