From f554f45d5428d85bf88d13828c555f474e653652 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 11 Feb 2016 12:48:04 +1100 Subject: [PATCH 01/18] Fix failing exception integration tests --- src/Tests/ClientConcepts/Exceptions/ExceptionTests.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Tests/ClientConcepts/Exceptions/ExceptionTests.cs b/src/Tests/ClientConcepts/Exceptions/ExceptionTests.cs index 4a675266aaf..5462ab64881 100644 --- a/src/Tests/ClientConcepts/Exceptions/ExceptionTests.cs +++ b/src/Tests/ClientConcepts/Exceptions/ExceptionTests.cs @@ -45,7 +45,12 @@ public void ClientTestWhenThrowExceptionsEnabled() var client = new ElasticClient(settings); var exception = Assert.Throws(() => client.RootNodeInfo()); var inner = exception.InnerException; +#if DOTNETCORE + // HttpClient does not throw on "known error" status codes (i.e. 404) thus OriginalException should not be set + inner.Should().BeNull(); +#else inner.Should().NotBeNull(); +#endif } [I] @@ -70,7 +75,12 @@ public void ClientTestWhenThrowExceptionsDisabled() var settings = new ConnectionSettings(new Uri("http://doesntexist:9200")); var client = new ElasticClient(settings); var response = client.RootNodeInfo(); +#if DOTNETCORE + // HttpClient does not throw on "known error" status codes (i.e. 404) thus OriginalException should not be set + response.CallDetails.OriginalException.Should().BeNull(); +#else response.CallDetails.OriginalException.Should().NotBeNull(); +#endif response.CallDetails.ServerError.Should().BeNull(); } } From 215afc55fe5df2cba2e0237943a2385144af8f5e Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 11 Feb 2016 20:11:42 +1100 Subject: [PATCH 02/18] Render nested types that do not contain test methods into documentation --- .../Files/CSharpDocumentationFile.cs | 51 ++++++++++++---- .../Documentation/Files/DocumentationFile.cs | 6 +- .../Walkers/CodeWithDocumentationWalker.cs | 60 +++++++++++-------- .../Walkers/DocumentationFileWalker.cs | 30 +++++++--- 4 files changed, 99 insertions(+), 48 deletions(-) diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index b530a67a31f..47487b5fe03 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -13,28 +13,59 @@ public class CSharpDocumentationFile : DocumentationFile { internal CSharpDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } - private string RenderBlocksToDocumentation(IEnumerable blocks, StringBuilder builder = null) + private string RenderBlocksToDocumentation(IEnumerable blocks) + { + var builder = new StringBuilder(); + var lastBlockWasCodeBlock = false; + + RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock); + if (lastBlockWasCodeBlock) builder.AppendLine("----"); + + RenderFooter(builder); + + return builder.ToString(); + } + + private void RenderFooter(StringBuilder builder) + { + builder.AppendLine(":ref: http://www.elastic.co/guide/elasticsearch/reference/current"); + } + + private void RenderBlocksToDocumentation(IEnumerable blocks, StringBuilder builder, ref bool lastBlockWasCodeBlock) { - var sb = builder ?? new StringBuilder(); foreach (var block in blocks) { if (block is TextBlock) { - sb.AppendLine(block.Value); + if (lastBlockWasCodeBlock) + { + lastBlockWasCodeBlock = false; + builder.AppendLine("----"); + } + + builder.AppendLine(block.Value); } else if (block is CodeBlock) { - sb.AppendLine("[source, csharp]"); - sb.AppendLine("----"); - sb.AppendLine(block.Value); - sb.AppendLine("----"); + if (!lastBlockWasCodeBlock) + { + builder.AppendLine("[source, csharp]"); + builder.AppendLine("----"); + } + else + { + builder.AppendLine(); + } + + builder.AppendLine(block.Value); + lastBlockWasCodeBlock = true; } else if (block is CombinedBlock) { - RenderBlocksToDocumentation(MergeAdjacentCodeBlocks(((CombinedBlock)block).Blocks), sb); + var mergedBlocks = MergeAdjacentCodeBlocks(((CombinedBlock)block).Blocks); + RenderBlocksToDocumentation(mergedBlocks, builder, ref lastBlockWasCodeBlock); } } - return sb.ToString(); } private List MergeAdjacentCodeBlocks(IEnumerable unmergedBlocks) @@ -58,7 +89,7 @@ private List MergeAdjacentCodeBlocks(IEnumerable(); collapseCodeBlocks.Add(b.Value); diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs index 4d8faf0aa90..6831fb5b779 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs @@ -37,10 +37,10 @@ public static DocumentationFile Load(FileInfo fileLocation) protected virtual FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; - var testInDocumenationFolder = Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "") + ".asciidoc"; + var testInDocumentationFolder = Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "") + ".asciidoc"; - var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, testInDocumenationFolder)); - var fileInfo = new FileInfo(documenationTargetPath); + var documentationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, testInDocumentationFolder)); + var fileInfo = new FileInfo(documentationTargetPath); if (fileInfo.Directory != null) Directory.CreateDirectory(fileInfo.Directory.FullName); return fileInfo; diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs index ca8936e189e..ab1e6445d0d 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs @@ -30,7 +30,7 @@ class CodeWithDocumentationWalker : CSharpSyntaxWalker /// We want to support inlining /** */ documentations because its super handy /// to document fluent code, what ensues is total hackery /// - /// + /// the depth of the class /// line number used for sorting public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null) : base(SyntaxWalkerDepth.StructuredTrivia) { @@ -51,14 +51,8 @@ public override void Visit(SyntaxNode node) _code = Regex.Replace(_code, $"\t{{{repeatedTabs},}}", match => match.Value.Substring(repeatedTabs)); var nodeLine = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var line = _lineNumberOverride ?? nodeLine; - - var codeBlocks = Regex.Split(_code, @"\/\*\*.*?\*\/", RegexOptions.Singleline) - .Select(b => b.TrimStart('\r', '\n').TrimEnd('\r', '\n', '\t')) - .Where(b => !string.IsNullOrEmpty(b) && b != ";") - .Select(b=>new CodeBlock(b, line)) - .ToList(); + var codeBlocks = ParseCodeBlocks(_code, line); base.Visit(node); @@ -79,20 +73,15 @@ public override void VisitBlock(BlockSyntax node) _firstVisit = false; foreach (var statement in node.Statements) { - var leadingTabs = new string('\t', 3 + ClassDepth); + var repeatedTabs = 3 + ClassDepth; SyntaxNode formattedStatement = statement; - _code = formattedStatement.WithoutLeadingTrivia().WithTrailingTrivia().ToFullString().Replace(leadingTabs, string.Empty); + _code = formattedStatement.WithoutLeadingTrivia().WithTrailingTrivia().ToFullString(); + _code = Regex.Replace(_code, $"\t{{{repeatedTabs},}}", match => match.Value.Substring(repeatedTabs)); var nodeLine = formattedStatement.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var line = _lineNumberOverride ?? nodeLine; - - var codeBlocks = Regex.Split(_code, @"\/\*\*.*?\*\/", RegexOptions.Singleline) - .Select(b => b.TrimStart('\r', '\n').TrimEnd('\r', '\n', '\t')) - .Where(b => !string.IsNullOrEmpty(b) && b != ";") - .Select(b => new CodeBlock(b, line)) - .ToList(); + var codeBlocks = ParseCodeBlocks(_code, line); this.Blocks.AddRange(codeBlocks); } @@ -101,19 +90,38 @@ public override void VisitBlock(BlockSyntax node) } } - public override void VisitXmlText(XmlTextSyntax node) + public override void VisitTrivia(SyntaxTrivia trivia) { - var nodeLine = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var line = _lineNumberOverride ?? nodeLine; - var text = node.TextTokens - .Where(n => n.Kind() == SyntaxKind.XmlTextLiteralToken) - .Aggregate(new StringBuilder(), (a, t) => a.AppendLine(t.Text.TrimStart()), a => a.ToString()); + if (trivia.Kind() != SyntaxKind.MultiLineDocumentationCommentTrivia) + { + base.VisitTrivia(trivia); + return; + } - this.TextBlocks.Add(new TextBlock(text, line)); + var tokens = trivia.ToFullString().TrimStart('/', '*').TrimEnd('*', '/').Split('\n'); + var builder = new StringBuilder(); - base.VisitXmlText(node); - } + foreach (var token in tokens) + { + var decodedToken = System.Net.WebUtility.HtmlDecode(token.TrimStart().TrimStart('*').TrimStart()); + builder.AppendLine(decodedToken); + } + var text = builder.ToString(); + var line = _firstVisit + ? trivia.SyntaxTree.GetLineSpan(trivia.Span).StartLinePosition.Line + : _lineNumberOverride.GetValueOrDefault(0); + this.Blocks.Add(new TextBlock(text, line)); + } + + private List ParseCodeBlocks(string code, int line) + { + return Regex.Split(code, @"\/\*\*.*?\*\/", RegexOptions.Singleline) + .Select(b => b.TrimStart('\r', '\n').TrimEnd('\r', '\n', '\t')) + .Where(b => !string.IsNullOrEmpty(b) && b != ";") + .Select(b => new CodeBlock(b, line)) + .ToList(); + } } } diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index 6ed9d53a679..3cfbf57998d 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis.Text; using Nest.Litterateur.Documentation.Blocks; namespace Nest.Litterateur.Walkers @@ -26,15 +28,27 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) if (ClassDepth == 1) { base.VisitClassDeclaration(node); - } - // are we dealing with a simple nested POCO? + } else if (node.ChildNodes().All(childNode => childNode is PropertyDeclarationSyntax || childNode is AttributeListSyntax)) - { + { + // simple nested POCO var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var walker = new CodeWithDocumentationWalker(ClassDepth - 2, line); walker.Visit(node); this.Blocks.AddRange(walker.Blocks); } + else + { + var methods = node.ChildNodes().OfType(); + if (!methods.Any(m => m.AttributeLists.SelectMany(a => a.Attributes).Any())) + { + // nested class with methods that are not unit or integration tests e.g. example PropertyVisitor + var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; + var walker = new CodeWithDocumentationWalker(ClassDepth - 2, line); + walker.Visit(node); + this.Blocks.AddRange(walker.Blocks); + } + } --ClassDepth; } @@ -131,23 +145,21 @@ public override void VisitTrivia(SyntaxTrivia trivia) } this.InsideMultiLineDocumentation = true; - this.CreateTextBlocksFromTrivia(trivia); - this.InsideMultiLineDocumentation = false; - } - private void CreateTextBlocksFromTrivia(SyntaxTrivia trivia) - { var tokens = trivia.ToFullString().TrimStart('/', '*').TrimEnd('*', '/').Split('\n'); var builder = new StringBuilder(); + foreach (var token in tokens) { - var decodedToken = System.Net.WebUtility.HtmlDecode(token.Trim().Trim('*').Trim()); + var decodedToken = System.Net.WebUtility.HtmlDecode(token.TrimStart().TrimStart('*').TrimStart()); builder.AppendLine(decodedToken); } var text = builder.ToString(); var line = trivia.SyntaxTree.GetLineSpan(trivia.Span).StartLinePosition.Line; this.Blocks.Add(new TextBlock(text, line)); + + this.InsideMultiLineDocumentation = false; } } } From a9954bdbd30d539e5ac69aec09b483960d3e7838 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 11 Feb 2016 20:12:51 +1100 Subject: [PATCH 03/18] Improve documentation wording --- .../HighLevel/Inferrence/DocumentPaths.doc.cs | 13 +- .../Inferrence/FieldInference.doc.cs | 121 +++++++++--------- .../HighLevel/Inferrence/IdsInference.doc.cs | 24 ++-- .../Inferrence/PropertyInference.doc.cs | 20 ++- .../HighLevel/Mapping/AutoMap.doc.cs | 91 ++++++------- .../ClientConcepts/LowLevel/Lifetimes.doc.cs | 78 +++++------ 6 files changed, 187 insertions(+), 160 deletions(-) diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs index 8b770364865..553e174dbcc 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs @@ -7,13 +7,14 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class DocumentPaths { - /** # DocumentPaths + /** = DocumentPaths + * * Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes * and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path * to your document more succintly */ - /** Manually newing */ + /** == Creating new instances */ [U] public void FromId() { /** here we create a new document path based on Project with the id 1 */ @@ -36,12 +37,14 @@ [U] public void FromId() Expect(1).WhenSerializing(path.Id); } - //** if you have an instance of your document you can use it as well generate document paths */ + /** == Creating from a document type instance + * if you have an instance of your document you can use it as well generate document paths + */ [U] public void FromObject() { var project = new Project { Name = "hello-world" }; - /** here we create a new document path based on a Project */ + /** here we create a new document path based on the instance of `Project`, project */ IDocumentPath path = new DocumentPath(project); Expect("project").WhenSerializing(path.Index); Expect("project").WhenSerializing(path.Type); @@ -72,7 +75,7 @@ [U] public void UsingWithRequests() request = new IndexRequest(project) { }; /** when comparing with the full blown constructor and passing document manually - * DocumentPath<T>'s benefits become apparent. + * `DocumentPath`'s benefits become apparent. */ request = new IndexRequest(IndexName.From(), TypeName.From(), 2) { diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs index 7407e83eacf..bd5b9a4804a 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs @@ -19,12 +19,12 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FieldInferrence { - /** # Strongly typed field access + /** = Strongly typed field access * * Several places in the elasticsearch API expect the path to a field from your original source document as a string. * NEST allows you to use C# expressions to strongly type these field path strings. * - * These expressions are assigned to a type called `Field` and there are several ways to create a instance of that type + * These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: */ /** Using the constructor directly is possible but rather involved */ @@ -42,7 +42,7 @@ public void UsingConstructors() .WhenSerializing(fieldString); } - /** Therefore you can also implicitly convert strings and expressions to Field's */ + /** Therefore you can also implicitly convert strings and expressions to `Field`s */ [U] public void ImplicitConversion() { @@ -57,7 +57,7 @@ public void ImplicitConversion() .WhenSerializing(fieldString); } - /** to ease creating Field's from expressions there is a static Property class you can use */ + /** to ease creating `Field`s from expressions there is a static Property class you can use */ [U] public void UsingStaticPropertyField() { @@ -66,8 +66,8 @@ public void UsingStaticPropertyField() /** but for expressions this is still rather involved */ var fieldExpression = Infer.Field(p => p.Name); - /** Using static imports in c# 6 this can be even shortened: - using static Nest.Static; + /** this can be even shortened even further using static imports in c# 6 i.e. + `using static Nest.Static;` */ fieldExpression = Field(p => p.Name); /** Now this is much much terser then our first example using the constructor! */ @@ -77,11 +77,11 @@ public void UsingStaticPropertyField() .WhenSerializing(fieldExpression); } - /** By default NEST will camelCase all the field names to be more javascripty */ + /** By default, NEST will camel-case all field names to be more _javascript-y_ */ [U] public void DefaultFieldNameInferrer() { - /** using DefaultFieldNameInferrer() on ConnectionSettings you can change this behavior */ + /** using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior */ var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); @@ -94,32 +94,36 @@ public void DefaultFieldNameInferrer() setup.Expect("Name").WhenSerializing(Field(p => p.Name)); } - /** Complex field name expressions */ - + /** == Complex field name expressions */ [U] public void ComplexFieldNameExpressions() { - /** You can follow your property expression to any depth, here we are traversing to the LeadDeveloper's (Person) FirstName */ + /** You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName */ Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); - /** When dealing with collection index access is ingnored allowing you to traverse into properties of collections */ + + /** When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections */ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); - /** Similarly .First() also works, remember these are expressions and not actual code that will be executed */ + + /** Similarly, LINQ's `.First()` method also works + * NOTE: remember these are expressions and not actual code that will be executed */ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); - /** When we see an indexer on a dictionary we assume they describe property names */ + /** An indexer on a dictionary is assumed to describe a property name */ Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); - /** A cool feature here is that we'll evaluate variables passed to these indexers */ + /** A cool feature here is that we'll evaluate variables passed to an indexer */ var variable = "var"; Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); - - /** If you are using elasticearch's multifield mapping (you really should!) these "virtual" sub fields - * do not always map back on to your POCO, by calling .Suffix() you describe the sub fields that do not live in your c# objects + /** :multifieldlink: https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html + * If you are using elasticearch's {multifieldlink}[multi_fields], which you really should as they allow + * you to analyze a string in a number of different ways, these _"virtual"_ sub fields + * do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that + * should be mapped. */ Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); @@ -129,11 +133,10 @@ public void ComplexFieldNameExpressions() Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); /** - * You can even chain them to any depth! + * You can even chain `.Suffix()` calls to any depth! */ Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); - /** Variables passed to suffix will be evaluated as well */ var suffix = "unanalyzed"; Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); @@ -141,13 +144,13 @@ public void ComplexFieldNameExpressions() } /** - * Suffixes can be appended to expressions. This is useful in cases where you want to apply the same suffix - * to a list of fields + * Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix + * to a list of fields. */ [U] public void AppendingSuffixToExpressions() { - /** */ + /** Here we have a list of expressions */ var expressions = new List>> { p => p.Name, @@ -156,7 +159,7 @@ public void AppendingSuffixToExpressions() p => p.LeadDeveloper.FirstName }; - /** append the suffix "raw" to each expression */ + /** and we want to append the suffix "raw" to each */ var fieldExpressions = expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); @@ -166,7 +169,7 @@ public void AppendingSuffixToExpressions() Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); } - /** Annotations + /** == Annotations * * When using NEST's property attributes you can specify a new name for the properties */ @@ -183,13 +186,15 @@ public void BuiltInAnnotiatons() /** * Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. - * Here we ask the default JsonNetSerializer and it takes JsonProperty into account + * Here we ask the default `JsonNetSerializer` to resolve a property name and it takes + * the `JsonPropertyAttribute` into account */ public class SerializerSpecific { [JsonProperty("nameInJson")] public string Name { get; set; } } + [U] public void SerializerSpecificAnnotations() { @@ -197,7 +202,8 @@ public void SerializerSpecificAnnotations() } /** - * If both are specified NEST takes precedence though + * If both a NEST property attribute and a serializer specific attribute are present on a property, + * NEST takes precedence */ public class Both { @@ -215,16 +221,14 @@ public void NestAttributeTakesPrecedence() }).WhenSerializing(new Both { Name = "Martijn Laarman" }); } - class A { public C C { get; set; } } - class B { public C C { get; set; } } - class C - { - public string Name { get; set; } - } /** - * Resolving field names is cached but this is per connection settings + * Resolution of field names is cached per connection settings instance. To demonstrate, + * take the following simple POCOs */ + class A { public C C { get; set; } } + class B { public C C { get; set; } } + class C { public string Name { get; set; } } [U] public void ExpressionsAreCachedButSeeDifferentTypes() @@ -269,49 +273,43 @@ public void ExpressionsAreCachedButSeeDifferentTypes() } /** - * To wrap up lets showcase the precedence that field names are inferred - * 1. A hard rename of the property on connection settings using Rename() - * 2. A NEST property mapping - * 3. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. - * 4. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases + * To wrap up, the precedence in which field names are inferred is: + * + * . A hard rename of the property on connection settings using `.Rename()` + * . A NEST property mapping + * . Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. + * . Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases * - * In the following example we have a class where each case wins + * The following example class will demonstrate this precedence */ - class Precedence { - /** - * Eventhough this property has a NEST property mapping and a JsonProperty attribute - * We are going to provide a hard rename for it on ConnectionSettings later that should win. - */ + // Even though this property has a NEST property mapping and a JsonProperty attribute, + // We are going to provide a hard rename for it on ConnectionSettings later that should win. [String(Name = "renamedIgnoresNest")] [JsonProperty("renamedIgnoresJsonProperty")] public string RenamedOnConnectionSettings { get; set; } - /** - * This property has both a NEST attribute and a JsonProperty, NEST should win. - */ + // This property has both a NEST attribute and a JsonProperty, NEST should win. [String(Name = "nestAtt")] [JsonProperty("jsonProp")] public string NestAttribute { get; set; } - /** We should take the json property into account by itself */ + // We should take the json property into account by itself [JsonProperty("jsonProp")] public string JsonProperty { get; set; } - /** This property we are going to special case in our custom serializer to resolve to `ask` */ + // This property we are going to special case in our custom serializer to resolve to ask [JsonProperty("dontaskme")] public string AskSerializer { get; set; } - /** We are going to register a DefaultFieldNameInferrer on ConnectionSettings - * that will uppercase all properties. - */ + // We are going to register a DefaultFieldNameInferrer on ConnectionSettings + // that will uppercase all properties. public string DefaultFieldNameInferrer { get; set; } - } /** - * Here we create a custom converter that renames any property named `AskSerializer` to `ask` + * Here we create a custom serializer that renames any property named `AskSerializer` to `ask` */ class CustomSerializer : JsonNetSerializer { @@ -319,20 +317,23 @@ public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) { - if (memberInfo.Name == "AskSerializer") return new PropertyMapping { Name = "ask" }; - return base.CreatePropertyMapping(memberInfo); + return memberInfo.Name == nameof(Precedence.AskSerializer) + ? new PropertyMapping { Name = "ask" } + : base.CreatePropertyMapping(memberInfo); } } [U] public void PrecedenceIsAsExpected() { + /** here we provide an explicit rename of a property on connectionsettings using `.Rename()` + * and all properties that are not mapped verbatim should be uppercased + */ var usingSettings = WithConnectionSettings(s => s - /** here we provide an explicit rename of a property on connectionsettings */ + .InferMappingFor(m => m .Rename(p => p.RenamedOnConnectionSettings, "renamed") ) - /** All properties that are not mapped verbatim should be uppercased*/ .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) ).WithSerializer(s => new CustomSerializer(s)); @@ -342,7 +343,7 @@ public void PrecedenceIsAsExpected() usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); - /** The same rules apply when indexing an object */ + /** The same naming rules also apply when indexing a document */ usingSettings.Expect(new [] { "ask", diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs index 95f1a6f6b59..df4f773f2f9 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs @@ -7,12 +7,13 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IdsInference { - /** # Ids + /** = Ids * - * Several places in the elasticsearch API expect an Id object to be passed. This is a special box type that you can implicitly convert to and from many value types. + * Several places in the elasticsearch API expect an Id object to be passed. + * This is a special box type that you can implicitly convert to and from many value types. */ - /** Methods that take an Id can be passed longs, ints, strings & Guids and they will implicitly converted to Ids */ + /** Methods that take an Id can be passed longs, ints, strings & Guids and they will be implicitly converted to Ids */ [U] public void CanImplicitlyConvertToId() { Id idFromInt = 1; @@ -27,7 +28,7 @@ [U] public void CanImplicitlyConvertToId() } /** Sometimes a method takes an object and we need an Id from that object to build up a path. - * There is no implicit conversion from any object to Id but we can call Id.From. + * There is no implicit conversion from any object to Id but we can call `Id.From`. * * Imagine your codebase has the following type that we want to index into elasticsearch */ @@ -61,7 +62,7 @@ [U] public void CanGetIdFromDocument() ).Expect("y").WhenInferringIdOn(dto); } - /** Another way is to mark the type with an ElasticType attribute, using a string IdProperty */ + /** Another way is to mark the type with an `ElasticsearchType` attribute, using a string `IdProperty` */ [ElasticsearchType(IdProperty = nameof(Name))] class MyOtherDTO { @@ -72,12 +73,15 @@ class MyOtherDTO [U] public void CanGetIdFromAttribute() { - /** Now when we infer the id we expect it to be the Name property without doing any configuration on the ConnectionSettings */ - var dto = new MyOtherDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; + /** Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the ConnectionSettings */ + var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; Expect("x").WhenInferringIdOn(dto); - /** This attribute IS cached statically/globally, however connectionsettings with a config for the type will - * still win over this static configuration*/ - /** Eventhough we have a cache at play the cache its per connection settings, so we can create a different config */ + + /** This attribute *is* cached statically/globally, however connectionsettings with a config for the type will + * still win over this static configuration. + * + * Even though we have a cache at play the cache its per connection settings, so we can create a different config + */ WithConnectionSettings(x => x .InferMappingFor(m => m .IdProperty(p => p.OtherName) diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs index c6c0262869e..e3311395958 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs @@ -8,15 +8,31 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence.PropertyNames { - public class PropertyNames { - [U] public void PropertyNamesAreResolvedToLastToken() + /** + * Property names resolve to the last token. An example using the `.Suffix()` extension + */ + [U] public void PropertyNamesAreResolvedToLastTokenUsingSuffix() { Expression> expression = p => p.Name.Suffix("raw"); Expect("raw").WhenSerializing(expression); } + /** + * And an example using the `.ApplySuffix()` extension on lambda expressions + */ + [U] + public void PropertyNamesAreResolvedToLastTokenUsingApplySuffix() + { + Expression> expression = p => p.Name; + expression.AppendSuffix("raw"); + Expect("raw").WhenSerializing(expression); + } + + /** Property names cannot contain a `.` in order to prevent the potential for collision with a field that + * may have https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html[`multi_fields`] + */ [U] public void StringsContainingDotsIsAnException() { Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index b399feaba90..1f6149a4993 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -286,7 +286,7 @@ [U] public void OverridingAutoMappedProperties() /** ## Automap with attributes * It is also possible to define your mappings using attributes on your POCOS. When you - * use attributes, you MUST use AutoMap() in order for the attributes to be applied. + * use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. * Here we define the same two types but this time using attributes. */ [ElasticsearchType(Name = "company")] @@ -325,6 +325,9 @@ public class EmployeeWithAttributes public List Employees { get; set; } } + /** + Then map the types by calling `.AutoMap()` + */ [U] public void UsingAutoMapWithAttributes() { @@ -466,7 +469,7 @@ public void UsingAutoMapWithAttributes() } }; - Expect(expected).WhenSerializing(descriptor as ICreateIndexRequest); + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); } /** @@ -634,8 +637,21 @@ public void OverridingAutoMappedAttributes() }; Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); - } - + } + + /** == Ignoring Properties + * Properties on a POCO can be ignored in a few ways: + * + * - Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO + * + * - Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings + * + * - Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` + * + * This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the + * property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` + */ + [ElasticsearchType(Name = "company")] public class CompanyWithAttributesAndPropertiesToIgnore { @@ -650,25 +666,10 @@ public class CompanyWithAttributesAndPropertiesToIgnore public string JsonIgnoredProperty { get; set; } } - /** == Ignoring Properties - * Properties on a POCO can be ignored in a few ways: - */ - /** - * - Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO - */ - /** - * - Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings - */ - /** - * - Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used and inspected inside of `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` - */ - /** - * This example demonstrates all ways, using the attribute way to ignore the property `PropertyToIgnore`, the infer mapping way to ignore the - * property `AnotherPropertyToIgnore` and the json serializer specific attribute way to ignore the property `JsonIgnoredProperty` - */ [U] public void IgnoringProperties() { + /** All of the properties except `Name` have been ignored in the mapping */ var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms .Map(m => m @@ -702,18 +703,18 @@ public void IgnoringProperties() settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); } - /** - * If you notice in our previous Company/Employee examples, the Employee type is recursive - * in that itself contains a collection of type `Employee`. By default, `.AutoMap()` will only + /** == Mapping Recursion + * If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive + * in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only * traverse a single depth when it encounters recursive instances like this. Hence, in the - * previous examples, the second level of Employee did not get any of its properties mapped. + * previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. * This is done as a safe-guard to prevent stack overflows and all the fun that comes with * infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is * often an edge case to have deeply nested mappings like this. However, you may still have - * the need to do this, so you can control the recursion depth of AutoMap(). + * the need to do this, so you can control the recursion depth of `.AutoMap()`. * - * Let's introduce a very simple class A, to reduce the noise, which itself has a property - * Child of type A. + * Let's introduce a very simple class, `A`, which itself has a property + * Child of type `A`. */ public class A { @@ -723,7 +724,7 @@ public class A [U] public void ControllingRecursionDepth() { - /** By default, AutoMap() only goes as far as depth 1 */ + /** By default, `.AutoMap()` only goes as far as depth 1 */ var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms .Map(m => m.AutoMap()) @@ -756,7 +757,7 @@ public void ControllingRecursionDepth() .Map(m => m.AutoMap(3)) ); - /** AutoMap() has now mapped three levels of our Child property */ + /** `.AutoMap()` has now mapped three levels of our Child property */ var expectedWithMaxRecursion = new { mappings = new @@ -797,26 +798,26 @@ public void ControllingRecursionDepth() }; Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); - } - - /** # Applying conventions through the Visitor pattern + } + + /** == Applying conventions through the Visitor pattern * It is also possible to apply a transformation on all or specific properties. * - * AutoMap internally implements the visitor pattern. The default visitor `NoopPropertyVisitor` does - * nothing, and acts as a blank canvas for you to implement your own visiting methods. + * AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, + * does nothing and acts as a blank canvas for you to implement your own visiting methods. * * For instance, lets create a custom visitor that disables doc values for numeric and boolean types. * (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) - */ + */ public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor { - /** Override the Visit method on INumberProperty and set DocValues = false */ + // Override the Visit method on INumberProperty and set DocValues = false public override void Visit(INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { type.DocValues = false; } - /** Similarily, override the Visit method on IBooleanProperty and set DocValues = false */ + // Similarily, override the Visit method on IBooleanProperty and set DocValues = false public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { type.DocValues = false; @@ -826,16 +827,16 @@ public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, Ela [U] public void UsingACustomPropertyVisitor() { - /** Now we can pass an instance of our custom visitor to AutoMap() */ + /** Now we can pass an instance of our custom visitor to `.AutoMap()` */ var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) - ); - - /** and anytime it maps a property as a number (INumberProperty) or boolean (IBooleanProperty) + ); + + /** and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) * it will apply the transformation defined in each Visit() respectively, which in this example - * disables doc values. - */ + * disables https://www.elastic.co/guide/en/elasticsearch/guide/current/doc-values.html[doc values]. + */ var expected = new { mappings = new @@ -878,8 +879,8 @@ public void UsingACustomPropertyVisitor() } /** You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit - * directly on your POCO properties (PropertyInfo). For example, lets create a visitor that maps all CLR types - * to an Elasticsearch string (IStringProperty). + * directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types + * to an Elasticsearch string (`IStringProperty`). */ public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { diff --git a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs index f6fcadfc92e..200d62c62d9 100644 --- a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs @@ -17,60 +17,36 @@ public class Lifetimes * ## Lifetimes * * If you are using an IOC container its always useful to know the best practices around the lifetime of your objects - + * * In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe * so sharing this instance over threads is ok. - - * Zooming in however the actual moving part that benefits the most of being static for most of the duration of your + * + * Zooming in however the actual moving part that benefits the most from being static for most of the duration of your * application is ConnectionSettings. Caches are per ConnectionSettings. - + * * In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different * connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. - - */ - - - [U] public void InitialDisposeState() - { - var connection = new AConnection(); - var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); - var settings = new AConnectionSettings(connectionPool, connection); - settings.IsDisposed.Should().BeFalse(); - connectionPool.IsDisposed.Should().BeFalse(); - connection.IsDisposed.Should().BeFalse(); - } - - /** - * Disposing the ConnectionSettings will dispose the IConnectionPool and IConnection it has a hold of + * + * Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types */ - [U] public void DisposingSettingsDisposesMovingParts() - { - var connection = new AConnection(); - var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); - var settings = new AConnectionSettings(connectionPool, connection); - using (settings) { } - settings.IsDisposed.Should().BeTrue(); - connectionPool.IsDisposed.Should().BeTrue(); - connection.IsDisposed.Should().BeTrue(); - } - - class AConnectionPool : SingleNodeConnectionPool + class AConnectionSettings : ConnectionSettings { - public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } - + public AConnectionSettings(IConnectionPool pool, IConnection connection) + : base(pool, connection) + { } public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() + protected override void DisposeManagedResources() { this.IsDisposed = true; base.DisposeManagedResources(); } } - class AConnectionSettings : ConnectionSettings + class AConnectionPool : SingleNodeConnectionPool { - public AConnectionSettings(IConnectionPool pool, IConnection connection) - : base(pool, connection) { } + public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } + public bool IsDisposed { get; private set; } protected override void DisposeManagedResources() { @@ -89,5 +65,31 @@ protected override void DisposeManagedResources() } } + /** + * `ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` + */ + [U] public void InitialDisposeState() + { + var connection = new AConnection(); + var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); + var settings = new AConnectionSettings(connectionPool, connection); + settings.IsDisposed.Should().BeFalse(); + connectionPool.IsDisposed.Should().BeFalse(); + connection.IsDisposed.Should().BeFalse(); + } + + /** + * Disposing the ConnectionSettings will dispose the `IConnectionPool` and `IConnection` it has a hold of + */ + [U] public void DisposingSettingsDisposesMovingParts() + { + var connection = new AConnection(); + var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); + var settings = new AConnectionSettings(connectionPool, connection); + using (settings) { } + settings.IsDisposed.Should().BeTrue(); + connectionPool.IsDisposed.Should().BeTrue(); + connection.IsDisposed.Should().BeTrue(); + } } } From dd779cdffa4d40826315449a3601355530897c60 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 11 Feb 2016 20:13:30 +1100 Subject: [PATCH 04/18] Run Litterateur --- .../ChildrenAggregationMapping.doc.asciidoc | 32 +- .../WritingAggregations.doc.asciidoc | 200 +++-- .../ConnectionPooling.Doc.asciidoc | 311 ++++--- .../DateTimeProviders.Doc.asciidoc | 113 +-- .../KeepingTrackOfNodes.Doc.asciidoc | 200 ++--- .../RequestPipelines.doc.asciidoc | 36 +- .../BuildingBlocks/Transports.Doc.asciidoc | 78 +- .../UnexpectedExceptions.doc.asciidoc | 226 +++-- .../UnrecoverableExceptions.doc.asciidoc | 88 +- .../Failover/FallingOver.doc.asciidoc | 160 ++-- .../MaxRetries/RespectsMaxRetry.doc.asciidoc | 292 +++--- .../Pinging/FirstUsage.doc.asciidoc | 236 +++-- .../Pinging/Revival.doc.asciidoc | 96 +- .../RespectsMaxRetryOverrides.doc.asciidoc | 136 +-- .../RoundRobin/RoundRobin.doc.asciidoc | 142 +-- .../RoundRobin/SkipDeadNodes.doc.asciidoc | 371 ++++---- .../RoundRobin/VolatileUpdates.doc.asciidoc | 5 +- .../Sniffing/OnConnectionFailure.doc.asciidoc | 327 ++++--- .../Sniffing/OnStaleClusterState.doc.asciidoc | 187 ++-- .../Sniffing/OnStartup.doc.asciidoc | 238 ++--- .../CovariantSearchResults.doc.asciidoc | 454 +++++----- .../Inferrence/DocumentPaths.doc.asciidoc | 203 +++-- .../Inferrence/FieldInference.doc.asciidoc | 833 +++++++++--------- .../Inferrence/IdsInference.doc.asciidoc | 196 ++--- .../Inferrence/IndicesPaths.doc.asciidoc | 92 +- .../Inferrence/PropertyInference.doc.asciidoc | 33 +- .../HighLevel/Mapping/AutoMap.doc.asciidoc | 153 ++-- .../LowLevel/Connecting.doc.asciidoc | 613 +++++++------ .../LowLevel/Lifetimes.doc.asciidoc | 118 ++- .../LowLevel/PostData.doc.asciidoc | 214 +++-- .../CodeStandards/Descriptors.doc.asciidoc | 104 +-- .../CodeStandards/ElasticClient.doc.asciidoc | 40 + .../NamingConventions.doc.asciidoc | 256 +++--- .../Serialization/Properties.doc.asciidoc | 32 +- .../DateMath/DateMathExpressions.doc.asciidoc | 186 ++-- .../TimeUnit/TimeUnits.doc.asciidoc | 232 ++--- .../QueryDsl/BoolDsl/BoolDsl.doc.asciidoc | 252 +++--- .../Geo/Distance/DistanceUnits.doc.asciidoc | 216 ++--- 38 files changed, 3894 insertions(+), 3807 deletions(-) diff --git a/docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc b/docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc index e03f8eb564a..6e375883cb6 100644 --- a/docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc +++ b/docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc @@ -1,16 +1,16 @@ -To use the child aggregation you have to make sure -a `_parent` mapping is in place, here we create the project -index with two mapped types, `project` and `commitactivity` and -we add a `_parent` mapping from `commitactivity` to `parent` - -[source, csharp] ----- -var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c - .Mappings(map=>map - .Map(m=>m.AutoMap()) - .Map(m=>m - .Parent() - ) - ) -); ----- +To use the child aggregation you have to make sure +a `_parent` mapping is in place, here we create the project +index with two mapped types, `project` and `commitactivity` and +we add a `_parent` mapping from `commitactivity` to `parent` + +[source, csharp] +---- +var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c + .Mappings(map=>map + .Map(m=>m.AutoMap()) + .Map(m=>m + .Parent() + ) + ) +); +---- diff --git a/docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc b/docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc index 7f2a8739c7d..84ee2a45592 100644 --- a/docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc +++ b/docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc @@ -1,78 +1,122 @@ -Aggregations are arguably one of the most powerful features of Elasticsearch. -NEST allows you to write your aggregations using a strict fluent dsl, a verbatim object initializer -syntax that maps verbatim to the elasticsearch API -a more terse object initializer aggregation DSL. - -Three different ways, yikes thats a lot to take in! Lets go over them one by one and explain when you might -want to use which one. - -The fluent lambda syntax is the most terse way to write aggregations. -It benefits from types that are carried over to sub aggregations - -[source, csharp] ----- -s => s -.Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => childAggs - .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - ) - ) -) ----- -The object initializer syntax (OIS) is a one-to-one mapping with how aggregations -have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one -mapping, being dictionary based in C# means it can grow exponentially in complexity rather quickly. - -[source, csharp] ----- -new SearchRequest -{ - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", "confidenceFactor") - && new MaxAggregation("max_per_child", "confidenceFactor") - } -} ----- -For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, -These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. -It also allows you to combine multiple aggregations using bitwise AND (` -`) operator. - -Compare the following example with the previous vanilla OIS syntax - -[source, csharp] ----- -new SearchRequest -{ - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) - && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) - } -} ----- -An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations -on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor -(`childAggs` below) in turn, returning the descriptor after each function application. - -[source, csharp] ----- -var aggregations = new List, IAggregationContainer>> -{ - a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), - a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) -}; -return s => s - .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => - aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) - ) - ) - ); ----- + +Aggregations are arguably one of the most powerful features of Elasticsearch. +NEST allows you to write your aggregations using a strict fluent dsl, a verbatim object initializer +syntax that maps verbatim to the elasticsearch API & a more terse object initializer aggregation DSL. + +Three different ways, yikes thats a lot to take in! Lets go over them one by one and explain when you might +want to use which one. + + + +The fluent lambda syntax is the most terse way to write aggregations. +It benefits from types that are carried over to sub aggregations + + + +The object initializer syntax (OIS) is a one-to-one mapping with how aggregations +have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one +mapping, being dictionary based in C# means it can grow exponentially in complexity rather quickly. + + +[source, csharp] +---- +public class Usage : UsageTestBase, SearchRequest> +{ + protected override object ExpectJson => new + { + aggs = new + { + name_of_child_agg = new + { + children = new { type = "commits" }, + aggs = new { + average_per_child = new + { + avg = new { field = "confidenceFactor" } + }, + max_per_child = new + { + max = new { field = "confidenceFactor" } + } + } + } + } + }; +protected override Func, ISearchRequest> Fluent => s => s + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) + ) + ); +protected override SearchRequest Initializer => + new SearchRequest + { + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", "confidenceFactor") + && new MaxAggregation("max_per_child", "confidenceFactor") + } + }; +} +---- + +For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, +These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. +It also allows you to combine multiple aggregations using bitwise AND (`&&`) operator. + +Compare the following example with the previous vanilla OIS syntax + + +[source, csharp] +---- +public class AggregationDslUsage : Usage +{ +protected override SearchRequest Initializer => + new SearchRequest + { + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) + && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) + } + }; +} +---- + +An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations +on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor +(`childAggs` below) in turn, returning the descriptor after each function application. + + + +[source, csharp] +---- +public class AdvancedAggregationDslUsage : Usage +{ +protected override Func, ISearchRequest> Fluent + { + get + { + var aggregations = new List, IAggregationContainer>> + { + a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), + a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + }; + + return s => s + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => + aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) + ) + ) + ); + } + } +} +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc index 8d4ec9d1de7..87b60162c38 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc @@ -1,161 +1,150 @@ -= Connection Pooling -Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which -we can use to issue client calls on. - - -== SingleNodeConnectionPool -The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls -It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always -ready to go. - - -[source, csharp] ----- -var uri = new Uri("http://localhost:9201"); -var pool = new SingleNodeConnectionPool(uri); -pool.Nodes.Should().HaveCount(1); -var node = pool.Nodes.First(); -node.Uri.Port.Should().Be(9201); ----- -This type of pool is hardwired to opt out of sniffing - -[source, csharp] ----- -pool.SupportsReseeding.Should().BeFalse(); ----- -and pinging - -[source, csharp] ----- -pool.SupportsPinging.Should().BeFalse(); ----- -When you use the low ceremony ElasticClient constructor that takes a single Uri, -We default to this SingleNodeConnectionPool - -[source, csharp] ----- -var client = new ElasticClient(uri); ----- -[source, csharp] ----- -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -However we urge that you always pass your connection settings explicitly - -[source, csharp] ----- -client = new ElasticClient(new ConnectionSettings(uri)); ----- -[source, csharp] ----- -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -or even better pass the connection pool explicitly - -[source, csharp] ----- -client = new ElasticClient(new ConnectionSettings(pool)); ----- -[source, csharp] ----- -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -== StaticConnectionPool -The static connection pool is great if you have a known small sized cluster and do no want to enable -sniffing to find out the cluster topology. - - -[source, csharp] ----- -var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ----- -a connection pool can be seeded using an enumerable of `Uri`s - -[source, csharp] ----- -var pool = new StaticConnectionPool(uris); ----- -Or using an enumerable of `Node` - -[source, csharp] ----- -var nodes = uris.Select(u=>new Node(u)); ----- -[source, csharp] ----- -pool = new StaticConnectionPool(nodes); ----- -This type of pool is hardwired to opt out of sniffing - -[source, csharp] ----- -pool.SupportsReseeding.Should().BeFalse(); ----- -but supports pinging when enabled - -[source, csharp] ----- -pool.SupportsPinging.Should().BeTrue(); ----- -To create a client using this static connection pool pass -the connection pool to the connectionsettings you pass to ElasticClient - -[source, csharp] ----- -var client = new ElasticClient(new ConnectionSettings(pool)); ----- -[source, csharp] ----- -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -== SniffingConnectionPool -A subclass of StaticConnectionPool that allows itself to be reseeded at run time. -It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. - - -[source, csharp] ----- -var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ----- -a connection pool can be seeded using an enumerable of `Uri` - -[source, csharp] ----- -var pool = new SniffingConnectionPool(uris); ----- -Or using an enumerable of `Node` -A major benefit here is you can include known node roles when seeding -NEST can use this information to favour sniffing on master eligible nodes first -and take master only nodes out of rotation for issuing client calls on. - -[source, csharp] ----- -var nodes = uris.Select(u=>new Node(u)); ----- -[source, csharp] ----- -pool = new SniffingConnectionPool(nodes); ----- -This type of pool is hardwired to opt in to sniffing - -[source, csharp] ----- -pool.SupportsReseeding.Should().BeTrue(); ----- -and pinging - -[source, csharp] ----- -pool.SupportsPinging.Should().BeTrue(); ----- -To create a client using the sniffing connection pool pass -the connection pool to the connectionsettings you pass to ElasticClient - -[source, csharp] ----- -var client = new ElasticClient(new ConnectionSettings(pool)); ----- -[source, csharp] ----- -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- += Connection Pooling +Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which +we can use to issue client calls on. + + +== SingleNodeConnectionPool +The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls +It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always +ready to go. + + +[source, csharp] +---- +var uri = new Uri("http://localhost:9201"); +var pool = new SingleNodeConnectionPool(uri); +pool.Nodes.Should().HaveCount(1); +var node = pool.Nodes.First(); +node.Uri.Port.Should().Be(9201); +---- +This type of pool is hardwired to opt out of sniffing + +[source, csharp] +---- +pool.SupportsReseeding.Should().BeFalse(); +---- +and pinging + +[source, csharp] +---- +pool.SupportsPinging.Should().BeFalse(); +---- +When you use the low ceremony ElasticClient constructor that takes a single Uri, +We default to this SingleNodeConnectionPool + +[source, csharp] +---- +var client = new ElasticClient(uri); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- +However we urge that you always pass your connection settings explicitly + +[source, csharp] +---- +client = new ElasticClient(new ConnectionSettings(uri)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- +or even better pass the connection pool explicitly + +[source, csharp] +---- +client = new ElasticClient(new ConnectionSettings(pool)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- +== StaticConnectionPool +The static connection pool is great if you have a known small sized cluster and do no want to enable +sniffing to find out the cluster topology. + + +[source, csharp] +---- +var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); +---- +a connection pool can be seeded using an enumerable of `Uri`s + +[source, csharp] +---- +var pool = new StaticConnectionPool(uris); +---- +Or using an enumerable of `Node` + +[source, csharp] +---- +var nodes = uris.Select(u=>new Node(u)); + +pool = new StaticConnectionPool(nodes); +---- +This type of pool is hardwired to opt out of sniffing + +[source, csharp] +---- +pool.SupportsReseeding.Should().BeFalse(); +---- +but supports pinging when enabled + +[source, csharp] +---- +pool.SupportsPinging.Should().BeTrue(); +---- +To create a client using this static connection pool pass +the connection pool to the connectionsettings you pass to ElasticClient + + +[source, csharp] +---- +var client = new ElasticClient(new ConnectionSettings(pool)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- +== SniffingConnectionPool +A subclass of StaticConnectionPool that allows itself to be reseeded at run time. +It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. + + +[source, csharp] +---- +var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); +---- +a connection pool can be seeded using an enumerable of `Uri` + +[source, csharp] +---- +var pool = new SniffingConnectionPool(uris); +---- +Or using an enumerable of `Node` +A major benefit here is you can include known node roles when seeding +NEST can use this information to favour sniffing on master eligible nodes first +and take master only nodes out of rotation for issuing client calls on. + + +[source, csharp] +---- +var nodes = uris.Select(u=>new Node(u)); + +pool = new SniffingConnectionPool(nodes); +---- +This type of pool is hardwired to opt in to sniffing + +[source, csharp] +---- +pool.SupportsReseeding.Should().BeTrue(); +---- +and pinging + +[source, csharp] +---- +pool.SupportsPinging.Should().BeTrue(); +---- +To create a client using the sniffing connection pool pass +the connection pool to the connectionsettings you pass to ElasticClient + + +[source, csharp] +---- +var client = new ElasticClient(new ConnectionSettings(pool)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc index 6865704b143..d3f7c9d7308 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc @@ -1,56 +1,57 @@ -= Date time providers - -Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` -in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover -in run time not being bound to wall clock time. - - -[source, csharp] ----- -var dateTimeProvider = DateTimeProvider.Default; ----- -dates are always returned in UTC - -[source, csharp] ----- -dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); ----- - -Another responsibility of this interface is to calculate the time a node has to be taken out of rotation -based on the number of attempts to revive it. For very advanced use cases, this might be something of interest -to provide a custom implementation for. - - -[source, csharp] ----- -var dateTimeProvider = DateTimeProvider.Default; ----- - -The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)` -The default values for `timeout` and `maxTimeout` are - -[source, csharp] ----- -var timeout = TimeSpan.FromMinutes(1); ----- -[source, csharp] ----- -var maxTimeout = TimeSpan.FromMinutes(30); ----- -Plotting these defaults looks as followed: -[[timeout]] -.Default formula, x-axis time in minutes, y-axis number of attempts to revive -image::timeoutplot.png[dead timeout] -The goal here is that whenever a node is resurrected and is found to still be offline, we send it -_back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. - -[source, csharp] ----- -var timeouts = Enumerable.Range(0, 30) - .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) - .ToList(); ----- -[source, csharp] ----- -increasedTimeout.Should().BeWithin(maxTimeout); ----- += Date time providers + +Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` +in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover +in run time not being bound to wall clock time. + + +[source, csharp] +---- +var dateTimeProvider = DateTimeProvider.Default; +---- +dates are always returned in UTC + +[source, csharp] +---- +dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); +---- + +Another responsibility of this interface is to calculate the time a node has to be taken out of rotation +based on the number of attempts to revive it. For very advanced use cases, this might be something of interest +to provide a custom implementation for. + + +[source, csharp] +---- +var dateTimeProvider = DateTimeProvider.Default; +---- + +The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)` +The default values for `timeout` and `maxTimeout` are + + +[source, csharp] +---- +var timeout = TimeSpan.FromMinutes(1); + +var maxTimeout = TimeSpan.FromMinutes(30); +---- + +Plotting these defaults looks as followed: + +[[timeout]] +.Default formula, x-axis time in minutes, y-axis number of attempts to revive +image::timeoutplot.png[dead timeout] + +The goal here is that whenever a node is resurrected and is found to still be offline, we send it +_back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. + + +[source, csharp] +---- +var timeouts = Enumerable.Range(0, 30) + .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) + .ToList(); + +increasedTimeout.Should().BeWithin(maxTimeout); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc index ab9533441a7..664157e5f65 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc @@ -1,106 +1,94 @@ -= Keeping track of nodes - - - -[source, csharp] ----- -var node = new Node(new Uri("http://localhost:9200")); -node.Uri.Should().NotBeNull(); -node.Uri.Port.Should().Be(9200); ----- -By default master eligible and holds data is presumed to be true * - -[source, csharp] ----- -node.MasterEligible.Should().BeTrue(); ----- -[source, csharp] ----- -node.HoldsData.Should().BeTrue(); ----- -Is resurrected is true on first usage, hints to the transport that a ping might be useful - -[source, csharp] ----- -node.IsResurrected.Should().BeTrue(); ----- -When instantiating your connection pool you could switch these to false to initialize the client to -a known cluster topology. - - -passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy - -[source, csharp] ----- -var node = new Node(new Uri("http://test.example/elasticsearch")); ----- -[source, csharp] ----- -node.Uri.Port.Should().Be(80); -node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); ----- -We force paths to end with a forward slash so that they can later be safely combined - -[source, csharp] ----- -var combinedPath = new Uri(node.Uri, "index/type/_search"); ----- -[source, csharp] ----- -combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); ----- -which is exactly what the `CreatePath` method does on `Node` - -[source, csharp] ----- -combinedPath = node.CreatePath("index/type/_search"); ----- -[source, csharp] ----- -combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); -var node = new Node(new Uri("http://localhost:9200")); -node.FailedAttempts.Should().Be(0); -node.IsAlive.Should().BeTrue(); ----- - -every time a node is marked dead the number of attempts should increase -and the passed datetime should be exposed. - - -[source, csharp] ----- -var deadUntil = DateTime.Now.AddMinutes(1); -node.MarkDead(deadUntil); -node.FailedAttempts.Should().Be(i + 1); -node.IsAlive.Should().BeFalse(); -node.DeadUntil.Should().Be(deadUntil); ----- -however when marking a node alive deaduntil should be reset and attempts reset to 0 - -[source, csharp] ----- -node.MarkAlive(); ----- -[source, csharp] ----- -node.FailedAttempts.Should().Be(0); -node.DeadUntil.Should().Be(default(DateTime)); -node.IsAlive.Should().BeTrue(); ----- -Nodes are considered equal if they have the same endpoint no matter what other metadata is associated - -[source, csharp] ----- -var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; ----- -[source, csharp] ----- -var nodeAsMaster = new Node(new Uri("http://localhost:9200")) { MasterEligible = true }; -(node == nodeAsMaster).Should().BeTrue(); -(node != nodeAsMaster).Should().BeFalse(); -var uri = new Uri("http://localhost:9200"); -(node == uri).Should().BeTrue(); -var differentUri = new Uri("http://localhost:9201"); -(node != differentUri).Should().BeTrue(); -node.Should().Be(nodeAsMaster); ----- += Keeping track of nodes + + + +[source, csharp] +---- +var node = new Node(new Uri("http://localhost:9200")); +node.Uri.Should().NotBeNull(); +node.Uri.Port.Should().Be(9200); +---- +By default master eligible and holds data is presumed to be true + +[source, csharp] +---- +node.MasterEligible.Should().BeTrue(); + +node.HoldsData.Should().BeTrue(); +---- +Is resurrected is true on first usage, hints to the transport that a ping might be useful + +[source, csharp] +---- +node.IsResurrected.Should().BeTrue(); +---- +When instantiating your connection pool you could switch these to false to initialize the client to +a known cluster topology. + + +passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy + +[source, csharp] +---- +var node = new Node(new Uri("http://test.example/elasticsearch")); + +node.Uri.Port.Should().Be(80); +node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); +---- +We force paths to end with a forward slash so that they can later be safely combined + +[source, csharp] +---- +var combinedPath = new Uri(node.Uri, "index/type/_search"); + +combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); +---- +which is exactly what the `CreatePath` method does on `Node` + +[source, csharp] +---- +combinedPath = node.CreatePath("index/type/_search"); + +combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); +var node = new Node(new Uri("http://localhost:9200")); +node.FailedAttempts.Should().Be(0); +node.IsAlive.Should().BeTrue(); +---- + +every time a node is marked dead the number of attempts should increase +and the passed datetime should be exposed. + + +[source, csharp] +---- +var deadUntil = DateTime.Now.AddMinutes(1); +node.MarkDead(deadUntil); +node.FailedAttempts.Should().Be(i + 1); +node.IsAlive.Should().BeFalse(); +node.DeadUntil.Should().Be(deadUntil); +---- +however when marking a node alive deaduntil should be reset and attempts reset to 0 + +[source, csharp] +---- +node.MarkAlive(); + +node.FailedAttempts.Should().Be(0); +node.DeadUntil.Should().Be(default(DateTime)); +node.IsAlive.Should().BeTrue(); +---- +Nodes are considered equal if they have the same endpoint no matter what other metadata is associated + +[source, csharp] +---- +var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; + +var nodeAsMaster = new Node(new Uri("http://localhost:9200")) { MasterEligible = true }; +(node == nodeAsMaster).Should().BeTrue(); +(node != nodeAsMaster).Should().BeFalse(); +var uri = new Uri("http://localhost:9200"); +(node == uri).Should().BeTrue(); +var differentUri = new Uri("http://localhost:9201"); +(node != differentUri).Should().BeTrue(); +node.Should().Be(nodeAsMaster); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc index a8bcb9555d8..8dcbe1f5eef 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc @@ -12,9 +12,7 @@ When calling Request(Async) on Transport the whole coordination of the request i [source, csharp] ---- var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); ----- -[source, csharp] ----- + pipeline.GetType().Should().Implement(); ---- However the transport does not instantiate RequestPipeline directly, it uses a pluggable `IRequestPipelineFactory` @@ -22,9 +20,7 @@ However the transport does not instantiate RequestPipeline directly, it uses a p [source, csharp] ---- var requestPipelineFactory = new RequestPipelineFactory(); ----- -[source, csharp] ----- + var requestPipeline = requestPipelineFactory.Create(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); requestPipeline.Should().BeOfType(); requestPipeline.GetType().Should().Implement(); @@ -35,7 +31,7 @@ which can be passed to the transport when instantiating a client ---- var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); ---- -this allows you to have requests executed on your own custom request pipeline +this allows you to have requests executed on your own custom request pipeline [source, csharp] ---- @@ -51,21 +47,18 @@ Here we have setup three pipelines using three different connection pools, lets [source, csharp] ---- singleNodePipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); ----- -[source, csharp] ----- + staticPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeTrue(); ---- Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() You can however disable this on ConnectionSettings + [source, csharp] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnStartup(false)); ----- -[source, csharp] ----- + sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); var staticPipeline = CreatePipeline(uris => new StaticConnectionPool(uris)); @@ -77,12 +70,11 @@ sniffingPipeline.SniffsOnConnectionFailure.Should().BeTrue(); Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() You can however disable this on ConnectionSettings + [source, csharp] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnConnectionFault(false)); ----- -[source, csharp] ----- + sniffingPipeline.SniffsOnConnectionFailure.Should().BeFalse(); var dateTime = new TestableDateTimeProvider(); var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First(), dateTime), dateTimeProvider: dateTime); @@ -106,9 +98,7 @@ connection pools that do not support reseeding never go stale [source, csharp] ---- singleNodePipeline.StaleClusterState.Should().BeFalse(); ----- -[source, csharp] ----- + staticPipeline.StaleClusterState.Should().BeFalse(); ---- the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date @@ -142,9 +132,7 @@ connection pools that do not support reseeding never go stale [source, csharp] ---- singleNodePipeline.IsTakingTooLong.Should().BeTrue(); ----- -[source, csharp] ----- + staticPipeline.IsTakingTooLong.Should().BeTrue(); ---- the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date @@ -158,9 +146,7 @@ request pipeline exposes the DateTime it started, here we assert it started 2 ho [source, csharp] ---- (dateTime.Now() - singleNodePipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); ----- -[source, csharp] ----- + (dateTime.Now() - staticPipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); (dateTime.Now() - sniffingPipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); var dateTime = new TestableDateTimeProvider(); diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc index 359ea30aefc..44786fca5fd 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc @@ -1,39 +1,39 @@ -= Transports - -The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. -It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote -the internals of the client, by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. - - - -Transport is generically typed to a type that implements IConnectionConfigurationValues -This is the minimum ITransport needs to report back for the client to function. -e.g in the low level client, transport is instantiated like this: - -[source, csharp] ----- -var lowLevelTransport = new Transport(new ConnectionConfiguration()); ----- -In the high level client like this: - -[source, csharp] ----- -var highlevelTransport = new Transport(new ConnectionSettings()); ----- -[source, csharp] ----- -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var inMemoryTransport = new Transport(new ConnectionSettings(connectionPool, new InMemoryConnection())); ----- -The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the default `ITransport` implementation is responsible for introducing -many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. -If you feel this need, please let us know as we'd love to learn why you've go down this route! - -[source, csharp] ----- -var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); ----- -[source, csharp] ----- -response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); ----- += Transports + +The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. +It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote +the internals of the client, by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. + + + +Transport is generically typed to a type that implements IConnectionConfigurationValues +This is the minimum ITransport needs to report back for the client to function. + +e.g in the low level client, transport is instantiated like this: + + +[source, csharp] +---- +var lowLevelTransport = new Transport(new ConnectionConfiguration()); +---- +In the high level client like this: + +[source, csharp] +---- +var highlevelTransport = new Transport(new ConnectionSettings()); + +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var inMemoryTransport = new Transport(new ConnectionSettings(connectionPool, new InMemoryConnection())); +---- + +The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the default `ITransport` implementation is responsible for introducing +many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. +If you feel this need, please let us know as we'd love to learn why you've go down this route! + + +[source, csharp] +---- +var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); + +response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc index 1dc333afec6..5c991fcffd2 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc @@ -1,114 +1,112 @@ -== Unexpected exceptions -When a client call throws an exception that the IConnction can not handle, this exception will bubble -out the client as an UnexpectedElasticsearchClientException, regardless whether the client is configured to throw or not. -An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and -will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { AuditEvent.HealthyResponse, 9200 }, - } - ); -audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); - e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); - } - ); -e.FailureReason.Should().Be(PipelineFailure.Unexpected); -e.InnerException.Should().NotBeNull(); -e.InnerException.Message.Should().Be("boom!"); ----- - -Sometimes an unexpected exception happens further down in the pipeline, this is why we -wrap them inside an UnexpectedElasticsearchClientException so that information about where -in the pipeline the unexpected exception is not lost, here a call to 9200 fails using a webexception. -It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we -can still see the audit trail for the whole coordinated request. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) -#if DOTNETCORE - .ClientCalls(r => r.OnPort(9200).FailAlways(new System.Net.Http.HttpRequestException("recover"))) -#else - .ClientCalls(r => r.OnPort(9200).FailAlways(new WebException("recover"))) -#endif - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.BadResponse, 9200 }, - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); - e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); - } - ); -e.FailureReason.Should().Be(PipelineFailure.Unexpected); -e.InnerException.Should().NotBeNull(); -e.InnerException.Message.Should().Be("boom!"); ----- - -An unexpected hard exception on ping and sniff is something we *do* try to revover from and failover. -Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. -However the client call on 9201 throws a hard exception we can not recover from - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(r => r.OnPort(9200).FailAlways(new Exception("ping exception"))) - .Ping(r => r.OnPort(9201).SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .AllDefaults() - ); ----- -[source, csharp] ----- -audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.PingFailure, 9200 }, - { AuditEvent.PingSuccess, 9201 }, - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); -e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); -e.SeenExceptions.Should().NotBeEmpty(); - var pipelineException = e.SeenExceptions.First(); - pipelineException.FailureReason.Should().Be(PipelineFailure.PingFailure); - pipelineException.InnerException.Message.Should().Be("ping exception"); -var pingException = e.AuditTrail.First(a => a.Event == AuditEvent.PingFailure).Exception; - pingException.Should().NotBeNull(); - pingException.Message.Should().Be("ping exception"); - - } -); ----- +== Unexpected exceptions +When a client call throws an exception that the IConnction can not handle, this exception will bubble +out the client as an UnexpectedElasticsearchClientException, regardless whether the client is configured to throw or not. +An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and +will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall { + { AuditEvent.HealthyResponse, 9200 }, + } + ); +audit = await audit.TraceUnexpectedException( + new ClientCall { + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); + } + ); +e.FailureReason.Should().Be(PipelineFailure.Unexpected); +e.InnerException.Should().NotBeNull(); +e.InnerException.Message.Should().Be("boom!"); +---- + +Sometimes an unexpected exception happens further down in the pipeline, this is why we +wrap them inside an UnexpectedElasticsearchClientException so that information about where +in the pipeline the unexpected exception is not lost, here a call to 9200 fails using a webexception. +It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we +can still see the audit trail for the whole coordinated request. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) +#if DOTNETCORE + .ClientCalls(r => r.OnPort(9200).FailAlways(new System.Net.Http.HttpRequestException("recover"))) +#else + .ClientCalls(r => r.OnPort(9200).FailAlways(new WebException("recover"))) +#endif + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceUnexpectedException( + new ClientCall { + { AuditEvent.BadResponse, 9200 }, + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); + } + ); +e.FailureReason.Should().Be(PipelineFailure.Unexpected); +e.InnerException.Should().NotBeNull(); +e.InnerException.Message.Should().Be("boom!"); +---- + +An unexpected hard exception on ping and sniff is something we *do* try to revover from and failover. +Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. +However the client call on 9201 throws a hard exception we can not recover from + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.OnPort(9200).FailAlways(new Exception("ping exception"))) + .Ping(r => r.OnPort(9201).SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .AllDefaults() + ); + +audit = await audit.TraceUnexpectedException( + new ClientCall { + { AuditEvent.PingFailure, 9200 }, + { AuditEvent.PingSuccess, 9201 }, + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); +e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); +e.SeenExceptions.Should().NotBeEmpty(); + var pipelineException = e.SeenExceptions.First(); + pipelineException.FailureReason.Should().Be(PipelineFailure.PingFailure); + pipelineException.InnerException.Message.Should().Be("ping exception"); +var pingException = e.AuditTrail.First(a => a.Event == AuditEvent.PingFailure).Exception; + pingException.Should().NotBeNull(); + pingException.Message.Should().Be("ping exception"); + + } +); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc index 7a2c0e52b85..31f22d65f29 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc @@ -1,44 +1,44 @@ -== Unrecoverable exceptions -Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. -By default the client won't throw on any ElasticsearchClientException but return an invalid response. -You can configure the client to throw using ThrowExceptions() on ConnectionSettings. The following test -both a client that throws and one that returns an invalid response with an `.OriginalException` exposed - - -[source, csharp] ----- -var recoverablExceptions = new[] - { - new PipelineException(PipelineFailure.BadResponse), - new PipelineException(PipelineFailure.PingFailure), - }; -recoverablExceptions.Should().OnlyContain(e => e.Recoverable); -var unrecoverableExceptions = new[] - { - new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), - new PipelineException(PipelineFailure.SniffFailure), - new PipelineException(PipelineFailure.Unexpected), - new PipelineException(PipelineFailure.BadAuthentication), - new PipelineException(PipelineFailure.MaxRetriesReached), - new PipelineException(PipelineFailure.MaxTimeoutReached) - }; -unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(r => r.SucceedAlways()) - .ClientCalls(r => r.FailAlways(401)) - .StaticConnectionPool() - .AllDefaults() - ); -audit = await audit.TraceElasticsearchException( - new ClientCall { - { AuditEvent.PingSuccess, 9200 }, - { AuditEvent.BadResponse, 9200 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); - } - ); -e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); ----- +== Unrecoverable exceptions +Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. +By default the client won't throw on any ElasticsearchClientException but return an invalid response. +You can configure the client to throw using ThrowExceptions() on ConnectionSettings. The following test +both a client that throws and one that returns an invalid response with an `.OriginalException` exposed + + +[source, csharp] +---- +var recoverablExceptions = new[] + { + new PipelineException(PipelineFailure.BadResponse), + new PipelineException(PipelineFailure.PingFailure), + }; +recoverablExceptions.Should().OnlyContain(e => e.Recoverable); +var unrecoverableExceptions = new[] + { + new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), + new PipelineException(PipelineFailure.SniffFailure), + new PipelineException(PipelineFailure.Unexpected), + new PipelineException(PipelineFailure.BadAuthentication), + new PipelineException(PipelineFailure.MaxRetriesReached), + new PipelineException(PipelineFailure.MaxTimeoutReached) + }; +unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.SucceedAlways()) + .ClientCalls(r => r.FailAlways(401)) + .StaticConnectionPool() + .AllDefaults() + ); +audit = await audit.TraceElasticsearchException( + new ClientCall { + { AuditEvent.PingSuccess, 9200 }, + { AuditEvent.BadResponse, 9200 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + } + ); +e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc index f83117ff4d0..1149214a473 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc @@ -1,80 +1,80 @@ -== Fail over -When using connection pooling and the pool has sufficient nodes a request will be retried if -the call to a node throws an exception or returns a 502 or 503 - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } - ); ----- -502 Bad Gateway -Will be treated as an error that requires retrying - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(502)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } - ); ----- -503 Service Unavailable -Will be treated as an error that requires retrying - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(503)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } - ); ----- - -If a call returns a valid http status code other then 502/503 the request won't be retried. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(418)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - } - ); ----- +== Fail over +When using connection pooling and the pool has sufficient nodes a request will be retried if +the call to a node throws an exception or returns a 502 or 503 + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } + ); +---- +502 Bad Gateway +Will be treated as an error that requires retrying + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(502)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } + ); +---- +503 Service Unavailable +Will be treated as an error that requires retrying + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(503)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } + ); +---- + +If a call returns a valid http status code other then 502/503 the request won't be retried. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(418)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + } + ); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc index 2aa8b032712..7789c95c8cd 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc @@ -1,146 +1,146 @@ -== MaxRetries -By default retry as many times as we have nodes. However retries still respect the request timeout. -Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can -but give up after 20 seconds - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { BadResponse, 9205 }, - { BadResponse, 9206 }, - { BadResponse, 9207 }, - { BadResponse, 9208 }, - { HealthyResponse, 9209 } - } - ); ----- - -When you have a 100 node cluster you might want to ensure a fixed number of retries. -Remember that the actual number of requests is initial attempt + set number of retries - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(3)) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { MaxRetriesReached } - } - ); ----- - -In our previous test we simulated very fast failures, in the real world a call might take upwards of a second -Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. -In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxTimeoutReached } - } - ); ----- - -If you set smaller request time outs you might not want it to also affect the retry timeout, therefor you can configure these separately too. -Here we simulate calls taking 3 seconds, a request time out of 2 and an overall retry timeout of 10 seconds. -We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 -wins over the configured request timeout - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).FailAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { MaxTimeoutReached } - } - ); ----- - -If your retry policy expands beyond available nodes we won't retry the same node twice - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(2) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxRetriesReached } - } - ); ----- - -This makes setting any retry setting on a single node connection pool a NOOP, this is by design! -Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and -not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .SingleNodeConnection() - .Settings(s => s.DisablePing().MaximumRetries(10)) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 } - } - ); ----- +== MaxRetries +By default retry as many times as we have nodes. However retries still respect the request timeout. +Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can +but give up after 20 seconds + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 } + } + ); +---- + +When you have a 100 node cluster you might want to ensure a fixed number of retries. +Remember that the actual number of requests is initial attempt + set number of retries + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(3)) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { MaxRetriesReached } + } + ); +---- + +In our previous test we simulated very fast failures, in the real world a call might take upwards of a second +Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. +In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxTimeoutReached } + } + ); +---- + +If you set smaller request time outs you might not want it to also affect the retry timeout, therefor you can configure these separately too. +Here we simulate calls taking 3 seconds, a request time out of 2 and an overall retry timeout of 10 seconds. +We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 +wins over the configured request timeout + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { MaxTimeoutReached } + } + ); +---- + +If your retry policy expands beyond available nodes we won't retry the same node twice + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(2) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxRetriesReached } + } + ); +---- + +This makes setting any retry setting on a single node connection pool a NOOP, this is by design! +Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and +not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .SingleNodeConnection() + .Settings(s => s.DisablePing().MaximumRetries(10)) + ); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 } + } + ); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc index 6648607066a..7aa893703be 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc @@ -1,128 +1,108 @@ -== Pinging - -Pinging is enabled by default for the Static & Sniffing connection pool. -This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. -This allows us to fail and fallover to a healthy node faster - - -A cluster with 2 nodes where the second node fails on ping - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(2) - .Ping(p => p.Succeeds(Always)) - .Ping(p => p.OnPort(9201).FailAlways()) - .StaticConnectionPool() - .AllDefaults() -); ----- -[source, csharp] ----- -await audit.TraceCalls( ----- -The first call goes to 9200 which succeeds - -[source, csharp] ----- -new ClientCall { - { PingSuccess, 9200}, - { HealthyResponse, 9200}, - { pool => - { - pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); - } } - }, ----- -The 2nd call does a ping on 9201 because its used for the first time. -It fails so we wrap over to node 9200 which we've already pinged - -[source, csharp] ----- -new ClientCall { - { PingFailure, 9201}, - { HealthyResponse, 9200}, ----- -Finally we assert that the connectionpool has one node that is marked as dead - -[source, csharp] ----- -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - } -); ----- -A cluster with 4 nodes where the second and third pings fail - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .Ping(p => p.SucceedAlways()) - .Ping(p => p.OnPort(9201).FailAlways()) - .Ping(p => p.OnPort(9202).FailAlways()) - .StaticConnectionPool() - .AllDefaults() -); ----- -[source, csharp] ----- -await audit.TraceCalls( ----- -The first call goes to 9200 which succeeds - -[source, csharp] ----- -new ClientCall { - { PingSuccess, 9200}, - { HealthyResponse, 9200}, - { pool => - { - pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); - } } - }, ----- -The 2nd call does a ping on 9201 because its used for the first time. -It fails and so we ping 9202 which also fails. We then ping 9203 becuase -we haven't used it before and it succeeds - -[source, csharp] ----- -new ClientCall { - { PingFailure, 9201}, - { PingFailure, 9202}, - { PingSuccess, 9203}, - { HealthyResponse, 9203}, ----- -Finally we assert that the connectionpool has two nodes that are marked as dead - -[source, csharp] ----- -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - } -); ----- -A healthy cluster of 4 (min master nodes of 3 of course!) - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .Ping(p => p.SucceedAlways()) - .StaticConnectionPool() - .AllDefaults() -); ----- -[source, csharp] ----- -await audit.TraceCalls( - new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }, - new ClientCall { { PingSuccess, 9201}, { HealthyResponse, 9201} }, - new ClientCall { { PingSuccess, 9202}, { HealthyResponse, 9202} }, - new ClientCall { { PingSuccess, 9203}, { HealthyResponse, 9203} }, - new ClientCall { { HealthyResponse, 9200} }, - new ClientCall { { HealthyResponse, 9201} }, - new ClientCall { { HealthyResponse, 9202} }, - new ClientCall { { HealthyResponse, 9203} }, - new ClientCall { { HealthyResponse, 9200} } - ); ----- +== Pinging + +Pinging is enabled by default for the Static & Sniffing connection pool. +This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. +This allows us to fail and fallover to a healthy node faster + + +A cluster with 2 nodes where the second node fails on ping + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(2) + .Ping(p => p.Succeeds(Always)) + .Ping(p => p.OnPort(9201).FailAlways()) + .StaticConnectionPool() + .AllDefaults() +); +---- +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails so we wrap over to node 9200 which we've already pinged + +Finally we assert that the connectionpool has one node that is marked as dead + +[source, csharp] +---- +await audit.TraceCalls( +new ClientCall { + { PingSuccess, 9200}, + { HealthyResponse, 9200}, + { pool => + { + pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); + } } + }, +new ClientCall { + { PingFailure, 9201}, + { HealthyResponse, 9200}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + } +); +---- +A cluster with 4 nodes where the second and third pings fail + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .Ping(p => p.SucceedAlways()) + .Ping(p => p.OnPort(9201).FailAlways()) + .Ping(p => p.OnPort(9202).FailAlways()) + .StaticConnectionPool() + .AllDefaults() +); +---- +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails and so we ping 9202 which also fails. We then ping 9203 becuase +we haven't used it before and it succeeds + +Finally we assert that the connectionpool has two nodes that are marked as dead + +[source, csharp] +---- +await audit.TraceCalls( +new ClientCall { + { PingSuccess, 9200}, + { HealthyResponse, 9200}, + { pool => + { + pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); + } } + }, +new ClientCall { + { PingFailure, 9201}, + { PingFailure, 9202}, + { PingSuccess, 9203}, + { HealthyResponse, 9203}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + } +); +---- +A healthy cluster of 4 (min master nodes of 3 of course!) + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .Ping(p => p.SucceedAlways()) + .StaticConnectionPool() + .AllDefaults() +); + +await audit.TraceCalls( + new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }, + new ClientCall { { PingSuccess, 9201}, { HealthyResponse, 9201} }, + new ClientCall { { PingSuccess, 9202}, { HealthyResponse, 9202} }, + new ClientCall { { PingSuccess, 9203}, { HealthyResponse, 9203} }, + new ClientCall { { HealthyResponse, 9200} }, + new ClientCall { { HealthyResponse, 9201} }, + new ClientCall { { HealthyResponse, 9202} }, + new ClientCall { { HealthyResponse, 9203} }, + new ClientCall { { HealthyResponse, 9200} } + ); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc index 89c4e99284a..a8bd14380a3 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc @@ -1,48 +1,48 @@ -== Pinging - -When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping -before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(3) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9202).Fails(Once)) - .Ping(p => p.SucceedAlways()) - .StaticConnectionPool() - .AllDefaults() - ); -audit = await audit.TraceCalls( - new ClientCall { { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, - new ClientCall { { PingSuccess, 9201 }, { HealthyResponse, 9201 } }, - new ClientCall { - { PingSuccess, 9202}, - { BadResponse, 9202}, - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.First(n=>!n.IsAlive).DeadUntil.Should().BeAfter(DateTime.UtcNow) } - } - ); -audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } } - ); -audit.ChangeTime(d => d.AddMinutes(20)); -audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { - { Resurrection, 9202 }, - { PingSuccess, 9202 }, - { HealthyResponse, 9202 } - } - ); ----- +== Pinging + +When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping +before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(3) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9202).Fails(Once)) + .Ping(p => p.SucceedAlways()) + .StaticConnectionPool() + .AllDefaults() + ); +audit = await audit.TraceCalls( + new ClientCall { { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, + new ClientCall { { PingSuccess, 9201 }, { HealthyResponse, 9201 } }, + new ClientCall { + { PingSuccess, 9202}, + { BadResponse, 9202}, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.First(n=>!n.IsAlive).DeadUntil.Should().BeAfter(DateTime.UtcNow) } + } + ); +audit = await audit.TraceCalls( + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } } + ); +audit.ChangeTime(d => d.AddMinutes(20)); +audit = await audit.TraceCalls( + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { + { Resurrection, 9202 }, + { PingSuccess, 9202 }, + { HealthyResponse, 9202 } + } + ); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc index ce2f5afac55..40b678d12de 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc @@ -1,68 +1,68 @@ -== MaxRetries -By default retry as many times as we have nodes. However retries still respect the request timeout. -Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can -but give up after 20 seconds - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(2)) { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { MaxRetriesReached } - } - ); ----- - -When you have a 100 node cluster you might want to ensure a fixed number of retries. -Remember that the actual number of requests is initial attempt + set number of retries - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(5)) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(2)) { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { MaxRetriesReached } - } - ); ----- - -This makes setting any retry setting on a single node connection pool a NOOP, this is by design! -Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and -not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .SingleNodeConnection() - .Settings(s => s.DisablePing().MaximumRetries(10)) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(10)) { - { BadResponse, 9200 } - } - ); ----- +== MaxRetries +By default retry as many times as we have nodes. However retries still respect the request timeout. +Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can +but give up after 20 seconds + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall(r => r.MaxRetries(2)) { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { MaxRetriesReached } + } + ); +---- + +When you have a 100 node cluster you might want to ensure a fixed number of retries. +Remember that the actual number of requests is initial attempt + set number of retries + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(5)) + ); +audit = await audit.TraceCall( + new ClientCall(r => r.MaxRetries(2)) { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { MaxRetriesReached } + } + ); +---- + +This makes setting any retry setting on a single node connection pool a NOOP, this is by design! +Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and +not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .SingleNodeConnection() + .Settings(s => s.DisablePing().MaximumRetries(10)) + ); +audit = await audit.TraceCall( + new ClientCall(r => r.MaxRetries(10)) { + { BadResponse, 9200 } + } + ); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc index 04cbc4ae7a0..76322255b04 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc @@ -1,71 +1,71 @@ -Round Robin -Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. - - -== GetNext -GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance -over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without -suffering from noisy neighboors advancing a global cursor. - - -[source, csharp] ----- -var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); -var staticPool = new StaticConnectionPool(uris, randomize: false); -var sniffingPool = new SniffingConnectionPool(uris, randomize: false); -this.AssertCreateView(staticPool); -this.AssertCreateView(sniffingPool); ----- -Here we have setup a static connection pool seeded with 10 nodes. We force randomizationOnStartup to false -so that we can test the nodes being returned are int the order we expect them to. -So what order we expect? Imagine the following: -Thread A calls GetNext first without a local cursor and takes the current from the internal global cursor which is 0. -Thread B calls GetNext() second without a local cursor and therefor starts at 1. -After this each thread should walk the nodes in successive order using their local cursor -e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. - -[source, csharp] ----- -var startingPositions = Enumerable.Range(0, NumberOfNodes) - .Select(i => pool.CreateView().First()) - .Select(n => n.Uri.Port) - .ToList(); ----- -[source, csharp] ----- -var expectedOrder = Enumerable.Range(9200, NumberOfNodes); -startingPositions.Should().ContainInOrder(expectedOrder); ----- - -What the above code just proved is that each call to GetNext(null) gets assigned the next available node. - -Lets up the ante: -- call get next over `NumberOfNodes * 2` threads -- on each thread call getnext `NumberOfNodes * 10` times using a local cursor. -We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 -comes 9200 again - -[source, csharp] ----- -var threadedStartPositions = new ConcurrentBag(); ----- -[source, csharp] ----- -var threads = Enumerable.Range(0, 20) - .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) - .ToList(); -t.Start(); -t.Join(); ----- -Each thread reported the first node it started off lets make sure we see each node twice as the first node -because we started `NumberOfNodes * 2` threads - -[source, csharp] ----- -var grouped = threadedStartPositions.GroupBy(p => p).ToList(); ----- -[source, csharp] ----- -grouped.Count().Should().Be(NumberOfNodes); -grouped.Select(p => p.Count()).Should().OnlyContain(p => p == 2); ----- +Round Robin +Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. + + +== GetNext +GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance +over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without +suffering from noisy neighboors advancing a global cursor. + + +[source, csharp] +---- +var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); +var staticPool = new StaticConnectionPool(uris, randomize: false); +var sniffingPool = new SniffingConnectionPool(uris, randomize: false); +this.AssertCreateView(staticPool); +this.AssertCreateView(sniffingPool); +---- + +Here we have setup a static connection pool seeded with 10 nodes. We force randomizationOnStartup to false +so that we can test the nodes being returned are int the order we expect them to. +So what order we expect? Imagine the following: + +Thread A calls GetNext first without a local cursor and takes the current from the internal global cursor which is 0. +Thread B calls GetNext() second without a local cursor and therefor starts at 1. +After this each thread should walk the nodes in successive order using their local cursor +e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. + + +[source, csharp] +---- +var startingPositions = Enumerable.Range(0, NumberOfNodes) + .Select(i => pool.CreateView().First()) + .Select(n => n.Uri.Port) + .ToList(); + +var expectedOrder = Enumerable.Range(9200, NumberOfNodes); +startingPositions.Should().ContainInOrder(expectedOrder); +---- + +What the above code just proved is that each call to GetNext(null) gets assigned the next available node. + +Lets up the ante: +- call get next over `NumberOfNodes * 2` threads +- on each thread call getnext `NumberOfNodes * 10` times using a local cursor. +We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 +comes 9200 again + + +[source, csharp] +---- +var threadedStartPositions = new ConcurrentBag(); + +var threads = Enumerable.Range(0, 20) + .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) + .ToList(); +t.Start(); +t.Join(); +---- + +Each thread reported the first node it started off lets make sure we see each node twice as the first node +because we started `NumberOfNodes * 2` threads + + +[source, csharp] +---- +var grouped = threadedStartPositions.GroupBy(p => p).ToList(); + +grouped.Count().Should().Be(NumberOfNodes); +grouped.Select(p => p.Count()).Should().OnlyContain(p => p == 2); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc index 54688bd9f36..0cb4f4f4d5f 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc @@ -1,196 +1,175 @@ -Round Robin - Skipping Dead Nodes -When selecting nodes the connection pool will try and skip all the nodes that are marked dead. - - -== GetNext -GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance -over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without -suffering from noisy neighboors advancing a global cursor. - - -[source, csharp] ----- -var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -var pool = new StaticConnectionPool(seeds, randomize: false); -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9200); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); -var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -seeds.First().MarkDead(DateTime.Now.AddDays(1)); -var pool = new StaticConnectionPool(seeds, randomize: false); -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); ----- -After we marke the first node alive again we expect it to be hit again - -[source, csharp] ----- -seeds.First().MarkAlive(); ----- -[source, csharp] ----- -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9200); -var dateTimeProvider = new TestableDateTimeProvider(); -var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -seeds.First().MarkDead(dateTimeProvider.Now().AddDays(1)); -var pool = new StaticConnectionPool(seeds, randomize: false, dateTimeProvider: dateTimeProvider); -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); ----- -If we forward our clock 2 days the node that was marked dead until tomorrow (or yesterday!) should be resurrected - -[source, csharp] ----- -dateTimeProvider.ChangeTime(d => d.AddDays(2)); ----- -[source, csharp] ----- -var n = pool.CreateView().First(); -n.Uri.Port.Should().Be(9201); -n = pool.CreateView().First(); -n.Uri.Port.Should().Be(9202); -n = pool.CreateView().First(); -n.Uri.Port.Should().Be(9200); -n.IsResurrected.Should().BeTrue(); ----- -A cluster with 2 nodes where the second node fails on ping - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .ClientCalls(p => p.Succeeds(Always)) - .ClientCalls(p => p.OnPort(9201).FailAlways()) - .ClientCalls(p => p.OnPort(9203).FailAlways()) - .StaticConnectionPool() - .Settings(p=>p.DisablePing()) -); ----- -[source, csharp] ----- -await audit.TraceCalls( ----- -The first call goes to 9200 which succeeds - -[source, csharp] ----- -new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0) } - }, ----- -The 2nd call does a ping on 9201 because its used for the first time. -It fails so we wrap over to node 9202 - -[source, csharp] ----- -new ClientCall { - { BadResponse, 9201}, - { HealthyResponse, 9202}, ----- -Finally we assert that the connectionpool has one node that is marked as dead - -[source, csharp] ----- -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - }, ----- -The next call goes to 9203 which fails so we should wrap over - -[source, csharp] ----- -new ClientCall { - { BadResponse, 9203}, - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - } -); ----- -A cluster with 2 nodes where the second node fails on ping - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .ClientCalls(p => p.Fails(Always)) - .StaticConnectionPool() - .Settings(p=>p.DisablePing()) -); ----- -[source, csharp] ----- -await audit.TraceCalls( ----- -All the calls fail - -[source, csharp] ----- -new ClientCall { - { BadResponse, 9200}, - { BadResponse, 9201}, - { BadResponse, 9202}, - { BadResponse, 9203}, - { MaxRetriesReached }, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, ----- -After all our registered nodes are marked dead we want to sample a single dead node -each time to quickly see if the cluster is back up. We do not want to retry all 4 -nodes - -[source, csharp] ----- -new ClientCall { - { AllNodesDead }, - { Resurrection, 9201}, - { BadResponse, 9201}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9202}, - { BadResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9203}, - { BadResponse, 9203}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9200}, - { BadResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - } -); ----- +Round Robin - Skipping Dead Nodes +When selecting nodes the connection pool will try and skip all the nodes that are marked dead. + + +== GetNext +GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance +over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without +suffering from noisy neighboors advancing a global cursor. + + +[source, csharp] +---- +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +var pool = new StaticConnectionPool(seeds, randomize: false); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +seeds.First().MarkDead(DateTime.Now.AddDays(1)); +var pool = new StaticConnectionPool(seeds, randomize: false); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +---- +After we marke the first node alive again we expect it to be hit again + +[source, csharp] +---- +seeds.First().MarkAlive(); + +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +var dateTimeProvider = new TestableDateTimeProvider(); +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +seeds.First().MarkDead(dateTimeProvider.Now().AddDays(1)); +var pool = new StaticConnectionPool(seeds, randomize: false, dateTimeProvider: dateTimeProvider); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +---- +If we forward our clock 2 days the node that was marked dead until tomorrow (or yesterday!) should be resurrected + +[source, csharp] +---- +dateTimeProvider.ChangeTime(d => d.AddDays(2)); + +var n = pool.CreateView().First(); +n.Uri.Port.Should().Be(9201); +n = pool.CreateView().First(); +n.Uri.Port.Should().Be(9202); +n = pool.CreateView().First(); +n.Uri.Port.Should().Be(9200); +n.IsResurrected.Should().BeTrue(); +---- +A cluster with 2 nodes where the second node fails on ping + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .ClientCalls(p => p.Succeeds(Always)) + .ClientCalls(p => p.OnPort(9201).FailAlways()) + .ClientCalls(p => p.OnPort(9203).FailAlways()) + .StaticConnectionPool() + .Settings(p=>p.DisablePing()) +); +---- +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails so we wrap over to node 9202 + +Finally we assert that the connectionpool has one node that is marked as dead + +The next call goes to 9203 which fails so we should wrap over + +[source, csharp] +---- +await audit.TraceCalls( +new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0) } + }, +new ClientCall { + { BadResponse, 9201}, + { HealthyResponse, 9202}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + }, +new ClientCall { + { BadResponse, 9203}, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + } +); +---- +A cluster with 2 nodes where the second node fails on ping + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .ClientCalls(p => p.Fails(Always)) + .StaticConnectionPool() + .Settings(p=>p.DisablePing()) +); +---- +All the calls fail + +After all our registered nodes are marked dead we want to sample a single dead node +each time to quickly see if the cluster is back up. We do not want to retry all 4 +nodes + + +[source, csharp] +---- +await audit.TraceCalls( +new ClientCall { + { BadResponse, 9200}, + { BadResponse, 9201}, + { BadResponse, 9202}, + { BadResponse, 9203}, + { MaxRetriesReached }, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, +new ClientCall { + { AllNodesDead }, + { Resurrection, 9201}, + { BadResponse, 9201}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9202}, + { BadResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9203}, + { BadResponse, 9203}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9200}, + { BadResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + } +); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc index 33f1561476d..902a069e86a 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc @@ -15,14 +15,13 @@ callStatic.ShouldNotThrow(); ---- + [source, csharp] ---- var threads = Enumerable.Range(0, 50) .Select(i => CreateReadAndUpdateThread(pool)) .ToList(); ----- -[source, csharp] ----- + t.Start(); t.Join(); ---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc index ef2b68cd4cc..778eb9a4056 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc @@ -1,175 +1,152 @@ -== Sniffing on connection failure -Sniffing on connection is enabled by default when using a connection pool that allows reseeding. -The only IConnectionPool we ship that allows this is the SniffingConnectionPool. - -This can be very handy to force a refresh of the pools known healthy node by inspecting elasticsearch itself. -A sniff tries to get the nodes by asking each currently known node until one response. - - -Here we seed our connection with 5 known nodes 9200-9204 of which we think -9202, 9203, 9204 are master eligible nodes. Our virtualized cluster will throw once when doing -a search on 9201. This should a sniff to be kicked off. - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(5) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).Fails(Once)) ----- -When the call fails on 9201 the sniff succeeds and returns a new cluster of healty nodes -this cluster only has 3 nodes and the known masters are 9200 and 9202 but a search on 9201 -still fails once - -[source, csharp] ----- -.Sniff(p => p.SucceedAlways(Framework.Cluster - .Nodes(3) - .MasterEligible(9200, 9202) - .ClientCalls(r => r.OnPort(9201).Fails(Once)) ----- -After this second failure on 9201 another sniff will be returned a cluster that no -longer fails but looks completely different (9210-9212) we should be able to handle this - -[source, csharp] ----- -.Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(3, 9210) - .MasterEligible(9210, 9212) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s.DisablePing().SniffOnStartup(false)) -); ----- -[source, csharp] ----- -audit = await audit.TraceCalls( ----- - - -[source, csharp] ----- -new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(5) } - }, - new ClientCall { - { BadResponse, 9201}, ----- -We assert we do a sniff on our first known master node 9202 - -[source, csharp] ----- -{ SniffOnFail }, - { SniffSuccess, 9202}, - { HealthyResponse, 9200}, ----- -Our pool should now have three nodes - -[source, csharp] ----- -{ pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { - { BadResponse, 9201}, ----- -We assert we do a sniff on the first master node in our updated cluster - -[source, csharp] ----- -{ SniffOnFail }, - { SniffSuccess, 9200}, - { HealthyResponse, 9210}, - { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } } -); ----- -Here we set up our cluster exactly the same as the previous setup -Only we enable pinging (default is true) and make the ping fail - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(5) - .MasterEligible(9202, 9203, 9204) - .Ping(r => r.OnPort(9201).Fails(Once)) - .Sniff(p => p.SucceedAlways(Framework.Cluster - .Nodes(3) - .MasterEligible(9200, 9202) - .Ping(r => r.OnPort(9201).Fails(Once)) - .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(3, 9210) - .MasterEligible(9210, 9211) - .Ping(r => r.SucceedAlways()) - .Sniff(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup(false)) -); ----- -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { - { PingSuccess, 9200 }, - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(5) } - }, - new ClientCall { - { PingFailure, 9201}, ----- -We assert we do a sniff on our first known master node 9202 - -[source, csharp] ----- -{ SniffOnFail }, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200}, ----- -Our pool should now have three nodes - -[source, csharp] ----- -{ pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { - { PingFailure, 9201}, ----- -We assert we do a sniff on the first master node in our updated cluster - -[source, csharp] ----- -{ SniffOnFail }, - { SniffSuccess, 9200}, - { PingSuccess, 9210}, - { HealthyResponse, 9210}, - { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { { PingSuccess, 9211 }, { HealthyResponse, 9211 } }, - new ClientCall { { PingSuccess, 9212 }, { HealthyResponse, 9212 } }, ----- -9210 was already pinged after the sniff returned the new nodes - -[source, csharp] ----- -new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } } -); ----- +== Sniffing on connection failure +Sniffing on connection is enabled by default when using a connection pool that allows reseeding. +The only IConnectionPool we ship that allows this is the SniffingConnectionPool. + +This can be very handy to force a refresh of the pools known healthy node by inspecting elasticsearch itself. +A sniff tries to get the nodes by asking each currently known node until one response. + + + +Here we seed our connection with 5 known nodes 9200-9204 of which we think +9202, 9203, 9204 are master eligible nodes. Our virtualized cluster will throw once when doing +a search on 9201. This should a sniff to be kicked off. + + + +When the call fails on 9201 the sniff succeeds and returns a new cluster of healty nodes +this cluster only has 3 nodes and the known masters are 9200 and 9202 but a search on 9201 +still fails once + + + +After this second failure on 9201 another sniff will be returned a cluster that no +longer fails but looks completely different (9210-9212) we should be able to handle this + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(5) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).Fails(Once)) +.Sniff(p => p.SucceedAlways(Framework.Cluster + .Nodes(3) + .MasterEligible(9200, 9202) + .ClientCalls(r => r.OnPort(9201).Fails(Once)) +.Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(3, 9210) + .MasterEligible(9210, 9212) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s.DisablePing().SniffOnStartup(false)) +); +---- + + +We assert we do a sniff on our first known master node 9202 + +Our pool should now have three nodes + +We assert we do a sniff on the first master node in our updated cluster + +[source, csharp] +---- +audit = await audit.TraceCalls( +new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(5) } + }, + new ClientCall { + { BadResponse, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9202}, + { HealthyResponse, 9200}, +{ pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { + { BadResponse, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9200}, + { HealthyResponse, 9210}, + { pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } } +); +---- +Here we set up our cluster exactly the same as the previous setup +Only we enable pinging (default is true) and make the ping fail + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(5) + .MasterEligible(9202, 9203, 9204) + .Ping(r => r.OnPort(9201).Fails(Once)) + .Sniff(p => p.SucceedAlways(Framework.Cluster + .Nodes(3) + .MasterEligible(9200, 9202) + .Ping(r => r.OnPort(9201).Fails(Once)) + .Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(3, 9210) + .MasterEligible(9210, 9211) + .Ping(r => r.SucceedAlways()) + .Sniff(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup(false)) +); +---- +We assert we do a sniff on our first known master node 9202 + +Our pool should now have three nodes + +We assert we do a sniff on the first master node in our updated cluster + +9210 was already pinged after the sniff returned the new nodes + +[source, csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { + { PingSuccess, 9200 }, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(5) } + }, + new ClientCall { + { PingFailure, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200}, +{ pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { + { PingFailure, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9200}, + { PingSuccess, 9210}, + { HealthyResponse, 9210}, + { pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { { PingSuccess, 9211 }, { HealthyResponse, 9211 } }, + new ClientCall { { PingSuccess, 9212 }, { HealthyResponse, 9212 } }, +new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } } +); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc index d20b01abde4..58593850e06 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc @@ -1,97 +1,90 @@ -== Sniffing periodically - -Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. -In addition to sniffing on startup and sniffing on failures, sniffing periodically can benefit scenerio's where -clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes -but without sniffing periodically it will never find the nodes that have been added to help out with load - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(100) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(ss => ss.SucceedAlways(Framework.Cluster - .Nodes(10) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s - .DisablePing() - .SniffOnConnectionFault(false) - .SniffOnStartup(false) - .SniffLifeSpan(TimeSpan.FromMinutes(30)) - ) - ); ----- -healty cluster all nodes return healthy responses - -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9202 } }, - new ClientCall { { HealthyResponse, 9203 } }, - new ClientCall { { HealthyResponse, 9204 } }, - new ClientCall { { HealthyResponse, 9205 } }, - new ClientCall { { HealthyResponse, 9206 } }, - new ClientCall { { HealthyResponse, 9207 } }, - new ClientCall { { HealthyResponse, 9208 } }, - new ClientCall { { HealthyResponse, 9209 } }, - new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(10) } - } -); ----- -Now let's forward the clock 31 minutes, our sniff lifespan should now go state -and the first call should do a sniff which discovered we scaled up to a 100 nodes! - -[source, csharp] ----- -audit.ChangeTime(d => d.AddMinutes(31)); ----- -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { ----- -a sniff is done first and it prefers the first node master node - -[source, csharp] ----- -{ SniffOnStaleCluster }, - { SniffSuccess, 9202 }, - { HealthyResponse, 9201 }, - { pool => pool.Nodes.Count.Should().Be(100) } - } -); ----- -[source, csharp] ----- -audit.ChangeTime(d => d.AddMinutes(31)); ----- -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { ----- -a sniff is done first and it prefers the first node master node - -[source, csharp] ----- -{ SniffOnStaleCluster }, - { SniffSuccess, 9202 }, - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(10) } - } -); ----- +== Sniffing periodically + +Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. +In addition to sniffing on startup and sniffing on failures, sniffing periodically can benefit scenerio's where +clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes +but without sniffing periodically it will never find the nodes that have been added to help out with load + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(100) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(ss => ss.SucceedAlways(Framework.Cluster + .Nodes(10) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s + .DisablePing() + .SniffOnConnectionFault(false) + .SniffOnStartup(false) + .SniffLifeSpan(TimeSpan.FromMinutes(30)) + ) + ); +---- +healty cluster all nodes return healthy responses + +[source, csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9202 } }, + new ClientCall { { HealthyResponse, 9203 } }, + new ClientCall { { HealthyResponse, 9204 } }, + new ClientCall { { HealthyResponse, 9205 } }, + new ClientCall { { HealthyResponse, 9206 } }, + new ClientCall { { HealthyResponse, 9207 } }, + new ClientCall { { HealthyResponse, 9208 } }, + new ClientCall { { HealthyResponse, 9209 } }, + new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(10) } + } +); +---- +Now let's forward the clock 31 minutes, our sniff lifespan should now go state +and the first call should do a sniff which discovered we scaled up to a 100 nodes! + + +[source, csharp] +---- +audit.ChangeTime(d => d.AddMinutes(31)); +---- +a sniff is done first and it prefers the first node master node + +[source, csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { +{ SniffOnStaleCluster }, + { SniffSuccess, 9202 }, + { HealthyResponse, 9201 }, + { pool => pool.Nodes.Count.Should().Be(100) } + } +); + +audit.ChangeTime(d => d.AddMinutes(31)); +---- +a sniff is done first and it prefers the first node master node + +[source, csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { +{ SniffOnStaleCluster }, + { SniffSuccess, 9202 }, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(10) } + } +); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc b/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc index 1f27d68c313..411e888a1d5 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc @@ -1,119 +1,119 @@ -== Sniffing on startup - -Connection pools that return true for `SupportsReseeding` by default sniff on startup. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall - { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCalls( - new ClientCall - { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} - }, - new ClientCall - { - { PingSuccess, 9201}, - { HealthyResponse, 9201} - } - ); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always, Framework.Cluster.Nodes(8, startFrom: 9204))) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess, 9204}, - { HealthyResponse, 9204} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9209).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffFailure, 9202}, - { SniffFailure, 9203}, - { SniffFailure, 9204}, - { SniffFailure, 9205}, - { SniffFailure, 9206}, - { SniffFailure, 9207}, - { SniffFailure, 9208}, - { SniffSuccess, 9209}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(new[] { - new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, - new Node(new Uri("http://localhost:9201")) { MasterEligible = false }, - new Node(new Uri("http://localhost:9202")) { MasterEligible = true }, - }) - .Sniff(s => s.Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(new[] { - new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, - new Node(new Uri("http://localhost:9201")) { MasterEligible = true }, - new Node(new Uri("http://localhost:9202")) { MasterEligible = false }, - }) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} - }); ----- +== Sniffing on startup + +Connection pools that return true for `SupportsReseeding` by default sniff on startup. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() + ); +await audit.TraceCall(new ClientCall + { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} + }); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() + ); +await audit.TraceCalls( + new ClientCall + { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} + }, + new ClientCall + { + { PingSuccess, 9201}, + { HealthyResponse, 9201} + } + ); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always, Framework.Cluster.Nodes(8, startFrom: 9204))) + .SniffingConnectionPool() + .AllDefaults() + ); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess, 9204}, + { HealthyResponse, 9204} + }); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9209).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() + ); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffFailure, 9202}, + { SniffFailure, 9203}, + { SniffFailure, 9204}, + { SniffFailure, 9205}, + { SniffFailure, 9206}, + { SniffFailure, 9207}, + { SniffFailure, 9208}, + { SniffSuccess, 9209}, + { PingSuccess, 9200}, + { HealthyResponse, 9200} + }); +var audit = new Auditor(() => Framework.Cluster + .Nodes(new[] { + new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, + new Node(new Uri("http://localhost:9201")) { MasterEligible = false }, + new Node(new Uri("http://localhost:9202")) { MasterEligible = true }, + }) + .Sniff(s => s.Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() + ); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200} + }); +var audit = new Auditor(() => Framework.Cluster + .Nodes(new[] { + new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, + new Node(new Uri("http://localhost:9201")) { MasterEligible = true }, + new Node(new Uri("http://localhost:9202")) { MasterEligible = false }, + }) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() + ); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200} + }); +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc index 0ccfe32fdd1..67386673400 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc @@ -1,223 +1,231 @@ -# Covariant Search Results - -NEST directly supports returning covariant result sets. -Meaning a result can be typed to an interface or baseclass -but the actual instance type of the result can be that of the subclass directly - -Let look at an example, imagine we want to search over multiple types that all implement -`ISearchResult` - - - - -We have three implementations of `ISearchResult` namely `A`, `B` and `C` - - -The most straightforward way to search over multiple types is to -type the response to the parent interface or base class -and pass the actual types we want to search over using `.Types()` - -[source, csharp] ----- -var result = this._client.Search(s => s - .Type(Types.Type(typeof(A), typeof(B), typeof(C))) - .Size(100) -); ----- -Nest will translate this to a search over /index/a,b,c/_search. -hits that have `"_type" : "a"` will be serialized to `A` and so forth - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); ----- -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable -ISearchResult -` - -[source, csharp] ----- -result.Documents.Count().Should().Be(100); ----- -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); ----- -[source, csharp] ----- -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- -and assume that properties that only exist on the subclass itself are properly filled - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); ----- -[source, csharp] ----- -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- -A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to - -[source, csharp] ----- -var result = this._client.Search(s => s - .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) - .Size(100) -); ----- -here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` -and a typed `h` which represents the encapsulating hit. - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); ----- -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable -ISearchResult -` - -[source, csharp] ----- -result.Documents.Count().Should().Be(100); ----- -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); ----- -[source, csharp] ----- -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- -and assume that properties that only exist on the subclass itself are properly filled - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); ----- -[source, csharp] ----- -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- -Scroll also supports CovariantSearchResponses - - -Scroll() is a continuation of a previous Search() so Types() are lost. -You can hint the type types again using CovariantTypes() - -[source, csharp] ----- -var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s - .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) -); ----- -Nest will translate this to a search over /index/a,b,c/_search. -hits that have `"_type" : "a"` will be serialized to `A` and so forth - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); ----- -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable -ISearchResult -` - -[source, csharp] ----- -result.Documents.Count().Should().Be(100); ----- -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); ----- -[source, csharp] ----- -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- -and assume that properties that only exist on the subclass itself are properly filled - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); ----- -[source, csharp] ----- -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- -The more low level concrete type selector can also be specified on scroll - -[source, csharp] ----- -var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s - .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) -); ----- -here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` -and a typed `h` which represents the encapsulating hit. - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); ----- -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable -ISearchResult -` - -[source, csharp] ----- -result.Documents.Count().Should().Be(100); ----- -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); ----- -[source, csharp] ----- -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- -and assume that properties that only exist on the subclass itself are properly filled - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); ----- -[source, csharp] ----- -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- +# Covariant Search Results + +NEST directly supports returning covariant result sets. +Meaning a result can be typed to an interface or baseclass +but the actual instance type of the result can be that of the subclass directly + +Let look at an example, imagine we want to search over multiple types that all implement +`ISearchResult` + + + + +We have three implementations of `ISearchResult` namely `A`, `B` and `C` + + + +The most straightforward way to search over multiple types is to +type the response to the parent interface or base class +and pass the actual types we want to search over using `.Types()` + + +[source, csharp] +---- +var result = this._client.Search(s => s + .Type(Types.Type(typeof(A), typeof(B), typeof(C))) + .Size(100) +); +---- + +Nest will translate this to a search over /index/a,b,c/_search. +hits that have `"_type" : "a"` will be serialized to `A` and so forth + + + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + + +[source, csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + + +[source, csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + + +[source, csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to + + +[source, csharp] +---- +var result = this._client.Search(s => s + .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) + .Size(100) +); +---- + +here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` +and a typed `h` which represents the encapsulating hit. + + + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + + +[source, csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + + +[source, csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + + +[source, csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- +Scroll also supports CovariantSearchResponses + + + +Scroll() is a continuation of a previous Search() so Types() are lost. +You can hint the type types again using CovariantTypes() + + +[source, csharp] +---- +var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s + .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) +); +---- + +Nest will translate this to a search over /index/a,b,c/_search. +hits that have `"_type" : "a"` will be serialized to `A` and so forth + + + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + + +[source, csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + + +[source, csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + + +[source, csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +The more low level concrete type selector can also be specified on scroll + + +[source, csharp] +---- +var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s + .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) +); +---- + +here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` +and a typed `h` which represents the encapsulating hit. + + + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + + +[source, csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + + +[source, csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + + +[source, csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc index f493e031c5e..cf7c5ffb3dc 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc @@ -1,105 +1,98 @@ -# DocumentPaths -Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes -and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path -to your document more succintly - - -Manually newing - -here we create a new document path based on Project with the id 1 - -[source, csharp] ----- -IDocumentPath path = new DocumentPath(1); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); ----- -You can still override the inferred index and type name - -[source, csharp] ----- -path = new DocumentPath(1).Type("project1"); ----- -[source, csharp] ----- -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(1).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- -there is also a static way to describe such paths - -[source, csharp] ----- -path = DocumentPath.Id(1); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); -var project = new Project { Name = "hello-world" }; ----- -here we create a new document path based on a Project - -[source, csharp] ----- -IDocumentPath path = new DocumentPath(project); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect("hello-world").WhenSerializing(path.Id); ----- -You can still override the inferred index and type name - -[source, csharp] ----- -path = new DocumentPath(project).Type("project1"); ----- -[source, csharp] ----- -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(project).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- -there is also a static way to describe such paths - -[source, csharp] ----- -path = DocumentPath.Id(project); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect("hello-world").WhenSerializing(path.Id); -DocumentPath p = project; -var project = new Project { Name = "hello-world" }; ----- -Here we can see and example how DocumentPath helps your describe your requests more tersely - -[source, csharp] ----- -var request = new IndexRequest(2) { Document = project }; ----- -[source, csharp] ----- -request = new IndexRequest(project) { }; ----- -when comparing with the full blown constructor and passing document manually -DocumentPath -T -'s benefits become apparent. - -[source, csharp] ----- -request = new IndexRequest(IndexName.From(), TypeName.From(), 2) -{ - Document = project -}; ----- += DocumentPaths + +Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes +and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path +to your document more succintly + + +== Creating new instances + +here we create a new document path based on Project with the id 1 + +[source, csharp] +---- +IDocumentPath path = new DocumentPath(1); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect(1).WhenSerializing(path.Id); +---- +You can still override the inferred index and type name + +[source, csharp] +---- +path = new DocumentPath(1).Type("project1"); + +Expect("project1").WhenSerializing(path.Type); +path = new DocumentPath(1).Index("project1"); +Expect("project1").WhenSerializing(path.Index); +---- +there is also a static way to describe such paths + +[source, csharp] +---- +path = DocumentPath.Id(1); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect(1).WhenSerializing(path.Id); +---- +== Creating from a document type instance +if you have an instance of your document you can use it as well generate document paths + + +[source, csharp] +---- +var project = new Project { Name = "hello-world" }; +---- +here we create a new document path based on the instance of `Project`, project + +[source, csharp] +---- +IDocumentPath path = new DocumentPath(project); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect("hello-world").WhenSerializing(path.Id); +---- +You can still override the inferred index and type name + +[source, csharp] +---- +path = new DocumentPath(project).Type("project1"); + +Expect("project1").WhenSerializing(path.Type); +path = new DocumentPath(project).Index("project1"); +Expect("project1").WhenSerializing(path.Index); +---- +there is also a static way to describe such paths + +[source, csharp] +---- +path = DocumentPath.Id(project); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect("hello-world").WhenSerializing(path.Id); +DocumentPath p = project; +var project = new Project { Name = "hello-world" }; +---- +Here we can see and example how DocumentPath helps your describe your requests more tersely + +[source, csharp] +---- +var request = new IndexRequest(2) { Document = project }; + +request = new IndexRequest(project) { }; +---- +when comparing with the full blown constructor and passing document manually +`DocumentPath`'s benefits become apparent. + + +[source, csharp] +---- +request = new IndexRequest(IndexName.From(), TypeName.From(), 2) +{ + Document = project +}; +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc index 8701d88bf1d..277325a18f4 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc @@ -1,429 +1,404 @@ -# Strongly typed field access - -Several places in the elasticsearch API expect the path to a field from your original source document as a string. -NEST allows you to use C# expressions to strongly type these field path strings. - -These expressions are assigned to a type called `Field` and there are several ways to create a instance of that type - - -Using the constructor directly is possible but rather involved - -[source, csharp] ----- -var fieldString = new Field { Name = "name" }; ----- -especially when using C# expressions since these can not be simply new'ed - -[source, csharp] ----- -Expression> expression = p => p.Name; ----- -[source, csharp] ----- -var fieldExpression = Field.Create(expression); -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- -Therefore you can also implicitly convert strings and expressions to Field's - -[source, csharp] ----- -Field fieldString = "name"; ----- -but for expressions this is still rather involved - -[source, csharp] ----- -Expression> expression = p => p.Name; ----- -[source, csharp] ----- -Field fieldExpression = expression; -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- -to ease creating Field's from expressions there is a static Property class you can use - -[source, csharp] ----- -Field fieldString = "name"; ----- -but for expressions this is still rather involved - -[source, csharp] ----- -var fieldExpression = Infer.Field(p => p.Name); ----- -Using static imports in c# 6 this can be even shortened: -using static Nest.Static; - -[source, csharp] ----- -fieldExpression = Field(p => p.Name); ----- -Now this is much much terser then our first example using the constructor! - -[source, csharp] ----- -Expect("name") - .WhenSerializing(fieldString) - .WhenSerializing(fieldExpression); ----- -By default NEST will camelCase all the field names to be more javascripty - -using DefaultFieldNameInferrer() on ConnectionSettings you can change this behavior - -[source, csharp] ----- -var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); ----- -[source, csharp] ----- -setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); ----- -However string are *always* passed along verbatim - -[source, csharp] ----- -setup.Expect("NaMe").WhenSerializing("NaMe"); ----- -if you want the same behavior for expressions simply do nothing in the default inferrer - -[source, csharp] ----- -setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); ----- -[source, csharp] ----- -setup.Expect("Name").WhenSerializing(Field(p => p.Name)); ----- -Complex field name expressions - -You can follow your property expression to any depth, here we are traversing to the LeadDeveloper's (Person) FirstName - -[source, csharp] ----- -Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ----- -When dealing with collection index access is ingnored allowing you to traverse into properties of collections - -[source, csharp] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ----- -Similarly .First() also works, remember these are expressions and not actual code that will be executed - -[source, csharp] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); ----- -[source, csharp] ----- -Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); -Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); ----- -When we see an indexer on a dictionary we assume they describe property names - -[source, csharp] ----- -Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); ----- -[source, csharp] ----- -Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); ----- -A cool feature here is that we'll evaluate variables passed to these indexers - -[source, csharp] ----- -var variable = "var"; ----- -[source, csharp] ----- -Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); -Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ----- -If you are using elasticearch's multifield mapping (you really should!) these "virtual" sub fields -do not always map back on to your POCO, by calling .Suffix() you describe the sub fields that do not live in your c# objects - -[source, csharp] ----- -Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); ----- -[source, csharp] ----- -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); -Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); -Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); -Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); ----- -You can even chain them to any depth! - -[source, csharp] ----- -Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ----- -Variables passed to suffix will be evaluated as well - -[source, csharp] ----- -var suffix = "unanalyzed"; ----- -[source, csharp] ----- -Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); -Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); ----- - -Suffixes can be appended to expressions. This is useful in cases where you want to apply the same suffix -to a list of fields - - - - -[source, csharp] ----- -var expressions = new List>> -{ - p => p.Name, - p => p.Description, - p => p.CuratedTags.First().Name, - p => p.LeadDeveloper.FirstName -}; ----- -append the suffix "raw" to each expression - -[source, csharp] ----- -var fieldExpressions = - expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); ----- -[source, csharp] ----- -Expect("name.raw").WhenSerializing(fieldExpressions[0]); -Expect("description.raw").WhenSerializing(fieldExpressions[1]); -Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); -Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); ----- -Annotations - -When using NEST's property attributes you can specify a new name for the properties - -[source, csharp] ----- -public class BuiltIn -{ - [String(Name = "naam")] - public string Name { get; set; } -} ----- -[source, csharp] ----- -Expect("naam").WhenSerializing(Field(p => p.Name)); ----- - -Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. -Here we ask the default JsonNetSerializer and it takes JsonProperty into account - -[source, csharp] ----- -public class SerializerSpecific -{ - [JsonProperty("nameInJson")] - public string Name { get; set; } -} ----- -[source, csharp] ----- -Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ----- - -If both are specified NEST takes precedence though - -[source, csharp] ----- -public class Both -{ - [String(Name = "naam")] - [JsonProperty("nameInJson")] - public string Name { get; set; } -} ----- -[source, csharp] ----- -Expect("naam").WhenSerializing(Field(p => p.Name)); -Expect(new - { - naam = "Martijn Laarman" - }).WhenSerializing(new Both { Name = "Martijn Laarman" }); ----- -[source, csharp] ----- -class A { public C C { get; set; } } ----- -[source, csharp] ----- -class B { public C C { get; set; } } ----- -[source, csharp] ----- -class C -{ - public string Name { get; set; } -} ----- - -Resolving field names is cached but this is per connection settings - - -[source, csharp] ----- -var connectionSettings = TestClient.CreateSettings(forceInMemory: true); -var client = new ElasticClient(connectionSettings); -var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); -var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); ----- -Here we have to similary shaped expressions on coming from A and on from B -that will resolve to the same field name, as expected - -[source, csharp] ----- -fieldNameOnA.Should().Be("c.name"); ----- -[source, csharp] ----- -fieldNameOnB.Should().Be("c.name"); ----- -now we create a new connectionsettings with a remap for C on class A to `d` -now when we resolve the field path for A will be different - -[source, csharp] ----- -var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s - .InferMappingFor(m => m - .Rename(p => p.C, "d") - ) -); ----- -[source, csharp] ----- -var newClient = new ElasticClient(newConnectionSettings); -fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); -fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); -fieldNameOnA.Should().Be("d.name"); -fieldNameOnB.Should().Be("c.name"); ----- -however we didn't break inferrence on the first client instance using its separate connectionsettings - -[source, csharp] ----- -fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); ----- -[source, csharp] ----- -fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); -fieldNameOnA.Should().Be("c.name"); -fieldNameOnB.Should().Be("c.name"); ----- -To wrap up lets showcase the precedence that field names are inferred -1. A hard rename of the property on connection settings using Rename() -2. A NEST property mapping -3. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. -4. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases -In the following example we have a class where each case wins - -[source, csharp] ----- -class Precedence -{ ----- -Eventhough this property has a NEST property mapping and a JsonProperty attribute -We are going to provide a hard rename for it on ConnectionSettings later that should win. - -[source, csharp] ----- -[String(Name = "renamedIgnoresNest")] - [JsonProperty("renamedIgnoresJsonProperty")] - public string RenamedOnConnectionSettings { get; set; } ----- -This property has both a NEST attribute and a JsonProperty, NEST should win. - -[source, csharp] ----- -[String(Name = "nestAtt")] - [JsonProperty("jsonProp")] - public string NestAttribute { get; set; } ----- -We should take the json property into account by itself - -[source, csharp] ----- -[JsonProperty("jsonProp")] - public string JsonProperty { get; set; } ----- -This property we are going to special case in our custom serializer to resolve to `ask` - -[source, csharp] ----- -[JsonProperty("dontaskme")] - public string AskSerializer { get; set; } ----- -We are going to register a DefaultFieldNameInferrer on ConnectionSettings -that will uppercase all properties. - -[source, csharp] ----- -public string DefaultFieldNameInferrer { get; set; } - -} ----- -[source, csharp] ----- -var usingSettings = WithConnectionSettings(s => s ----- -here we provide an explicit rename of a property on connectionsettings - -[source, csharp] ----- -.InferMappingFor(m => m - .Rename(p => p.RenamedOnConnectionSettings, "renamed") - ) ----- -All properties that are not mapped verbatim should be uppercased - -[source, csharp] ----- -.DefaultFieldNameInferrer(p => p.ToUpperInvariant()) -).WithSerializer(s => new CustomSerializer(s)); ----- -[source, csharp] ----- -usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); -usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); -usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); -usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); -usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); ----- -The same rules apply when indexing an object - -[source, csharp] ----- -usingSettings.Expect(new [] -{ - "ask", - "DEFAULTFIELDNAMEINFERRER", - "jsonProp", - "nestAtt", - "renamed" -}).AsPropertiesOf(new Precedence -{ - RenamedOnConnectionSettings = "renamed on connection settings", - NestAttribute = "using a nest attribute", - JsonProperty = "the default serializer resolves json property attributes", - AskSerializer = "serializer fiddled with this one", - DefaultFieldNameInferrer = "shouting much?" -}); ----- += Strongly typed field access + +Several places in the elasticsearch API expect the path to a field from your original source document as a string. +NEST allows you to use C# expressions to strongly type these field path strings. + +These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: + + +Using the constructor directly is possible but rather involved + +[source, csharp] +---- +var fieldString = new Field { Name = "name" }; +---- +especially when using C# expressions since these can not be simply new'ed + +[source, csharp] +---- +Expression> expression = p => p.Name; + +var fieldExpression = Field.Create(expression); +Expect("name") + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); +---- +Therefore you can also implicitly convert strings and expressions to `Field`s + +[source, csharp] +---- +Field fieldString = "name"; +---- +but for expressions this is still rather involved + +[source, csharp] +---- +Expression> expression = p => p.Name; + +Field fieldExpression = expression; +Expect("name") + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); +---- +to ease creating `Field`s from expressions there is a static Property class you can use + +[source, csharp] +---- +Field fieldString = "name"; +---- +but for expressions this is still rather involved + +[source, csharp] +---- +var fieldExpression = Infer.Field(p => p.Name); +---- +this can be even shortened even further using static imports in c# 6 i.e. +`using static Nest.Static;` + + +[source, csharp] +---- +fieldExpression = Field(p => p.Name); +---- +Now this is much much terser then our first example using the constructor! + +[source, csharp] +---- +Expect("name") + .WhenSerializing(fieldString) + .WhenSerializing(fieldExpression); +---- +By default, NEST will camel-case all field names to be more _javascript-y_ + +using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior + +[source, csharp] +---- +var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); + +setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); +---- +However string are *always* passed along verbatim + +[source, csharp] +---- +setup.Expect("NaMe").WhenSerializing("NaMe"); +---- +if you want the same behavior for expressions simply do nothing in the default inferrer + +[source, csharp] +---- +setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); + +setup.Expect("Name").WhenSerializing(Field(p => p.Name)); +---- +== Complex field name expressions + +You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName + +[source, csharp] +---- +Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); +---- +When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections + +[source, csharp] +---- +Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); +---- +Similarly, LINQ's `.First()` method also works +NOTE: remember these are expressions and not actual code that will be executed + +[source, csharp] +---- +Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); + +Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); +Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); +---- +An indexer on a dictionary is assumed to describe a property name + +[source, csharp] +---- +Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); + +Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); +---- +A cool feature here is that we'll evaluate variables passed to an indexer + +[source, csharp] +---- +var variable = "var"; + +Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); +Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); +---- +:multifieldlink: https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html +If you are using elasticearch's {multifieldlink}[multi_fields], which you really should as they allow +you to analyze a string in a number of different ways, these _"virtual"_ sub fields +do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that +should be mapped. + + +[source, csharp] +---- +Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); + +Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); +Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); +Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); +Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); +Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); +---- + +You can even chain `.Suffix()` calls to any depth! + + +[source, csharp] +---- +Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); +---- +Variables passed to suffix will be evaluated as well + +[source, csharp] +---- +var suffix = "unanalyzed"; + +Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); +Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); +---- + +Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix +to a list of fields. + + +Here we have a list of expressions + +[source, csharp] +---- +var expressions = new List>> +{ + p => p.Name, + p => p.Description, + p => p.CuratedTags.First().Name, + p => p.LeadDeveloper.FirstName +}; +---- +and we want to append the suffix "raw" to each + +[source, csharp] +---- +var fieldExpressions = + expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); + +Expect("name.raw").WhenSerializing(fieldExpressions[0]); +Expect("description.raw").WhenSerializing(fieldExpressions[1]); +Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); +Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); +---- +== Annotations + +When using NEST's property attributes you can specify a new name for the properties + + +[source, csharp] +---- +public class BuiltIn +{ + [String(Name = "naam")] + public string Name { get; set; } +} + +Expect("naam").WhenSerializing(Field(p => p.Name)); +---- + +Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. +Here we ask the default `JsonNetSerializer` to resolve a property name and it takes +the `JsonPropertyAttribute` into account + + +[source, csharp] +---- +public class SerializerSpecific +{ + [JsonProperty("nameInJson")] + public string Name { get; set; } +} + +Expect("nameInJson").WhenSerializing(Field(p => p.Name)); +---- + +If both a NEST property attribute and a serializer specific attribute are present on a property, +NEST takes precedence + + +[source, csharp] +---- +public class Both +{ + [String(Name = "naam")] + [JsonProperty("nameInJson")] + public string Name { get; set; } +} + +Expect("naam").WhenSerializing(Field(p => p.Name)); +Expect(new + { + naam = "Martijn Laarman" + }).WhenSerializing(new Both { Name = "Martijn Laarman" }); +---- + +Resolution of field names is cached per connection settings instance. To demonstrate, +take the following simple POCOs + + +[source, csharp] +---- +class A { public C C { get; set; } } + +class B { public C C { get; set; } } + +class C { public string Name { get; set; } } + +var connectionSettings = TestClient.CreateSettings(forceInMemory: true); +var client = new ElasticClient(connectionSettings); +var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); +var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); +---- + +Here we have to similary shaped expressions on coming from A and on from B +that will resolve to the same field name, as expected + + +[source, csharp] +---- +fieldNameOnA.Should().Be("c.name"); + +fieldNameOnB.Should().Be("c.name"); +---- + +now we create a new connectionsettings with a remap for C on class A to `d` +now when we resolve the field path for A will be different + + +[source, csharp] +---- +var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s + .InferMappingFor(m => m + .Rename(p => p.C, "d") + ) +); + +var newClient = new ElasticClient(newConnectionSettings); +fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); +fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); +fieldNameOnA.Should().Be("d.name"); +fieldNameOnB.Should().Be("c.name"); +---- +however we didn't break inferrence on the first client instance using its separate connectionsettings + +[source, csharp] +---- +fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); + +fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); +fieldNameOnA.Should().Be("c.name"); +fieldNameOnB.Should().Be("c.name"); +---- + +To wrap up, the precedence in which field names are inferred is: + +. A hard rename of the property on connection settings using `.Rename()` +. A NEST property mapping +. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. +. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases + +The following example class will demonstrate this precedence + + +[source, csharp] +---- +class Precedence +{ + // Even though this property has a NEST property mapping and a JsonProperty attribute, + // We are going to provide a hard rename for it on ConnectionSettings later that should win. + [String(Name = "renamedIgnoresNest")] + [JsonProperty("renamedIgnoresJsonProperty")] + public string RenamedOnConnectionSettings { get; set; } + + // This property has both a NEST attribute and a JsonProperty, NEST should win. + [String(Name = "nestAtt")] + [JsonProperty("jsonProp")] + public string NestAttribute { get; set; } + + // We should take the json property into account by itself + [JsonProperty("jsonProp")] + public string JsonProperty { get; set; } + + // This property we are going to special case in our custom serializer to resolve to ask + [JsonProperty("dontaskme")] + public string AskSerializer { get; set; } + + // We are going to register a DefaultFieldNameInferrer on ConnectionSettings + // that will uppercase all properties. + public string DefaultFieldNameInferrer { get; set; } +} +---- + +Here we create a custom serializer that renames any property named `AskSerializer` to `ask` + + +[source, csharp] +---- +class CustomSerializer : JsonNetSerializer +{ + public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } + + public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) + { + return memberInfo.Name == nameof(Precedence.AskSerializer) + ? new PropertyMapping { Name = "ask" } + : base.CreatePropertyMapping(memberInfo); + } +} +---- +here we provide an explicit rename of a property on connectionsettings using `.Rename()` +and all properties that are not mapped verbatim should be uppercased + + +[source, csharp] +---- +var usingSettings = WithConnectionSettings(s => s + + .InferMappingFor(m => m + .Rename(p => p.RenamedOnConnectionSettings, "renamed") + ) + .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) +).WithSerializer(s => new CustomSerializer(s)); + +usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); +usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); +usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); +usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); +usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); +---- +The same naming rules also apply when indexing a document + +[source, csharp] +---- +usingSettings.Expect(new [] +{ + "ask", + "DEFAULTFIELDNAMEINFERRER", + "jsonProp", + "nestAtt", + "renamed" +}).AsPropertiesOf(new Precedence +{ + RenamedOnConnectionSettings = "renamed on connection settings", + NestAttribute = "using a nest attribute", + JsonProperty = "the default serializer resolves json property attributes", + AskSerializer = "serializer fiddled with this one", + DefaultFieldNameInferrer = "shouting much?" +}); +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc index b5818a65d59..c927ec2443f 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc @@ -1,98 +1,98 @@ -# Ids - -Several places in the elasticsearch API expect an Id object to be passed. This is a special box type that you can implicitly convert to and from many value types. - - -Methods that take an Id can be passed longs, ints, strings & Guids and they will implicitly converted to Ids - -[source, csharp] ----- -Id idFromInt = 1; -Id idFromLong = 2L; -Id idFromString = "hello-world"; -Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); -Expect(1).WhenSerializing(idFromInt); -Expect(2).WhenSerializing(idFromLong); -Expect("hello-world").WhenSerializing(idFromString); -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); ----- -Sometimes a method takes an object and we need an Id from that object to build up a path. -There is no implicit conversion from any object to Id but we can call Id.From. -Imagine your codebase has the following type that we want to index into elasticsearch - -[source, csharp] ----- -class MyDTO -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } -} ----- -By default NEST will try to find a property called `Id` on the class using reflection -and create a cached fast func delegate based on the properties getter - -[source, csharp] ----- -var dto = new MyDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; ----- -[source, csharp] ----- -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); ----- -Using the connection settings you can specify a different property NEST should look for ids. -Here we instruct NEST to infer the Id for MyDTO based on its Name property - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.Name) - ) -).Expect("x").WhenInferringIdOn(dto); ----- -Even though we have a cache at play the cache is per connection settings, so we can create a different config - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- -Another way is to mark the type with an ElasticType attribute, using a string IdProperty - -[source, csharp] ----- -[ElasticsearchType(IdProperty = nameof(Name))] -class MyOtherDTO -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } -} ----- -Now when we infer the id we expect it to be the Name property without doing any configuration on the ConnectionSettings - -[source, csharp] ----- -var dto = new MyOtherDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; ----- -[source, csharp] ----- -Expect("x").WhenInferringIdOn(dto); ----- -This attribute IS cached statically/globally, however connectionsettings with a config for the type will -still win over this static configuration - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- -Eventhough we have a cache at play the cache its per connection settings, so we can create a different config - += Ids + +Several places in the elasticsearch API expect an Id object to be passed. +This is a special box type that you can implicitly convert to and from many value types. + + +Methods that take an Id can be passed longs, ints, strings & Guids and they will be implicitly converted to Ids + +[source, csharp] +---- +Id idFromInt = 1; +Id idFromLong = 2L; +Id idFromString = "hello-world"; +Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); +Expect(1).WhenSerializing(idFromInt); +Expect(2).WhenSerializing(idFromLong); +Expect("hello-world").WhenSerializing(idFromString); +Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); +---- +Sometimes a method takes an object and we need an Id from that object to build up a path. +There is no implicit conversion from any object to Id but we can call `Id.From`. + +Imagine your codebase has the following type that we want to index into elasticsearch + + +[source, csharp] +---- +class MyDTO +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } +} +---- +By default NEST will try to find a property called `Id` on the class using reflection +and create a cached fast func delegate based on the properties getter + +[source, csharp] +---- +var dto = new MyDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; + +Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); +---- +Using the connection settings you can specify a different property NEST should look for ids. +Here we instruct NEST to infer the Id for MyDTO based on its Name property + +[source, csharp] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.Name) + ) +).Expect("x").WhenInferringIdOn(dto); +---- +Even though we have a cache at play the cache is per connection settings, so we can create a different config + +[source, csharp] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) +).Expect("y").WhenInferringIdOn(dto); +---- +Another way is to mark the type with an `ElasticsearchType` attribute, using a string `IdProperty` + +[source, csharp] +---- +[ElasticsearchType(IdProperty = nameof(Name))] +class MyOtherDTO +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } +} +---- +Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the ConnectionSettings + +[source, csharp] +---- +var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; + +Expect("x").WhenInferringIdOn(dto); +---- +This attribute *is* cached statically/globally, however connectionsettings with a config for the type will +still win over this static configuration. + +Even though we have a cache at play the cache its per connection settings, so we can create a different config + + +[source, csharp] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) +).Expect("y").WhenInferringIdOn(dto); +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc index c6c5a78f898..2b12be8ad23 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc @@ -1,47 +1,45 @@ -# Indices paths - -Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices -In nest this is encoded using `Indices` - - -Several types implicitly convert to `Indices` - -[source, csharp] ----- -Nest.Indices singleIndexFromString = "name"; -Nest.Indices multipleIndicesFromString = "name1, name2"; -Nest.Indices allFromString = "_all"; -Nest.Indices allWithOthersFromString = "_all, name2"; -singleIndexFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(1).And.Contain("name") - ); -multipleIndicesFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(2).And.Contain("name2") - ); -allFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() - ); -allWithOthersFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() - ); ----- -to ease creating Field's from expressions there is a static Property class you can use - - - -[source, csharp] ----- -var all = Nest.Indices.All; ----- -[source, csharp] ----- -var many = Nest.Indices.Index("name1", "name2"); -var manyTyped = Nest.Indices.Index().And(); -var singleTyped = Nest.Indices.Index(); -var singleString = Nest.Indices.Index("name1"); -var invalidSingleString = Nest.Indices.Index("name1, name2"); ----- +# Indices paths + +Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices +In nest this is encoded using `Indices` + + +Several types implicitly convert to `Indices` + +[source, csharp] +---- +Nest.Indices singleIndexFromString = "name"; +Nest.Indices multipleIndicesFromString = "name1, name2"; +Nest.Indices allFromString = "_all"; +Nest.Indices allWithOthersFromString = "_all, name2"; +singleIndexFromString.Match( + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(1).And.Contain("name") + ); +multipleIndicesFromString.Match( + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(2).And.Contain("name2") + ); +allFromString.Match( + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() + ); +allWithOthersFromString.Match( + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() + ); +---- +to ease creating Field's from expressions there is a static Property class you can use + + + +[source, csharp] +---- +var all = Nest.Indices.All; + +var many = Nest.Indices.Index("name1", "name2"); +var manyTyped = Nest.Indices.Index().And(); +var singleTyped = Nest.Indices.Index(); +var singleString = Nest.Indices.Index("name1"); +var invalidSingleString = Nest.Indices.Index("name1, name2"); +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc index d21a723cd1b..b7cd1b429f4 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc @@ -1,6 +1,27 @@ -[source, csharp] ----- -Expression> expression = p => p.Name.Suffix("raw"); -Expect("raw").WhenSerializing(expression); -Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); ----- + +Property names resolve to the last token. An example using the `.Suffix()` extension + + +[source, csharp] +---- +Expression> expression = p => p.Name.Suffix("raw"); +Expect("raw").WhenSerializing(expression); +---- + +And an example using the `.ApplySuffix()` extension on lambda expressions + + +[source, csharp] +---- +Expression> expression = p => p.Name; +expression.AppendSuffix("raw"); +Expect("raw").WhenSerializing(expression); +---- +Property names cannot contain a `.` in order to prevent the potential for collision with a field that +may have https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html[`multi_fields`] + + +[source, csharp] +---- +Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); +---- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc index 9db88699059..4d9740b2209 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc @@ -8,10 +8,12 @@ in order for your attributes to be applied. We'll look at examples of both. + For these examples, we'll define two POCOS. A Company, which has a name and a collection of Employees. And Employee, which has various properties of different types, and itself has a collection of Employees. + [source, csharp] ---- public class Company @@ -19,9 +21,7 @@ public class Company public string Name { get; set; } public List Employees { get; set; } } ----- -[source, csharp] ----- + public class Employee { public string FirstName { get; set; } @@ -37,6 +37,7 @@ public class Employee To create a mapping for our Company type, we can use the fluent API and map each property explicitly + [source, csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") @@ -65,10 +66,12 @@ var descriptor = new CreateIndexDescriptor("myindex") ) ); ---- + Which is all fine and dandy, and useful for some use cases. However in most cases this is becomes too cumbersome of an approach, and you simply just want to map *all* the properties of your POCO in a single go. + [source, csharp] ---- var expected = new @@ -106,15 +109,14 @@ var expected = new } } }; ----- -[source, csharp] ----- + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- ## Simple Automapping This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work + [source, csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") @@ -123,6 +125,7 @@ var descriptor = new CreateIndexDescriptor("myindex") .Map(m => m.AutoMap()) ); ---- + Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. In this example, - Birthday was mapped as a date, @@ -132,6 +135,7 @@ In this example, - Employees as an object and the remaining string properties as strings. + [source, csharp] ---- var expected = new @@ -221,21 +225,21 @@ var expected = new } } }; ----- -[source, csharp] ----- + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- ## Automapping with overrides In most cases, you'll want to map more than just the vanilla datatypes and also provide various options on your properties (analyzer, doc_values, etc...). In that case, it's -possible to use AutoMap() in conjuction with explicitly mapped properties. +possible to use AutoMap() in conjuction with explicitly mapped properties. + Here we are using AutoMap() to automatically map our company type, but then we're overriding our employee property and making it a `nested` type, since by default, AutoMap() will infer objects as `object`. + [source, csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") @@ -252,9 +256,7 @@ var descriptor = new CreateIndexDescriptor("myindex") ) ) ); ----- -[source, csharp] ----- + var expected = new { mappings = new @@ -280,9 +282,10 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- ## Automap with attributes It is also possible to define your mappings using attributes on your POCOS. When you -use attributes, you MUST use AutoMap() in order for the attributes to be applied. +use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. Here we define the same two types but this time using attributes. + [source, csharp] ---- [ElasticsearchType(Name = "company")] @@ -297,9 +300,7 @@ public class CompanyWithAttributes [Object(Path = "employees", Store = false)] public List Employees { get; set; } } ----- -[source, csharp] ----- + [ElasticsearchType(Name = "employee")] public class EmployeeWithAttributes { @@ -323,6 +324,10 @@ public class EmployeeWithAttributes public List Employees { get; set; } } ---- + +Then map the types by calling `.AutoMap()` + + [source, csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") @@ -461,7 +466,7 @@ var expected = new } } }; -Expect(expected).WhenSerializing(descriptor as ICreateIndexRequest); +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- Just as we were able to override the inferred properties in our earlier example, explicit (manual) @@ -627,6 +632,19 @@ var expected = new }; Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- +== Ignoring Properties +Properties on a POCO can be ignored in a few ways: + +- Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO + +- Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings + +- Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` + +This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the +property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` + + [source, csharp] ---- [ElasticsearchType(Name = "company")] @@ -643,35 +661,17 @@ public class CompanyWithAttributesAndPropertiesToIgnore public string JsonIgnoredProperty { get; set; } } ---- -== Ignoring Properties -Properties on a POCO can be ignored in a few ways: - - - -- Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO - - - -- Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings - - - -- Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used and inspected inside of `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` - - - -This example demonstrates all ways, using the attribute way to ignore the property `PropertyToIgnore`, the infer mapping way to ignore the -property `AnotherPropertyToIgnore` and the json serializer specific attribute way to ignore the property `JsonIgnoredProperty` - +All of the properties except `Name` have been ignored in the mapping [source, csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - ) - ); + .Mappings(ms => ms + .Map(m => m + .AutoMap() + ) + ); + var expected = new { mappings = new @@ -695,16 +695,19 @@ var settings = WithConnectionSettings(s => s ); settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- -If you notice in our previous Company/Employee examples, the Employee type is recursive -in that itself contains a collection of type `Employee`. By default, `.AutoMap()` will only +== Mapping Recursion +If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive +in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only traverse a single depth when it encounters recursive instances like this. Hence, in the -previous examples, the second level of Employee did not get any of its properties mapped. +previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. This is done as a safe-guard to prevent stack overflows and all the fun that comes with infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is often an edge case to have deeply nested mappings like this. However, you may still have -the need to do this, so you can control the recursion depth of AutoMap(). -Let's introduce a very simple class A, to reduce the noise, which itself has a property -Child of type A. +the need to do this, so you can control the recursion depth of `.AutoMap()`. + +Let's introduce a very simple class, `A`, which itself has a property +Child of type `A`. + [source, csharp] ---- @@ -713,7 +716,7 @@ public class A public A Child { get; set; } } ---- -By default, AutoMap() only goes as far as depth 1 +By default, `.AutoMap()` only goes as far as depth 1 [source, csharp] ---- @@ -743,9 +746,7 @@ var expected = new } } }; ----- -[source, csharp] ----- + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- Now lets specify a maxRecursion of 3 @@ -757,7 +758,7 @@ var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") .Map(m => m.AutoMap(3)) ); ---- -AutoMap() has now mapped three levels of our Child property +`.AutoMap()` has now mapped three levels of our Child property [source, csharp] ---- @@ -799,12 +800,37 @@ var expectedWithMaxRecursion = new } } }; + +Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); ---- +== Applying conventions through the Visitor pattern +It is also possible to apply a transformation on all or specific properties. + +AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, +does nothing and acts as a blank canvas for you to implement your own visiting methods. + +For instance, lets create a custom visitor that disables doc values for numeric and boolean types. +(Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) + + [source, csharp] ---- -Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); +public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor +{ + // Override the Visit method on INumberProperty and set DocValues = false + public override void Visit(INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + type.DocValues = false; + } + + // Similarily, override the Visit method on IBooleanProperty and set DocValues = false + public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + type.DocValues = false; + } +} ---- -Now we can pass an instance of our custom visitor to AutoMap() +Now we can pass an instance of our custom visitor to `.AutoMap()` [source, csharp] ---- @@ -813,9 +839,10 @@ var descriptor = new CreateIndexDescriptor("myindex") .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) ); ---- -and anytime it maps a property as a number (INumberProperty) or boolean (IBooleanProperty) +and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) it will apply the transformation defined in each Visit() respectively, which in this example -disables doc values. +disables https://www.elastic.co/guide/en/elasticsearch/guide/current/doc-values.html[doc values]. + [source, csharp] ---- @@ -859,8 +886,18 @@ var expected = new } }; ---- +You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit +directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types +to an Elasticsearch string (`IStringProperty`). + + [source, csharp] ---- +public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor +{ + public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); +} + var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms .Map(m => m.AutoMap(new EverythingIsAStringPropertyVisitor())) diff --git a/docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc b/docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc index 41ac4fd0d1b..4aabac1d5b1 100644 --- a/docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc @@ -1,291 +1,322 @@ -# Connecting -Connecting to *Elasticsearch* with `Elasticsearch.Net` is quite easy but has a few toggles and options worth knowing. - -# Choosing the right connection strategy -If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` - - -[source, csharp] ----- -var client = new ElasticLowLevelClient(); -var tokenizers = new TokenizersDescriptor(); ----- - -If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then -you will need to pass in some instance of `IConnectionConfigurationValues`. - -The easiest way to do this is: - - -[source, csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); -var config = new ConnectionConfiguration(node); -var client = new ElasticLowLevelClient(config); ----- - -This however is still a non-failover connection. Meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. - -To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. - - -[source, csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); -var connectionPool = new SniffingConnectionPool(new[] { node }); -var config = new ConnectionConfiguration(connectionPool); -var client = new ElasticLowLevelClient(config); ----- - -Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. -Be sure to read more about [Connection Pooling and Cluster Failover here](/elasticsearch-net/cluster-failover.html) - -## Options - -Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: - - -[source, csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); -var connectionPool = new SniffingConnectionPool(new[] { node }); -var config = new ConnectionConfiguration(connectionPool) - .DisableDirectStreaming() - .BasicAuthentication("user", "pass") - .RequestTimeout(TimeSpan.FromSeconds(5)); ----- - -The following is a list of available connection configuration options: - - -[source, csharp] ----- -var client = new ElasticLowLevelClient(); ----- -[source, csharp] ----- -var config = new ConnectionConfiguration() - - .DisableAutomaticProxyDetection() ----- -Disable automatic proxy detection. Defaults to true. - -[source, csharp] ----- -.EnableHttpCompression() ----- -Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured -to allow this. See the [http module settings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html) for more info). - -[source, csharp] ----- -.DisableDirectStreaming() ----- -By default responses are deserialized off stream to the object you tell it to. -For debugging purposes it can be very useful to keep a copy of the raw response on the result object. - -[source, csharp] ----- -var result = client.Search>(new { size = 12 }); -var raw = result.ResponseBodyInBytes; ----- -This will only have a value if the client configuration has ExposeRawResponse set - -[source, csharp] ----- -var stringResult = client.Search(new { }); ----- - -Please note that this only make sense if you need a mapped response and the raw response at the same time. -If you need a `string` or `byte[]` response simply call: - -[source, csharp] ----- -config = config - //endhide - .GlobalQueryStringParameters(new NameValueCollection()) ----- -Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. - -[source, csharp] ----- -.Proxy(new Uri("http://myproxy"), "username", "pass") ----- -Sets proxy information on the connection. - -[source, csharp] ----- -.RequestTimeout(TimeSpan.FromSeconds(4)) ----- -Sets the global maximum time a connection may take. -Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts -(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx). - -[source, csharp] ----- -.ThrowExceptions() ----- -As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw -exceptions. -There are three category of exceptions thay may be thrown: - -1) ElasticsearchClientException: These are known exceptions, either an exception that occurred in the request pipeline -(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could -not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property -on the response will contain the the actual error that was returned. The inner exception will always contain the -root causing exception. - -2) UnexpectedElasticsearchClientException: These are unknown exceptions, for instance a response from Elasticsearch not -properly deserialized. These are usually bugs and should be reported. This excpetion also inherits from ElasticsearchClientException -so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. -3) Development time exceptions: These are CLR exceptions like ArgumentException, NullArgumentException etc... that are thrown -when an API in the client is misused. These should not be handled as you want to know about them during development. - -[source, csharp] ----- -.PrettyJson() ----- -Forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well - -[source, csharp] ----- -.BasicAuthentication("username", "password") ----- -Sets the HTTP basic authentication credentials to specify with all requests. - -**Note:** This can alternatively be specified on the node URI directly: - -[source, csharp] ----- -var uri = new Uri("http://username:password@localhost:9200"); ----- -[source, csharp] ----- -var settings = new ConnectionConfiguration(uri); ----- - -...but may become tedious when using connection pooling with multiple nodes. - - - -You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. -If you have complex logging needs this is a good place to add that in. - - -[source, csharp] ----- -var counter = 0; -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) - .OnRequestCompleted(r => counter++); -var client = new ElasticClient(settings); -client.RootNodeInfo(); -counter.Should().Be(1); -client.RootNodeInfoAsync(); -counter.Should().Be(2); ----- - -An example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like -to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` -to `true` - - -[source, csharp] ----- -var list = new List(); -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) - .DisableDirectStreaming() - .OnRequestCompleted(response => - { - // log out the request - if (response.RequestBodyInBytes != null) - { - list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); - } - else - { - list.Add($"{response.HttpMethod} {response.Uri}"); - } - - // log out the response - if (response.ResponseBodyInBytes != null) - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); - } - else - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); - } - }); -list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); -list.Add($"{response.HttpMethod} {response.Uri}"); -list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); -list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); -var client = new ElasticClient(settings); -var syncResponse = client.Search(s => s - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) - ); -list.Count.Should().Be(2); -var asyncResponse = await client.SearchAsync(s => s - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) - ); -list.Count.Should().Be(4); -list.ShouldAllBeEquivalentTo(new [] - { - "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", - "Status: 200\n------------------------------\n", - "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", - "Status: 200\n------------------------------\n" - }); ----- -## Configuring SSL -SSL must be configured outside of the client using .NET's -[ServicePointManager](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx) -class and setting the [ServerCertificateValidationCallback](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx) -property. - -The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: - -[source, csharp] ----- -ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; ----- - -However, this will accept all requests from the AppDomain to untrusted SSL sites, -therefore we recommend doing some minimal introspection on the passed in certificate. - - - -You can then register a factory on ConnectionSettings to create an instance of your subclass instead. -This is called once per instance of ConnectionSettings. - - -[source, csharp] ----- -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); -var client = new ElasticClient(settings); -client.RootNodeInfo(); -client.RootNodeInfo(); -var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; -serializer.CallToModify.Should().BeGreaterThan(0); -serializer.SerializeToString(new Project { }); -serializer.CallToContractConverter.Should().BeGreaterThan(0); ----- +# Connecting +Connecting to *Elasticsearch* with `Elasticsearch.Net` is quite easy but has a few toggles and options worth knowing. + +# Choosing the right connection strategy +If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` + + +[source, csharp] +---- +var client = new ElasticLowLevelClient(); +var tokenizers = new TokenizersDescriptor(); +---- + +If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then +you will need to pass in some instance of `IConnectionConfigurationValues`. + +The easiest way to do this is: + + +[source, csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); +var config = new ConnectionConfiguration(node); +var client = new ElasticLowLevelClient(config); +---- + +This however is still a non-failover connection. Meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. + +To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. + + +[source, csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); +var connectionPool = new SniffingConnectionPool(new[] { node }); +var config = new ConnectionConfiguration(connectionPool); +var client = new ElasticLowLevelClient(config); +---- + +Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. +Be sure to read more about [Connection Pooling and Cluster Failover here](/elasticsearch-net/cluster-failover.html) + +## Options + +Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: + + +[source, csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); +var connectionPool = new SniffingConnectionPool(new[] { node }); +var config = new ConnectionConfiguration(connectionPool) + .DisableDirectStreaming() + .BasicAuthentication("user", "pass") + .RequestTimeout(TimeSpan.FromSeconds(5)); +---- + +The following is a list of available connection configuration options: + + +[source, csharp] +---- +var client = new ElasticLowLevelClient(); +---- +Disable automatic proxy detection. Defaults to true. + + +Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured +to allow this. See the [http module settings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html) for more info). + + + +By default responses are deserialized off stream to the object you tell it to. +For debugging purposes it can be very useful to keep a copy of the raw response on the result object. + + +[source, csharp] +---- +var config = new ConnectionConfiguration() + + .DisableAutomaticProxyDetection() +.EnableHttpCompression() +.DisableDirectStreaming() + +var result = client.Search>(new { size = 12 }); +var raw = result.ResponseBodyInBytes; +---- +This will only have a value if the client configuration has ExposeRawResponse set + + +Please note that this only make sense if you need a mapped response and the raw response at the same time. +If you need a `string` or `byte[]` response simply call: + + +[source, csharp] +---- +var stringResult = client.Search(new { }); +---- + +Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. + + +Sets proxy information on the connection. + + +Sets the global maximum time a connection may take. +Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts +(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx). + + + +As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw +exceptions. + +There are three category of exceptions thay may be thrown: + +1) ElasticsearchClientException: These are known exceptions, either an exception that occurred in the request pipeline +(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could +not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property +on the response will contain the the actual error that was returned. The inner exception will always contain the +root causing exception. + +2) UnexpectedElasticsearchClientException: These are unknown exceptions, for instance a response from Elasticsearch not +properly deserialized. These are usually bugs and should be reported. This excpetion also inherits from ElasticsearchClientException +so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. + +3) Development time exceptions: These are CLR exceptions like ArgumentException, NullArgumentException etc... that are thrown +when an API in the client is misused. These should not be handled as you want to know about them during development. + + + + +Forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well + + +Sets the HTTP basic authentication credentials to specify with all requests. + +[source, csharp] +---- +config = config + //endhide + .GlobalQueryStringParameters(new NameValueCollection()) +.Proxy(new Uri("http://myproxy"), "username", "pass") +.RequestTimeout(TimeSpan.FromSeconds(4)) +.ThrowExceptions() +.PrettyJson() +.BasicAuthentication("username", "password") +---- + +**Note:** This can alternatively be specified on the node URI directly: + + +[source, csharp] +---- +var uri = new Uri("http://username:password@localhost:9200"); + +var settings = new ConnectionConfiguration(uri); +---- + +...but may become tedious when using connection pooling with multiple nodes. + + + +You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. +If you have complex logging needs this is a good place to add that in. + + +[source, csharp] +---- +var counter = 0; +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + .OnRequestCompleted(r => counter++); +var client = new ElasticClient(settings); +client.RootNodeInfo(); +counter.Should().Be(1); +client.RootNodeInfoAsync(); +counter.Should().Be(2); +---- + +An example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like +to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` +to `true` + + +[source, csharp] +---- +var list = new List(); +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + .DisableDirectStreaming() + .OnRequestCompleted(response => + { + // log out the request + if (response.RequestBodyInBytes != null) + { + list.Add( + $"{response.HttpMethod} {response.Uri} \n" + + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); + } + else + { + list.Add($"{response.HttpMethod} {response.Uri}"); + } + + // log out the response + if (response.ResponseBodyInBytes != null) + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + + $"{new string('-', 30)}\n"); + } + else + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{new string('-', 30)}\n"); + } + }); +list.Add( + $"{response.HttpMethod} {response.Uri} \n" + + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); +list.Add($"{response.HttpMethod} {response.Uri}"); +list.Add($"Status: {response.HttpStatusCode}\n" + + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + + $"{new string('-', 30)}\n"); +list.Add($"Status: {response.HttpStatusCode}\n" + + $"{new string('-', 30)}\n"); +var client = new ElasticClient(settings); +var syncResponse = client.Search(s => s + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) + ); +list.Count.Should().Be(2); +var asyncResponse = await client.SearchAsync(s => s + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) + ); +list.Count.Should().Be(4); +list.ShouldAllBeEquivalentTo(new [] + { + "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", + "Status: 200\n------------------------------\n", + "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", + "Status: 200\n------------------------------\n" + }); +---- + +## Configuring SSL +SSL must be configured outside of the client using .NET's +[ServicePointManager](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx) +class and setting the [ServerCertificateValidationCallback](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx) +property. + +The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: + + +[source, csharp] +---- +ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; +---- + +However, this will accept all requests from the AppDomain to untrusted SSL sites, +therefore we recommend doing some minimal introspection on the passed in certificate. + + + +## Overriding default Json.NET behavior + +Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful + +Create a subclass of the `JsonNetSerializer` + + + + +Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` + + + +You can inject contract resolved converters by implementing the ContractConverters property +This can be much faster then registering them on JsonSerializerSettings.Converters + + +[source, csharp] +---- +public class MyJsonNetSerializer : JsonNetSerializer +{ + public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } +public int CallToModify { get; set; } = 0; + protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; +public int CallToContractConverter { get; set; } = 0; + protected override IList> ContractConverters => new List>() + { + { t => { + CallToContractConverter++; + return null; + } } + }; + +} +---- + +You can then register a factory on ConnectionSettings to create an instance of your subclass instead. +This is called once per instance of ConnectionSettings. + + +[source, csharp] +---- +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); +var client = new ElasticClient(settings); +client.RootNodeInfo(); +client.RootNodeInfo(); +var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; +serializer.CallToModify.Should().BeGreaterThan(0); +serializer.SerializeToString(new Project { }); +serializer.CallToContractConverter.Should().BeGreaterThan(0); +---- diff --git a/docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc b/docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc index 2ea18a0d78a..8e37cfba354 100644 --- a/docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc @@ -1,38 +1,80 @@ - -## Lifetimes - -If you are using an IOC container its always useful to know the best practices around the lifetime of your objects - -In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe -so sharing this instance over threads is ok. - -Zooming in however the actual moving part that benefits the most of being static for most of the duration of your -application is ConnectionSettings. Caches are per ConnectionSettings. - -In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different -connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. - - - -[source, csharp] ----- -var connection = new AConnection(); -var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); -var settings = new AConnectionSettings(connectionPool, connection); -settings.IsDisposed.Should().BeFalse(); -connectionPool.IsDisposed.Should().BeFalse(); -connection.IsDisposed.Should().BeFalse(); ----- - -Disposing the ConnectionSettings will dispose the IConnectionPool and IConnection it has a hold of - - -[source, csharp] ----- -var connection = new AConnection(); -var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); -var settings = new AConnectionSettings(connectionPool, connection); -settings.IsDisposed.Should().BeTrue(); -connectionPool.IsDisposed.Should().BeTrue(); -connection.IsDisposed.Should().BeTrue(); ----- + +## Lifetimes + +If you are using an IOC container its always useful to know the best practices around the lifetime of your objects + +In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe +so sharing this instance over threads is ok. + +Zooming in however the actual moving part that benefits the most from being static for most of the duration of your +application is ConnectionSettings. Caches are per ConnectionSettings. + +In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different +connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. + +Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types + + +[source, csharp] +---- +class AConnectionSettings : ConnectionSettings +{ + public AConnectionSettings(IConnectionPool pool, IConnection connection) + : base(pool, connection) + { } + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } +} + +class AConnectionPool : SingleNodeConnectionPool +{ + public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } + + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } +} + +class AConnection : InMemoryConnection +{ + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } +} +---- + +`ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` + + +[source, csharp] +---- +var connection = new AConnection(); +var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); +var settings = new AConnectionSettings(connectionPool, connection); +settings.IsDisposed.Should().BeFalse(); +connectionPool.IsDisposed.Should().BeFalse(); +connection.IsDisposed.Should().BeFalse(); +---- + +Disposing the ConnectionSettings will dispose the `IConnectionPool` and `IConnection` it has a hold of + + +[source, csharp] +---- +var connection = new AConnection(); +var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); +var settings = new AConnectionSettings(connectionPool, connection); +settings.IsDisposed.Should().BeTrue(); +connectionPool.IsDisposed.Should().BeTrue(); +connection.IsDisposed.Should().BeTrue(); +---- diff --git a/docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc b/docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc index b174112033f..ed7f47c0819 100644 --- a/docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc +++ b/docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc @@ -1,110 +1,104 @@ -# Post data -The low level allows you to post a string, byte[] array directly. On top of this if you pass a list of strings or objects -they will be serialized in Elasticsearch's special bulk/multi format. - - -Even though the argument for postData on the low level client takes a PostData -You can rely on C# implicit conversion to abstract the notion of PostData completely. -You can implicitly convert from the following types. - -[source, csharp] ----- -var fromString = ImplicitlyConvertsFrom(@string); ----- -[source, csharp] ----- -var fromByteArray = ImplicitlyConvertsFrom(bytes); -var fromListOfString = ImplicitlyConvertsFrom(listOfStrings); -var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); -var fromObject = ImplicitlyConvertsFrom(@object); ----- -postData Bytes will always be set if it originated from a byte - -[source, csharp] ----- -fromByteArray.WrittenBytes.Should().BeSameAs(bytes); ----- -[source, csharp] ----- -fromString.Type.Should().Be(PostType.LiteralString); -fromByteArray.Type.Should().Be(PostType.ByteArray); -fromListOfString.Type.Should().Be(PostType.EnumerableOfString); -fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); -fromObject.Type.Should().Be(PostType.Serializable); -fromString = ImplicitlyConvertsFrom(fromString); -fromByteArray = ImplicitlyConvertsFrom(fromByteArray); -fromListOfString = ImplicitlyConvertsFrom(fromListOfString); -fromListOfObject = ImplicitlyConvertsFrom(fromListOfObject); -fromObject = ImplicitlyConvertsFrom(fromObject); -fromString.Type.Should().Be(PostType.LiteralString); -fromByteArray.Type.Should().Be(PostType.ByteArray); -fromListOfString.Type.Should().Be(PostType.EnumerableOfString); -fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); -fromObject.Type.Should().Be(PostType.Serializable); -await this.AssertOn(new ConnectionSettings()); -await this.AssertOn(new ConnectionConfiguration()); ----- -Although each implicitly types behaves slightly differently - -[source, csharp] ----- -await Post(()=>@string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); ----- -[source, csharp] ----- -await Post(()=>bytes, writes: bytes, storesBytes: true, settings: settings); ----- -When passing a list of strings we assume its a list of valid serialized json that we -join with newlinefeeds making sure there is a trailing linefeed - -[source, csharp] ----- -await Post(()=>listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); ----- -When passing a list of object we assume its a list of objects we need to serialize -individually to json and join with newlinefeeds aking sure there is a trailing linefeed - -[source, csharp] ----- -await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); ----- -In all other cases postdata is serialized as is. - -[source, csharp] ----- -await Post(()=>@object, writes: objectJson, storesBytes: false, settings: settings); ----- -If you want to maintain a copy of the request that went out use the following settings - -[source, csharp] ----- -settings = new ConnectionSettings().DisableDirectStreaming(); ----- -by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream -so we can get a hold of the serialized bytes - -[source, csharp] ----- -await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); ----- -this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` - -[source, csharp] ----- -await Post(()=>@object, writes: objectJson, storesBytes: true, settings: settings); ----- -[source, csharp] ----- -PostAssert(postData(), writes, storesBytes, settings); -await PostAssertAsync(postData(), writes, storesBytes, settings); -postData.Write(ms, settings); -var sentBytes = ms.ToArray(); -sentBytes.Should().Equal(writes); -postData.WrittenBytes.Should().NotBeNull(); -postData.WrittenBytes.Should().BeNull(); -await postData.WriteAsync(ms, settings); -var sentBytes = ms.ToArray(); -sentBytes.Should().Equal(writes); -postData.WrittenBytes.Should().NotBeNull(); -postData.WrittenBytes.Should().BeNull(); ----- +# Post data +The low level allows you to post a string, byte[] array directly. On top of this if you pass a list of strings or objects +they will be serialized in Elasticsearch's special bulk/multi format. + + +Even though the argument for postData on the low level client takes a PostData +You can rely on C# implicit conversion to abstract the notion of PostData completely. +You can implicitly convert from the following types. + +[source, csharp] +---- +var fromString = ImplicitlyConvertsFrom(@string); + +var fromByteArray = ImplicitlyConvertsFrom(bytes); +var fromListOfString = ImplicitlyConvertsFrom(listOfStrings); +var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); +var fromObject = ImplicitlyConvertsFrom(@object); +---- +postData Bytes will always be set if it originated from a byte + +[source, csharp] +---- +fromByteArray.WrittenBytes.Should().BeSameAs(bytes); + +fromString.Type.Should().Be(PostType.LiteralString); +fromByteArray.Type.Should().Be(PostType.ByteArray); +fromListOfString.Type.Should().Be(PostType.EnumerableOfString); +fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); +fromObject.Type.Should().Be(PostType.Serializable); +fromString = ImplicitlyConvertsFrom(fromString); +fromByteArray = ImplicitlyConvertsFrom(fromByteArray); +fromListOfString = ImplicitlyConvertsFrom(fromListOfString); +fromListOfObject = ImplicitlyConvertsFrom(fromListOfObject); +fromObject = ImplicitlyConvertsFrom(fromObject); +fromString.Type.Should().Be(PostType.LiteralString); +fromByteArray.Type.Should().Be(PostType.ByteArray); +fromListOfString.Type.Should().Be(PostType.EnumerableOfString); +fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); +fromObject.Type.Should().Be(PostType.Serializable); +await this.AssertOn(new ConnectionSettings()); +await this.AssertOn(new ConnectionConfiguration()); +---- +Although each implicitly types behaves slightly differently + +[source, csharp] +---- +await Post(()=>@string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); + +await Post(()=>bytes, writes: bytes, storesBytes: true, settings: settings); +---- +When passing a list of strings we assume its a list of valid serialized json that we +join with newlinefeeds making sure there is a trailing linefeed + +[source, csharp] +---- +await Post(()=>listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); +---- + +When passing a list of object we assume its a list of objects we need to serialize +individually to json and join with newlinefeeds aking sure there is a trailing linefeed + + +[source, csharp] +---- +await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); +---- +In all other cases postdata is serialized as is. + +[source, csharp] +---- +await Post(()=>@object, writes: objectJson, storesBytes: false, settings: settings); +---- +If you want to maintain a copy of the request that went out use the following settings + +[source, csharp] +---- +settings = new ConnectionSettings().DisableDirectStreaming(); +---- +by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream +so we can get a hold of the serialized bytes + +[source, csharp] +---- +await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); +---- +this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` + +[source, csharp] +---- +await Post(()=>@object, writes: objectJson, storesBytes: true, settings: settings); + +PostAssert(postData(), writes, storesBytes, settings); +await PostAssertAsync(postData(), writes, storesBytes, settings); +postData.Write(ms, settings); +var sentBytes = ms.ToArray(); +sentBytes.Should().Equal(writes); +postData.WrittenBytes.Should().NotBeNull(); +postData.WrittenBytes.Should().BeNull(); +await postData.WriteAsync(ms, settings); +var sentBytes = ms.ToArray(); +sentBytes.Should().Equal(writes); +postData.WrittenBytes.Should().NotBeNull(); +postData.WrittenBytes.Should().BeNull(); +---- diff --git a/docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc b/docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc index 42149e5985e..426b4734e4f 100644 --- a/docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc +++ b/docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc @@ -1,52 +1,52 @@ - -Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface - - -[source, csharp] ----- -var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; -var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() - where t.IsClass() - && t.Name.Contains("Descriptor") - && !notDescriptors.Contains(t.Name) - && !t.GetInterfaces().Any(i => i == typeof(IDescriptor)) - select t.FullName; -descriptors.Should().BeEmpty(); ----- - -Methods taking a func should have that func return an interface - - -[source, csharp] ----- -var descriptors = - from t in typeof(DescriptorBase<,>).Assembly().Types() - where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) - select t; -var selectorMethods = - from d in descriptors - from m in d.GetMethods() - let parameters = m.GetParameters() - from p in parameters - let type = p.ParameterType - let isGeneric = type.IsGeneric() - where isGeneric - let isFunc = type.GetGenericTypeDefinition() == typeof(Func<,>) - where isFunc - let firstFuncArg = type.GetGenericArguments().First() - let secondFuncArg = type.GetGenericArguments().Last() - let isQueryFunc = firstFuncArg.IsGeneric() && - firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) && - typeof(QueryContainer).IsAssignableFrom(secondFuncArg) - where !isQueryFunc - let isFluentDictionaryFunc = - firstFuncArg.IsGeneric() && - firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) && - secondFuncArg.IsGeneric() && - secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) - where !isFluentDictionaryFunc - let lastArgIsNotInterface = !secondFuncArg.IsInterface() - where lastArgIsNotInterface - select $"{m.Name} on {m.DeclaringType.Name}"; -selectorMethods.Should().BeEmpty(); ----- + +Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface + + +[source, csharp] +---- +var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; +var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() + where t.IsClass() + && t.Name.Contains("Descriptor") + && !notDescriptors.Contains(t.Name) + && !t.GetInterfaces().Any(i => i == typeof(IDescriptor)) + select t.FullName; +descriptors.Should().BeEmpty(); +---- + +Methods taking a func should have that func return an interface + + +[source, csharp] +---- +var descriptors = + from t in typeof(DescriptorBase<,>).Assembly().Types() + where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) + select t; +var selectorMethods = + from d in descriptors + from m in d.GetMethods() + let parameters = m.GetParameters() + from p in parameters + let type = p.ParameterType + let isGeneric = type.IsGeneric() + where isGeneric + let isFunc = type.GetGenericTypeDefinition() == typeof(Func<,>) + where isFunc + let firstFuncArg = type.GetGenericArguments().First() + let secondFuncArg = type.GetGenericArguments().Last() + let isQueryFunc = firstFuncArg.IsGeneric() && + firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) && + typeof(QueryContainer).IsAssignableFrom(secondFuncArg) + where !isQueryFunc + let isFluentDictionaryFunc = + firstFuncArg.IsGeneric() && + firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) && + secondFuncArg.IsGeneric() && + secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) + where !isFluentDictionaryFunc + let lastArgIsNotInterface = !secondFuncArg.IsInterface() + where lastArgIsNotInterface + select $"{m.Name} on {m.DeclaringType.Name}"; +selectorMethods.Should().BeEmpty(); +---- diff --git a/docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc b/docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc index d8e7ee25432..5c8ca551f5c 100644 --- a/docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc +++ b/docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc @@ -51,4 +51,44 @@ var syncMethod = methodGroup.First(g => g.MethodInfo.GetGenericArguments().Length == asyncMethod.MethodInfo.GetGenericArguments().Length)); asyncMethod.Parameter.HasDefaultValue.Should().Be(syncMethod.Parameter.HasDefaultValue, $"sync and async versions of {asyncMethod.MethodType} '{nameof(ElasticClient)}{methodGroup.Key}' should match"); + +private class MethodWithRequestParameter + { + public string Name { get; } + + public MethodInfo MethodInfo { get; } + + public bool IsAsync { get; } + + public ClientMethodType MethodType { get; } + + public ParameterInfo Parameter { get; } + + public MethodWithRequestParameter(MethodInfo methodInfo) + { + Name = methodInfo.Name.EndsWith("Async") + ? methodInfo.Name.Substring(0, methodInfo.Name.Length - "Async".Length) + : methodInfo.Name; + + IsAsync = methodInfo.ReturnType.IsGeneric() && + methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); + + MethodInfo = methodInfo; + + var parameterInfo = methodInfo.GetParameters() + .FirstOrDefault(p => typeof(IRequest).IsAssignableFrom(p.ParameterType)); + + if (parameterInfo != null) + { + Parameter = parameterInfo; + MethodType = ClientMethodType.Initializer; + } + else + { + Parameter = methodInfo.GetParameters() + .First(p => p.ParameterType.BaseType() == typeof(MulticastDelegate)); + MethodType = ClientMethodType.Fluent; + } + } + } ---- diff --git a/docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc b/docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc index 79e6d70d120..fd550dbbe3f 100644 --- a/docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc +++ b/docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc @@ -1,128 +1,128 @@ -# Naming Conventions - -NEST uses the following naming conventions (with _some_ exceptions). - - -## Class Names - -Abstract class names should end with a `Base` suffix - - -[source, csharp] ----- -var exceptions = new[] - { - typeof(DateMath) - }; -var abstractClasses = typeof(IRequest).Assembly().GetTypes() - .Where(t => t.IsClass() && t.IsAbstract() && !t.IsSealed() && !exceptions.Contains(t)) - .Where(t => !t.Name.Split('`')[0].EndsWith("Base")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -abstractClasses.Should().BeEmpty(); ----- - -Class names that end with `Base` suffix are abstract - - -[source, csharp] ----- -var exceptions = new[] { typeof(DateMath) }; -var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() - .Where(t => t.IsClass() && !exceptions.Contains(t)) - .Where(t => t.Name.Split('`')[0].EndsWith("Base")) - .Where(t => !t.IsAbstractClass()) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -baseClassesNotAbstract.Should().BeEmpty(); ----- -## Requests and Responses - -Request class names should end with `Request` - - -[source, csharp] ----- -var types = typeof(IRequest).Assembly().GetTypes(); -var requests = types - .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) - .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) - .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -requests.Should().BeEmpty(); ----- - -Response class names should end with `Response` - - -[source, csharp] ----- -var types = typeof(IRequest).Assembly().GetTypes(); -var responses = types - .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) - .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -responses.Should().BeEmpty(); ----- - -Request and Response class names should be one to one in *most* cases. -e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => `ValidateResponse` -There are a few exceptions to this rule, most notably the `Cat` prefixed requests and -`Exists` requests. - - -[source, csharp] ----- -var exceptions = new[] - { - typeof(CatAliasesRequest), - typeof(CatAllocationRequest), - typeof(CatCountRequest), - typeof(CatFielddataRequest), - typeof(CatHealthRequest), - typeof(CatHelpRequest), - typeof(CatIndicesRequest), - typeof(CatMasterRequest), - typeof(CatNodesRequest), - typeof(CatPendingTasksRequest), - typeof(CatPluginsRequest), - typeof(CatRecoveryRequest), - typeof(CatSegmentsRequest), - typeof(CatShardsRequest), - typeof(CatThreadPoolRequest), - typeof(DocumentExistsRequest), - typeof(DocumentExistsRequest<>), - typeof(AliasExistsRequest), - typeof(IndexExistsRequest), - typeof(TypeExistsRequest), - typeof(IndexTemplateExistsRequest), - typeof(SearchExistsRequest), - typeof(SearchExistsRequest<>), - typeof(SearchTemplateRequest), - typeof(SearchTemplateRequest<>), - typeof(ScrollRequest), - typeof(SourceRequest), - typeof(SourceRequest<>), - typeof(ValidateQueryRequest<>), - typeof(GetAliasRequest), - typeof(CatNodeattrsRequest), - typeof(IndicesShardStoresRequest), - typeof(RenderSearchTemplateRequest) - }; -var types = typeof(IRequest).Assembly().GetTypes(); -var requests = new HashSet(types - .Where(t => - t.IsClass() && - !t.IsAbstract() && - typeof(IRequest).IsAssignableFrom(t) && - !typeof(IDescriptor).IsAssignableFrom(t) - && !exceptions.Contains(t)) - .Select(t => t.Name.Split('`')[0].Replace("Request", "")) - ); -var responses = types - .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) - .Select(t => t.Name.Split('`')[0].Replace("Response", "")); -requests.Except(responses).Should().BeEmpty(); ----- +# Naming Conventions + +NEST uses the following naming conventions (with _some_ exceptions). + + +## Class Names + +Abstract class names should end with a `Base` suffix + + +[source, csharp] +---- +var exceptions = new[] + { + typeof(DateMath) + }; +var abstractClasses = typeof(IRequest).Assembly().GetTypes() + .Where(t => t.IsClass() && t.IsAbstract() && !t.IsSealed() && !exceptions.Contains(t)) + .Where(t => !t.Name.Split('`')[0].EndsWith("Base")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +abstractClasses.Should().BeEmpty(); +---- + +Class names that end with `Base` suffix are abstract + + +[source, csharp] +---- +var exceptions = new[] { typeof(DateMath) }; +var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() + .Where(t => t.IsClass() && !exceptions.Contains(t)) + .Where(t => t.Name.Split('`')[0].EndsWith("Base")) + .Where(t => !t.IsAbstractClass()) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +baseClassesNotAbstract.Should().BeEmpty(); +---- +## Requests and Responses + +Request class names should end with `Request` + + +[source, csharp] +---- +var types = typeof(IRequest).Assembly().GetTypes(); +var requests = types + .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) + .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) + .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +requests.Should().BeEmpty(); +---- + +Response class names should end with `Response` + + +[source, csharp] +---- +var types = typeof(IRequest).Assembly().GetTypes(); +var responses = types + .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) + .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +responses.Should().BeEmpty(); +---- + +Request and Response class names should be one to one in *most* cases. +e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => `ValidateResponse` +There are a few exceptions to this rule, most notably the `Cat` prefixed requests and +`Exists` requests. + + +[source, csharp] +---- +var exceptions = new[] + { + typeof(CatAliasesRequest), + typeof(CatAllocationRequest), + typeof(CatCountRequest), + typeof(CatFielddataRequest), + typeof(CatHealthRequest), + typeof(CatHelpRequest), + typeof(CatIndicesRequest), + typeof(CatMasterRequest), + typeof(CatNodesRequest), + typeof(CatPendingTasksRequest), + typeof(CatPluginsRequest), + typeof(CatRecoveryRequest), + typeof(CatSegmentsRequest), + typeof(CatShardsRequest), + typeof(CatThreadPoolRequest), + typeof(DocumentExistsRequest), + typeof(DocumentExistsRequest<>), + typeof(AliasExistsRequest), + typeof(IndexExistsRequest), + typeof(TypeExistsRequest), + typeof(IndexTemplateExistsRequest), + typeof(SearchExistsRequest), + typeof(SearchExistsRequest<>), + typeof(SearchTemplateRequest), + typeof(SearchTemplateRequest<>), + typeof(ScrollRequest), + typeof(SourceRequest), + typeof(SourceRequest<>), + typeof(ValidateQueryRequest<>), + typeof(GetAliasRequest), + typeof(CatNodeattrsRequest), + typeof(IndicesShardStoresRequest), + typeof(RenderSearchTemplateRequest) + }; +var types = typeof(IRequest).Assembly().GetTypes(); +var requests = new HashSet(types + .Where(t => + t.IsClass() && + !t.IsAbstract() && + typeof(IRequest).IsAssignableFrom(t) && + !typeof(IDescriptor).IsAssignableFrom(t) + && !exceptions.Contains(t)) + .Select(t => t.Name.Split('`')[0].Replace("Request", "")) + ); +var responses = types + .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) + .Select(t => t.Name.Split('`')[0].Replace("Response", "")); +requests.Except(responses).Should().BeEmpty(); +---- diff --git a/docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc b/docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc index 7814362db9b..0a0242448e8 100644 --- a/docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc +++ b/docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc @@ -1,16 +1,16 @@ - -Our Json.NET contract resolver picks up attributes set on the interface - - -[source, csharp] ----- -var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(pool, new InMemoryConnection()); -var c = new ElasticClient(settings); -var serialized = c.Serializer.SerializeToString(new Nest.Analysis { CharFilters = new CharFilters() }); -serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); -serialized.Should().Contain("char_filter"); -serialized = c.Serializer.SerializeToString(new AnalysisDescriptor().CharFilters(cf=>cf)); -serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); -serialized.Should().Contain("char_filter"); ----- + +Our Json.NET contract resolver picks up attributes set on the interface + + +[source, csharp] +---- +var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(pool, new InMemoryConnection()); +var c = new ElasticClient(settings); +var serialized = c.Serializer.SerializeToString(new Nest.Analysis { CharFilters = new CharFilters() }); +serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); +serialized.Should().Contain("char_filter"); +serialized = c.Serializer.SerializeToString(new AnalysisDescriptor().CharFilters(cf=>cf)); +serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); +serialized.Should().Contain("char_filter"); +---- diff --git a/docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc b/docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc index dd78ae09ee8..37b078ccf03 100644 --- a/docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc +++ b/docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc @@ -1,97 +1,89 @@ -# Date Expressions -The date type supports using date math expression when using it in a query/filter -Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified - -The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with ||. -It can then follow by a math expression, supporting +, - and / (rounding). -The units supported are y (year), M (month), w (week), d (day), h (hour), m (minute), and s (second). -as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. - -Be sure to read the elasticsearch documentation {ref}/mapping-date-format.html#date-math[on this subject here] - - - -You can create simple expressions using any of the static methods on `DateMath` - -[source, csharp] ----- -Expect("now").WhenSerializing(Nest.DateMath.Now); ----- -[source, csharp] ----- -Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05, 05))); ----- -strings implicitly convert to date maths - -[source, csharp] ----- -Expect("now").WhenSerializing("now"); ----- -but are lenient to bad math expressions - -[source, csharp] ----- -var nonsense = "now||*asdaqwe"; ----- -[source, csharp] ----- -Expect(nonsense).WhenSerializing(nonsense) ----- -the resulting date math will assume the whole string is the anchor - -[source, csharp] ----- -.Result(dateMath => ((IDateMath)dateMath) - .Anchor.Match( - d => d.Should().NotBe(default(DateTime)), - s => s.Should().Be(nonsense) - ) - ); ----- -date's also implicitly convert to simple date math expressions - -[source, csharp] ----- -var date = new DateTime(2015, 05, 05); ----- -[source, csharp] ----- -Expect("2015-05-05T00:00:00").WhenSerializing(date) ----- -the anchor will be an actual DateTime, even after a serialization - deserialization round trip - -[source, csharp] ----- -.Result(dateMath => ((IDateMath)dateMath) - . Anchor.Match( - d => d.Should().Be(date), - s => s.Should().BeNull() - ) - ); ----- -Ranges can be chained on to simple expressions - -[source, csharp] ----- -Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); ----- -plural means that you can chain multiple - -[source, csharp] ----- -Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); ----- -a rounding value can also be chained at the end afterwhich no more ranges can be appended - -[source, csharp] ----- -Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); ----- -When anchoring date's we need to append `||` as clear separator between anchor and ranges - -[source, csharp] ----- -Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); ----- -plural means that you can chain multiple - +# Date Expressions +The date type supports using date math expression when using it in a query/filter +Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified + +The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with ||. +It can then follow by a math expression, supporting +, - and / (rounding). +The units supported are y (year), M (month), w (week), d (day), h (hour), m (minute), and s (second). +as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. + +Be sure to read the elasticsearch documentation {ref}/mapping-date-format.html#date-math[on this subject here] + + + +You can create simple expressions using any of the static methods on `DateMath` + +[source, csharp] +---- +Expect("now").WhenSerializing(Nest.DateMath.Now); + +Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05, 05))); +---- +strings implicitly convert to date maths + +[source, csharp] +---- +Expect("now").WhenSerializing("now"); +---- +but are lenient to bad math expressions + +[source, csharp] +---- +var nonsense = "now||*asdaqwe"; +---- +the resulting date math will assume the whole string is the anchor + +[source, csharp] +---- +Expect(nonsense).WhenSerializing(nonsense) +.Result(dateMath => ((IDateMath)dateMath) + .Anchor.Match( + d => d.Should().NotBe(default(DateTime)), + s => s.Should().Be(nonsense) + ) + ); +---- +date's also implicitly convert to simple date math expressions + +[source, csharp] +---- +var date = new DateTime(2015, 05, 05); +---- +the anchor will be an actual DateTime, even after a serialization - deserialization round trip + +[source, csharp] +---- +Expect("2015-05-05T00:00:00").WhenSerializing(date) +.Result(dateMath => ((IDateMath)dateMath) + . Anchor.Match( + d => d.Should().Be(date), + s => s.Should().BeNull() + ) + ); +---- +Ranges can be chained on to simple expressions + +[source, csharp] +---- +Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); +---- +plural means that you can chain multiple + +[source, csharp] +---- +Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); +---- +a rounding value can also be chained at the end afterwhich no more ranges can be appended + +[source, csharp] +---- +Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); +---- +When anchoring date's we need to append `||` as clear separator between anchor and ranges + +plural means that you can chain multiple + +[source, csharp] +---- +Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); +---- diff --git a/docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc b/docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc index a68dbb3deae..0cd133a1c36 100644 --- a/docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc +++ b/docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc @@ -1,115 +1,117 @@ -# Time units -Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified -as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. - -## Using Time units in NEST -NEST uses `Time` to strongly type this and there are several ways to construct one. - -### Constructor -The most straight forward way to construct a `Time` is through its constructor - - -[source, csharp] ----- -var unitString = new Time("2d"); -var unitComposed = new Time(2, Nest.TimeUnit.Day); -var unitTimeSpan = new Time(TimeSpan.FromDays(2)); -var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); ----- -When serializing Time constructed from a string, milliseconds, composition of factor and -interval, or a `TimeSpan` the expression will be serialized as time unit string - -[source, csharp] ----- -Expect("2d") - .WhenSerializing(unitString) - .WhenSerializing(unitComposed) - .WhenSerializing(unitTimeSpan) - .WhenSerializing(unitMilliseconds); ----- -Milliseconds are always calculated even when not using the constructor that takes a long - -[source, csharp] ----- -unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); ----- -[source, csharp] ----- -unitComposed.Milliseconds.Should().Be(1000*60*60*24*2); -unitTimeSpan.Milliseconds.Should().Be(1000*60*60*24*2); -unitString.Milliseconds.Should().Be(1000*60*60*24*2); ----- - -### Implicit conversion -Alternatively `string`, `TimeSpan` and `double` can be implicitly assigned to `Time` properties and variables - - -[source, csharp] ----- -Time oneAndHalfYear = "1.5y"; -Time twoWeeks = TimeSpan.FromDays(14); -Time twoDays = 1000*60*60*24*2; -Expect("1.5y").WhenSerializing(oneAndHalfYear); -Expect("2w").WhenSerializing(twoWeeks); -Expect("2d").WhenSerializing(twoDays); -Time oneAndHalfYear = "1.5y"; -Time twoWeeks = TimeSpan.FromDays(14); -Time twoDays = 1000*60*60*24*2; ----- -Milliseconds are calculated even when values are not passed as long - -[source, csharp] ----- -oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); ----- -[source, csharp] ----- -twoWeeks.Milliseconds.Should().BeGreaterThan(1); ----- -This allows you to do comparisons on the expressions - -[source, csharp] ----- -oneAndHalfYear.Should().BeGreaterThan(twoWeeks); ----- -[source, csharp] ----- -(oneAndHalfYear > twoWeeks).Should().BeTrue(); -(oneAndHalfYear >= twoWeeks).Should().BeTrue(); -(twoDays >= new Time("2d")).Should().BeTrue(); -twoDays.Should().BeLessThan(twoWeeks); -(twoDays < twoWeeks).Should().BeTrue(); -(twoDays <= twoWeeks).Should().BeTrue(); -(twoDays <= new Time("2d")).Should().BeTrue(); ----- -And assert equality - -[source, csharp] ----- -twoDays.Should().Be(new Time("2d")); ----- -[source, csharp] ----- -(twoDays == new Time("2d")).Should().BeTrue(); -(twoDays != new Time("2.1d")).Should().BeTrue(); -(new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue(); ----- -Time units are specified as a union of either a `DateInterval` or `Time` -both of which implicitly convert to the `Union` of these two. - -[source, csharp] ----- -Expect("month").WhenSerializing>(DateInterval.Month); ----- -[source, csharp] ----- -Expect("day").WhenSerializing>(DateInterval.Day); -Expect("hour").WhenSerializing>(DateInterval.Hour); -Expect("minute").WhenSerializing>(DateInterval.Minute); -Expect("quarter").WhenSerializing>(DateInterval.Quarter); -Expect("second").WhenSerializing>(DateInterval.Second); -Expect("week").WhenSerializing>(DateInterval.Week); -Expect("year").WhenSerializing>(DateInterval.Year); -Expect("2d").WhenSerializing>((Time)"2d"); -Expect("1.16w").WhenSerializing>((Time)TimeSpan.FromDays(8.1)); ----- +# Time units +Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified +as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. + +## Using Time units in NEST +NEST uses `Time` to strongly type this and there are several ways to construct one. + +### Constructor +The most straight forward way to construct a `Time` is through its constructor + + +[source, csharp] +---- +var unitString = new Time("2d"); +var unitComposed = new Time(2, Nest.TimeUnit.Day); +var unitTimeSpan = new Time(TimeSpan.FromDays(2)); +var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); +---- + +When serializing Time constructed from a string, milliseconds, composition of factor and +interval, or a `TimeSpan` the expression will be serialized as time unit string + + +[source, csharp] +---- +Expect("2d") + .WhenSerializing(unitString) + .WhenSerializing(unitComposed) + .WhenSerializing(unitTimeSpan) + .WhenSerializing(unitMilliseconds); +---- + +Milliseconds are always calculated even when not using the constructor that takes a long + + +[source, csharp] +---- +unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); + +unitComposed.Milliseconds.Should().Be(1000*60*60*24*2); +unitTimeSpan.Milliseconds.Should().Be(1000*60*60*24*2); +unitString.Milliseconds.Should().Be(1000*60*60*24*2); +---- + +### Implicit conversion +Alternatively `string`, `TimeSpan` and `double` can be implicitly assigned to `Time` properties and variables + + +[source, csharp] +---- +Time oneAndHalfYear = "1.5y"; +Time twoWeeks = TimeSpan.FromDays(14); +Time twoDays = 1000*60*60*24*2; +Expect("1.5y").WhenSerializing(oneAndHalfYear); +Expect("2w").WhenSerializing(twoWeeks); +Expect("2d").WhenSerializing(twoDays); +Time oneAndHalfYear = "1.5y"; +Time twoWeeks = TimeSpan.FromDays(14); +Time twoDays = 1000*60*60*24*2; +---- + +Milliseconds are calculated even when values are not passed as long + + +[source, csharp] +---- +oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); + +twoWeeks.Milliseconds.Should().BeGreaterThan(1); +---- + +This allows you to do comparisons on the expressions + + +[source, csharp] +---- +oneAndHalfYear.Should().BeGreaterThan(twoWeeks); + +(oneAndHalfYear > twoWeeks).Should().BeTrue(); +(oneAndHalfYear >= twoWeeks).Should().BeTrue(); +(twoDays >= new Time("2d")).Should().BeTrue(); +twoDays.Should().BeLessThan(twoWeeks); +(twoDays < twoWeeks).Should().BeTrue(); +(twoDays <= twoWeeks).Should().BeTrue(); +(twoDays <= new Time("2d")).Should().BeTrue(); +---- + +And assert equality + + +[source, csharp] +---- +twoDays.Should().Be(new Time("2d")); + +(twoDays == new Time("2d")).Should().BeTrue(); +(twoDays != new Time("2.1d")).Should().BeTrue(); +(new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue(); +---- + +Time units are specified as a union of either a `DateInterval` or `Time` +both of which implicitly convert to the `Union` of these two. + + +[source, csharp] +---- +Expect("month").WhenSerializing>(DateInterval.Month); + +Expect("day").WhenSerializing>(DateInterval.Day); +Expect("hour").WhenSerializing>(DateInterval.Hour); +Expect("minute").WhenSerializing>(DateInterval.Minute); +Expect("quarter").WhenSerializing>(DateInterval.Quarter); +Expect("second").WhenSerializing>(DateInterval.Second); +Expect("week").WhenSerializing>(DateInterval.Week); +Expect("year").WhenSerializing>(DateInterval.Year); +Expect("2d").WhenSerializing>((Time)"2d"); +Expect("1.16w").WhenSerializing>((Time)TimeSpan.FromDays(8.1)); +---- diff --git a/docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc b/docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc index 9dde4bb05c8..8cb24e88afc 100644 --- a/docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc +++ b/docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc @@ -1,126 +1,126 @@ -Writing boolean queries can grow rather verbose rather quickly using the query DSL e.g - -[source, csharp] ----- -var searchResults = this.Client.Search(s => s - .Query(q => q - .Bool(b => b - .Should( - bs => bs.Term(p => p.Name, "x"), - bs => bs.Term(p => p.Name, "y") - ) - ) - ) - ); ----- -now this is just a single bool with only two clauses, imagine multiple nested bools this quickly becomes an exercise in -hadouken indenting - -[[indent]] -.hadouken indenting example -image::http://i.imgur.com/BtjZedW.jpg[dead indent] - - -For this reason, NEST introduces operator overloading so complex bool queries become easier to write, the previous example will become. - -[source, csharp] ----- -var searchResults = this.Client.Search(s => s - .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) - ); ----- -Or using the object initializer syntax - -[source, csharp] ----- -searchResults = this.Client.Search(new SearchRequest -{ - Query = new TermQuery { Field = "name", Value= "x" } - || new TermQuery { Field = Field(p=>p.Name), Value = "y" } -}); ----- -A naive implementation of operator overloading would rewrite - -`term && term && term` to - -> bool -> |___must -> |___term -> |___bool -> |___must -> |___term -> |___term - -As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and -join them together to become a single bool query - -> bool -> |___must -> |___term -> |___term -> |___term - - - -The bool DSL offers also a short hand notation to mark a query as a must_not using ! - -And to mark a query as a filter using + - -Both of these can be combined with ands to a single bool query - -When combining multiple queries some or all possibly marked as must_not or filter NEST still combines to a single bool query - -> bool -> |___must -> | |___term -> | |___term -> | |___term -> | -> |___must_not -> |___term - - -[source, csharp] ----- -Assert( - q => q.Query() && q.Query() && q.Query() && !q.Query(), - Query && Query && Query && !Query, - c=> - { - c.Bool.Must.Should().HaveCount(3); - c.Bool.MustNot.Should().HaveCount(1); - }); -c.Bool.Must.Should().HaveCount(3); -c.Bool.MustNot.Should().HaveCount(1); ----- -Even more involved `term && term && term && !term && +term && +term` still only results in a single bool query: - -> bool -> |___must -> | |___term -> | |___term -> | |___term -> | -> |___must_not -> | |___term -> | -> |___filter -> |___term -> |___term - - -You can still mix and match actual bool queries with the bool dsl e.g - -`bool(must=term, term, term) && !term` - -it would still merge into a single bool query. - -[source, csharp] ----- -c.Bool.Should.Should().HaveCount(2); -var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); -nestedBool.Bool.Should.Should().HaveCount(1); -nestedBool.Bool.Name.Should().Be(firstName); -assert(fluent.InvokeQuery(new QueryContainerDescriptor())); -assert((QueryContainer)ois); ----- +Writing boolean queries can grow rather verbose rather quickly using the query DSL e.g + +[source, csharp] +---- +var searchResults = this.Client.Search(s => s + .Query(q => q + .Bool(b => b + .Should( + bs => bs.Term(p => p.Name, "x"), + bs => bs.Term(p => p.Name, "y") + ) + ) + ) + ); +---- +now this is just a single bool with only two clauses, imagine multiple nested bools this quickly becomes an exercise in +hadouken indenting + +[[indent]] +.hadouken indenting example +image::http://i.imgur.com/BtjZedW.jpg[dead indent] + + +For this reason, NEST introduces operator overloading so complex bool queries become easier to write, the previous example will become. + +[source, csharp] +---- +var searchResults = this.Client.Search(s => s + .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) + ); +---- +Or using the object initializer syntax + +[source, csharp] +---- +searchResults = this.Client.Search(new SearchRequest +{ + Query = new TermQuery { Field = "name", Value= "x" } + || new TermQuery { Field = Field(p=>p.Name), Value = "y" } +}); +---- +A naive implementation of operator overloading would rewrite + +`term && term && term` to + +> bool +> |___must +> |___term +> |___bool +> |___must +> |___term +> |___term + +As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and +join them together to become a single bool query + +> bool +> |___must +> |___term +> |___term +> |___term + + + +The bool DSL offers also a short hand notation to mark a query as a must_not using ! + +And to mark a query as a filter using + + +Both of these can be combined with ands to a single bool query + +When combining multiple queries some or all possibly marked as must_not or filter NEST still combines to a single bool query + +> bool +> |___must +> | |___term +> | |___term +> | |___term +> | +> |___must_not +> |___term + + +[source, csharp] +---- +Assert( + q => q.Query() && q.Query() && q.Query() && !q.Query(), + Query && Query && Query && !Query, + c=> + { + c.Bool.Must.Should().HaveCount(3); + c.Bool.MustNot.Should().HaveCount(1); + }); +c.Bool.Must.Should().HaveCount(3); +c.Bool.MustNot.Should().HaveCount(1); +---- +Even more involved `term && term && term && !term && +term && +term` still only results in a single bool query: + +> bool +> |___must +> | |___term +> | |___term +> | |___term +> | +> |___must_not +> | |___term +> | +> |___filter +> |___term +> |___term + + +You can still mix and match actual bool queries with the bool dsl e.g + +`bool(must=term, term, term) && !term` + +it would still merge into a single bool query. + +[source, csharp] +---- +c.Bool.Should.Should().HaveCount(2); +var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); +nestedBool.Bool.Should.Should().HaveCount(1); +nestedBool.Bool.Name.Should().Be(firstName); +assert(fluent.InvokeQuery(new QueryContainerDescriptor())); +assert((QueryContainer)ois); +---- diff --git a/docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc b/docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc index c049e778115..cc4333ee7b1 100644 --- a/docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc +++ b/docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc @@ -1,98 +1,118 @@ -# Distance Units -Whenever distances need to be specified, e.g. for a geo distance query, the distance unit can be specified -as a double number representing distance in meters, as a new instance of a `Distance`, or as a string -of the form number and distance unit e.g. `"2.72km"` - -## Using Distance units in NEST -NEST uses `Distance` to strongly type distance units and there are several ways to construct one. - -### Constructor -The most straight forward way to construct a `Distance` is through its constructor - - -[source, csharp] ----- -var unitComposed = new Nest.Distance(25); -var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); ----- -When serializing Distance constructed from a string, composition of distance value and unit - -[source, csharp] ----- -Expect("25.0m") - .WhenSerializing(unitComposed) - .WhenSerializing(unitComposedWithUnits); ----- - -### Implicit conversion -Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. -If no `DistanceUnit` is specified, the default distance unit is meters - - -[source, csharp] ----- -Nest.Distance distanceString = "25"; -Nest.Distance distanceStringWithUnits = "25m"; -Expect(new Nest.Distance(25)) - .WhenSerializing(distanceString) - .WhenSerializing(distanceStringWithUnits); ----- - -### Supported units -A number of distance units are supported, from millimeters to nautical miles - - -Miles - -[source, csharp] ----- -Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); ----- -Yards - -[source, csharp] ----- -Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); ----- -Feet - -[source, csharp] ----- -Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); ----- -Inches - -[source, csharp] ----- -Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); ----- -Kilometers - -[source, csharp] ----- -Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); ----- -Meters - -[source, csharp] ----- -Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); ----- -Centimeters - -[source, csharp] ----- -Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); ----- -Millimeters - -[source, csharp] ----- -Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); ----- -Nautical Miles - -[source, csharp] ----- -Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); ----- +# Distance Units +Whenever distances need to be specified, e.g. for a geo distance query, the distance unit can be specified +as a double number representing distance in meters, as a new instance of a `Distance`, or as a string +of the form number and distance unit e.g. `"2.72km"` + +## Using Distance units in NEST +NEST uses `Distance` to strongly type distance units and there are several ways to construct one. + +### Constructor +The most straight forward way to construct a `Distance` is through its constructor + + +[source, csharp] +---- +var unitComposed = new Nest.Distance(25); +var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); +---- + +When serializing Distance constructed from a string, composition of distance value and unit + + +[source, csharp] +---- +Expect("25.0m") + .WhenSerializing(unitComposed) + .WhenSerializing(unitComposedWithUnits); +---- + +### Implicit conversion +Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. +If no `DistanceUnit` is specified, the default distance unit is meters + + +[source, csharp] +---- +Nest.Distance distanceString = "25"; +Nest.Distance distanceStringWithUnits = "25m"; +Expect(new Nest.Distance(25)) + .WhenSerializing(distanceString) + .WhenSerializing(distanceStringWithUnits); +---- + +### Supported units +A number of distance units are supported, from millimeters to nautical miles + + + +Miles + + +[source, csharp] +---- +Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); +---- + +Yards + + +[source, csharp] +---- +Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); +---- + +Feet + + +[source, csharp] +---- +Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); +---- + +Inches + + +[source, csharp] +---- +Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); +---- + +Kilometers + + +[source, csharp] +---- +Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); +---- + +Meters + + +[source, csharp] +---- +Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); +---- + +Centimeters + + +[source, csharp] +---- +Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); +---- + +Millimeters + + +[source, csharp] +---- +Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); +---- + +Nautical Miles + + +[source, csharp] +---- +Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); +---- From c6124a5364bd84400324807049c1ad6bc2e60340 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Fri, 12 Feb 2016 17:14:23 +1100 Subject: [PATCH 05/18] WIP write all asciidocs to single output directory --- .../DocumentPaths/DocumentPaths.doc.asciidoc | 104 ------ .../FieldNames/FieldInference.doc.asciidoc | 313 ------------------ .../Inferrence/Id/IdsInference.doc.asciidoc | 79 ----- .../Indices/IndicesPaths.doc.asciidoc | 34 -- ...AutoMap.doc.asciidoc => auto_map.asciidoc} | 22 +- ...BoolDsl.doc.asciidoc => bool_dsl.asciidoc} | 45 ++- ... => children_aggregation_mapping.asciidoc} | 2 + ...cting.doc.asciidoc => connecting.asciidoc} | 2 + ...c.asciidoc => connection_pooling.asciidoc} | 10 +- ...idoc => covariant_search_results.asciidoc} | 2 + ...sciidoc => date_math_expressions.asciidoc} | 2 + ....asciidoc => date_time_providers.asciidoc} | 6 +- ...tors.doc.asciidoc => descriptors.asciidoc} | 2 + .../disable_sniff_ping_per_request.asciidoc | 79 +++++ ...s.doc.asciidoc => distance_units.asciidoc} | 2 + ...s.doc.asciidoc => document_paths.asciidoc} | 2 + ...t.doc.asciidoc => elastic_client.asciidoc} | 2 + ...ver.doc.asciidoc => falling_over.asciidoc} | 10 +- ....doc.asciidoc => field_inference.asciidoc} | 2 + ...sage.doc.asciidoc => first_usage.asciidoc} | 4 +- ...ce.doc.asciidoc => ids_inference.asciidoc} | 2 + .../LowLevel => images}/class.png | Bin docs/asciidoc/images/hadouken_indentation.jpg | Bin 0 -> 43939 bytes .../LowLevel => images}/pipeline.png | Bin .../BuildingBlocks => images}/timeoutplot.png | Bin docs/asciidoc/index.asciidoc | 36 +- ...hs.doc.asciidoc => indices_paths.asciidoc} | 2 + ...ciidoc => keeping_track_of_nodes.asciidoc} | 4 +- ...etimes.doc.asciidoc => lifetimes.asciidoc} | 2 + ...c.asciidoc => naming_conventions.asciidoc} | 2 + ...sciidoc => on_connection_failure.asciidoc} | 3 + ...ciidoc => on_stale_cluster_state.asciidoc} | 2 + ...artup.doc.asciidoc => on_startup.asciidoc} | 2 + ...stData.doc.asciidoc => post_data.asciidoc} | 2 + ...rties.doc.asciidoc => properties.asciidoc} | 2 + ...c.asciidoc => property_inference.asciidoc} | 2 + .../Queries.doc.asciidoc => queries.asciidoc} | 2 + ...oc.asciidoc => request_pipelines.asciidoc} | 9 +- .../request_timeouts_overrides.asciidoc | 95 ++++++ .../respects_allowed_status_code.asciidoc | 22 ++ docs/asciidoc/respects_force_node.asciidoc | 22 ++ ...c.asciidoc => respects_max_retry.asciidoc} | 2 + ... => respects_max_retry_overrides.asciidoc} | 5 +- .../Revival.doc.asciidoc => revival.asciidoc} | 4 +- ...n.doc.asciidoc => role_detection.asciidoc} | 2 + ...obin.doc.asciidoc => round_robin.asciidoc} | 2 + ....doc.asciidoc => skip_dead_nodes.asciidoc} | 11 +- ...Units.doc.asciidoc => time_units.asciidoc} | 2 + ...ports.Doc.asciidoc => transports.asciidoc} | 6 +- ...sciidoc => unexpected_exceptions.asciidoc} | 2 + ...idoc => unrecoverable_exceptions.asciidoc} | 2 + ...doc.asciidoc => volatile_updates.asciidoc} | 2 + ...asciidoc => writing_aggregations.asciidoc} | 2 + .../Files/CSharpDocumentationFile.cs | 10 +- .../Documentation/Files/DocumentationFile.cs | 12 +- .../Files/ImageDocumentationFile.cs | 21 ++ .../Files/RawDocumentationFile.cs | 2 +- .../Nest.Litterateur/EnumerableExtensions.cs | 23 ++ .../Nest.Litterateur/Linker/Linker.cs | 18 + src/CodeGeneration/Nest.Litterateur/LitUp.cs | 3 +- .../BuildingBlocks/ConnectionPooling.Doc.cs | 8 +- .../BuildingBlocks/DateTimeProviders.Doc.cs | 4 +- .../BuildingBlocks/KeepingTrackOfNodes.Doc.cs | 2 +- .../BuildingBlocks/RequestPipelines.doc.cs | 9 +- .../BuildingBlocks/Transports.Doc.cs | 4 +- .../Failover/FallingOver.doc.cs | 8 +- .../Pinging/FirstUsage.doc.cs | 2 +- .../ConnectionPooling/Pinging/Revival.doc.cs | 2 +- ...t.cs => DisableSniffPingPerRequest.doc.cs} | 185 ++++++----- ...des.cs => RequestTimeoutsOverrides.doc.cs} | 131 ++++---- ...de.cs => RespectsAllowedStatusCode.doc.cs} | 68 ++-- ...sForceNode.cs => RespectsForceNode.doc.cs} | 68 ++-- .../RespectsMaxRetryOverrides.doc.cs | 3 +- .../RoundRobin/SkipDeadNodes.doc.cs | 9 +- .../Sniffing/OnConnectionFailure.doc.cs | 1 + .../HighLevel/Mapping/AutoMap.doc.cs | 20 +- src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs | 91 ++--- .../QueryDsl/BoolDsl/hadouken_indentation.jpg | Bin 0 -> 43939 bytes src/Tests/index.asciidoc | 36 +- 79 files changed, 806 insertions(+), 911 deletions(-) delete mode 100644 docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths/DocumentPaths.doc.asciidoc delete mode 100644 docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldNames/FieldInference.doc.asciidoc delete mode 100644 docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Id/IdsInference.doc.asciidoc delete mode 100644 docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Indices/IndicesPaths.doc.asciidoc rename docs/asciidoc/{ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc => auto_map.asciidoc} (96%) rename docs/asciidoc/{QueryDsl/BoolDsl/BoolDsl.doc.asciidoc => bool_dsl.asciidoc} (59%) rename docs/asciidoc/{Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc => children_aggregation_mapping.asciidoc} (83%) rename docs/asciidoc/{ClientConcepts/LowLevel/Connecting.doc.asciidoc => connecting.asciidoc} (96%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc => connection_pooling.asciidoc} (92%) rename docs/asciidoc/{ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc => covariant_search_results.asciidoc} (95%) rename docs/asciidoc/{CommonOptions/DateMath/DateMathExpressions.doc.asciidoc => date_math_expressions.asciidoc} (94%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc => date_time_providers.asciidoc} (88%) rename docs/asciidoc/{CodeStandards/Descriptors.doc.asciidoc => descriptors.asciidoc} (94%) create mode 100644 docs/asciidoc/disable_sniff_ping_per_request.asciidoc rename docs/asciidoc/{QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc => distance_units.asciidoc} (92%) rename docs/asciidoc/{ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc => document_paths.asciidoc} (94%) rename docs/asciidoc/{CodeStandards/ElasticClient.doc.asciidoc => elastic_client.asciidoc} (98%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc => falling_over.asciidoc} (84%) rename docs/asciidoc/{ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc => field_inference.asciidoc} (96%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc => first_usage.asciidoc} (93%) rename docs/asciidoc/{ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc => ids_inference.asciidoc} (94%) rename docs/asciidoc/{ClientConcepts/LowLevel => images}/class.png (100%) create mode 100644 docs/asciidoc/images/hadouken_indentation.jpg rename docs/asciidoc/{ClientConcepts/LowLevel => images}/pipeline.png (100%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/BuildingBlocks => images}/timeoutplot.png (100%) rename docs/asciidoc/{ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc => indices_paths.asciidoc} (91%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc => keeping_track_of_nodes.asciidoc} (93%) rename docs/asciidoc/{ClientConcepts/LowLevel/Lifetimes.doc.asciidoc => lifetimes.asciidoc} (94%) rename docs/asciidoc/{CodeStandards/NamingConventions.doc.asciidoc => naming_conventions.asciidoc} (94%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc => on_connection_failure.asciidoc} (95%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc => on_stale_cluster_state.asciidoc} (94%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc => on_startup.asciidoc} (94%) rename docs/asciidoc/{ClientConcepts/LowLevel/PostData.doc.asciidoc => post_data.asciidoc} (95%) rename docs/asciidoc/{CodeStandards/Serialization/Properties.doc.asciidoc => properties.asciidoc} (88%) rename docs/asciidoc/{ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc => property_inference.asciidoc} (89%) rename docs/asciidoc/{CodeStandards/Queries.doc.asciidoc => queries.asciidoc} (95%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc => request_pipelines.asciidoc} (94%) create mode 100644 docs/asciidoc/request_timeouts_overrides.asciidoc create mode 100644 docs/asciidoc/respects_allowed_status_code.asciidoc create mode 100644 docs/asciidoc/respects_force_node.asciidoc rename docs/asciidoc/{ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc => respects_max_retry.asciidoc} (95%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc => respects_max_retry_overrides.asciidoc} (92%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc => revival.asciidoc} (92%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.asciidoc => role_detection.asciidoc} (98%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc => round_robin.asciidoc} (94%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc => skip_dead_nodes.asciidoc} (91%) rename docs/asciidoc/{CommonOptions/TimeUnit/TimeUnits.doc.asciidoc => time_units.asciidoc} (95%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc => transports.asciidoc} (91%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc => unexpected_exceptions.asciidoc} (95%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc => unrecoverable_exceptions.asciidoc} (93%) rename docs/asciidoc/{ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc => volatile_updates.asciidoc} (90%) rename docs/asciidoc/{Aggregations/WritingAggregations.doc.asciidoc => writing_aggregations.asciidoc} (95%) create mode 100644 src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs rename src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/{DisableSniffPingPerRequest.cs => DisableSniffPingPerRequest.doc.cs} (96%) rename src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/{RequestTimeoutsOverrides.cs => RequestTimeoutsOverrides.doc.cs} (97%) rename src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/{RespectsAllowedStatusCode.cs => RespectsAllowedStatusCode.doc.cs} (95%) rename src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/{RespectsForceNode.cs => RespectsForceNode.doc.cs} (96%) create mode 100644 src/Tests/QueryDsl/BoolDsl/hadouken_indentation.jpg diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths/DocumentPaths.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths/DocumentPaths.doc.asciidoc deleted file mode 100644 index 22a2862b8ef..00000000000 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths/DocumentPaths.doc.asciidoc +++ /dev/null @@ -1,104 +0,0 @@ -# DocumentPaths -Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes -and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path -to your document more succintly - -Manually newing - -here we create a new document path based on Project with the id 1 - -[source, csharp] ----- -IDocumentPath path = new DocumentPath(1); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); ----- -You can still override the inferred index and type name - -[source, csharp] ----- -path = new DocumentPath(1).Type("project1"); ----- -[source, csharp] ----- -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(1).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- -there is also a static way to describe such paths - -[source, csharp] ----- -path = DocumentPath.Id(1); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); -var project = new Project { Name = "hello-world" }; ----- -here we create a new document path based on a Project - -[source, csharp] ----- -IDocumentPath path = new DocumentPath(project); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect("hello-world").WhenSerializing(path.Id); ----- -You can still override the inferred index and type name - -[source, csharp] ----- -path = new DocumentPath(project).Type("project1"); ----- -[source, csharp] ----- -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(project).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- -there is also a static way to describe such paths - -[source, csharp] ----- -path = DocumentPath.Id(project); ----- -[source, csharp] ----- -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect("hello-world").WhenSerializing(path.Id); -DocumentPath p = project; -var project = new Project { Name = "hello-world" }; ----- -Here we can see and example how DocumentPath helps your describe your requests more tersely - -[source, csharp] ----- -var request = new IndexRequest(2) { Document = project }; ----- -[source, csharp] ----- -request = new IndexRequest(project) { }; ----- -when comparing with the full blown constructor and passing document manually -DocumentPath -T -'s benefits become apparent. - -[source, csharp] ----- -request = new IndexRequest(IndexName.From(), TypeName.From(), 2) -{ - Document = project -}; ----- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldNames/FieldInference.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldNames/FieldInference.doc.asciidoc deleted file mode 100644 index 82b58a192ec..00000000000 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldNames/FieldInference.doc.asciidoc +++ /dev/null @@ -1,313 +0,0 @@ -# Strongly typed field access - -Several places in the elasticsearch API expect the path to a field from your original source document as a string. -NEST allows you to use C# expressions to strongly type these field path strings. -These expressions are assigned to a type called `Field` and there are several ways to create a instance of that type - -Using the constructor directly is possible but rather involved - -[source, csharp] ----- -var fieldString = new Field { Name = "name" }; ----- -especially when using C# expressions since these can not be simply new'ed - -[source, csharp] ----- -Expression> expression = p => p.Name; ----- -[source, csharp] ----- -var fieldExpression = Field.Create(expression); -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- -Therefor you can also implicitly convert strings and expressions to Field's - -[source, csharp] ----- -Field fieldString = "name"; ----- -but for expressions this is still rather involved - -[source, csharp] ----- -Expression> expression = p => p.Name; ----- -[source, csharp] ----- -Field fieldExpression = expression; -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- -to ease creating Field's from expressions there is a static Property class you can use - -[source, csharp] ----- -Field fieldString = "name"; ----- -but for expressions this is still rather involved - -[source, csharp] ----- -var fieldExpression = Field(p => p.Name); ----- -Using static imports in c# 6 this can be even shortened: -using static Nest.Static; - -[source, csharp] ----- -fieldExpression = Field(p => p.Name); ----- -Now this is much much terser then our first example using the constructor! - -[source, csharp] ----- -Expect("name") - .WhenSerializing(fieldString) - .WhenSerializing(fieldExpression); ----- -By default NEST will camelCase all the field names to be more javascripty - -using DefaultFieldNameInferrer() on ConnectionSettings you can change this behavior - -[source, csharp] ----- -var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); ----- -[source, csharp] ----- -setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); ----- -However string are *always* passed along verbatim - -[source, csharp] ----- -setup.Expect("NaMe").WhenSerializing("NaMe"); ----- -if you want the same behavior for expressions simply do nothing in the default inferrer - -[source, csharp] ----- -setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); ----- -[source, csharp] ----- -setup.Expect("Name").WhenSerializing(Field(p => p.Name)); ----- -Complex field name expressions - -You can follow your property expression to any depth, here we are traversing to the LeadDeveloper's (Person) FirstName - -[source, csharp] ----- -Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ----- -When dealing with collection index access is ingnored allowing you to traverse into properties of collections - -[source, csharp] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ----- -Similarly .First() also works, remember these are expressions and not actual code that will be executed - -[source, csharp] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); ----- -[source, csharp] ----- -Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); -Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); ----- -When we see an indexer on a dictionary we assume they describe property names - -[source, csharp] ----- -Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); ----- -[source, csharp] ----- -Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); ----- -A cool feature here is that we'll evaluate variables passed to these indexers - -[source, csharp] ----- -var variable = "var"; ----- -[source, csharp] ----- -Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); -Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ----- -If you are using elasticearch's multifield mapping (you really should!) these "virtual" sub fields -do not always map back on to your POCO, by calling .Suffix() you describe the sub fields that do not live in your c# objects - -[source, csharp] ----- -Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); ----- -[source, csharp] ----- -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); -Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); -Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); -Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); ----- -You can even chain them to any depth! - -[source, csharp] ----- -Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ----- -Variables passed to suffix will be evaluated as well - -[source, csharp] ----- -var suffix = "unanalyzed"; ----- -[source, csharp] ----- -Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); -Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); ----- -Annotations - -When using NEST's property attributes you can specify a new name for the properties - -[source, csharp] ----- -Expect("naam").WhenSerializing(Field(p => p.Name)); ----- - -Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. -Here we ask the default JsonNetSerializer and it takes JsonProperty into account - -[source, csharp] ----- -Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ----- - -If both are specified NEST takes precedence though - -[source, csharp] ----- -Expect("naam").WhenSerializing(Field(p => p.Name)); -Expect(new - { - naam = "Martijn Laarman" - }).WhenSerializing(new Both { Name = "Martijn Laarman" }); ----- -Resolving field names is cached but this is per connection settings - -[source, csharp] ----- -var connectionSettings = TestClient.CreateSettings(forceInMemory: true); -var client = new ElasticClient(connectionSettings); -var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); -var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); ----- -Here we have to similary shaped expressions on coming from A and on from B -that will resolve to the same field name, as expected - -[source, csharp] ----- -fieldNameOnA.Should().Be("c.name"); ----- -[source, csharp] ----- -fieldNameOnB.Should().Be("c.name"); ----- -now we create a new connectionsettings with a remap for C on class A to `d` -now when we resolve the field path for A will be different - -[source, csharp] ----- -var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s - .InferMappingFor(m => m - .Rename(p => p.C, "d") - ) -); ----- -[source, csharp] ----- -var newClient = new ElasticClient(newConnectionSettings); -fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); -fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); -fieldNameOnA.Should().Be("d.name"); -fieldNameOnB.Should().Be("c.name"); ----- -however we didn't break inferrence on the first client instance using its separate connectionsettings - -[source, csharp] ----- -fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); ----- -[source, csharp] ----- -fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); -fieldNameOnA.Should().Be("c.name"); -fieldNameOnB.Should().Be("c.name"); ----- -To wrap up lets showcase the precedence that field names are inferred -1. A hard rename of the property on connection settings using Rename() -2. A NEST property mapping -3. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. -4. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases -In the following example we have a class where each case wins - - -Here we create a custom converter that renames any property named `AskSerializer` to `ask` - -[source, csharp] ----- -var usingSettings = WithConnectionSettings(s => s ----- -here we provide an explicit rename of a property on connectionsettings - -[source, csharp] ----- -.InferMappingFor(m => m - .Rename(p => p.RenamedOnConnectionSettings, "renamed") - ) ----- -All properties that are not mapped verbatim should be uppercased - -[source, csharp] ----- -.DefaultFieldNameInferrer(p => p.ToUpperInvariant()) -).WithSerializer(s => new CustomSerializer(s)); ----- -[source, csharp] ----- -usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); -usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); -usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); -usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); -usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); ----- -The same rules apply when indexing an object - -[source, csharp] ----- -usingSettings.Expect(new [] -{ - "ask", - "DEFAULTFIELDNAMEINFERRER", - "jsonProp", - "nestAtt", - "renamed" -}).AsPropertiesOf(new Precedence -{ - RenamedOnConnectionSettings = "renamed on connection settings", - NestAttribute = "using a nest attribute", - JsonProperty = "the default serializer resolves json property attributes", - AskSerializer = "serializer fiddled with this one", - DefaultFieldNameInferrer = "shouting much?" -}); ----- - diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Id/IdsInference.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Id/IdsInference.doc.asciidoc deleted file mode 100644 index 6a659778cb3..00000000000 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Id/IdsInference.doc.asciidoc +++ /dev/null @@ -1,79 +0,0 @@ -# Ids - -Several places in the elasticsearch API expect an Id object to be passed. This is a special box type that you can implicitly convert to and from many value types. - -Methods that take an Id can be passed longs, ints, strings -Guids and they will implicitly converted to Ids - -[source, csharp] ----- -Nest.Id idFromInt = 1; -Nest.Id idFromLong = 2L; -Nest.Id idFromString = "hello-world"; -Nest.Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); -Expect(1).WhenSerializing(idFromInt); -Expect(2).WhenSerializing(idFromLong); -Expect("hello-world").WhenSerializing(idFromString); -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); ----- -Sometimes a method takes an object and we need an Id from that object to build up a path. -There is no implicit conversion from any object to Id but we can call Id.From. -Imagine your codebase has the following type that we want to index into elasticsearch - -By default NEST will try to find a property called `Id` on the class using reflection -and create a cached fast func delegate based on the properties getter - -[source, csharp] ----- -var dto = new MyDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; ----- -[source, csharp] ----- -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); ----- -Using the connection settings you can specify a different property NEST should look for ids. -Here we instruct NEST to infer the Id for MyDTO based on its Name property - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.Name) - ) -).Expect("x").WhenInferringIdOn(dto); ----- -Even though we have a cache at play the cache is per connection settings, so we can create a different config - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- -Another way is to mark the type with an ElasticType attribute, using a string IdProperty - -Now when we infer the id we expect it to be the Name property without doing any configuration on the ConnectionSettings - -[source, csharp] ----- -var dto = new MyOtherDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; ----- -[source, csharp] ----- -Expect("x").WhenInferringIdOn(dto); ----- -This attribute IS cached statically/globally, however connectionsettings with a config for the type will -still win over this static configuration - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- -Eventhough we have a cache at play the cache its per connection settings, so we can create a different config - diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Indices/IndicesPaths.doc.asciidoc b/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Indices/IndicesPaths.doc.asciidoc deleted file mode 100644 index cc902f17fde..00000000000 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/Indices/IndicesPaths.doc.asciidoc +++ /dev/null @@ -1,34 +0,0 @@ -# Indices paths - -Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices -In nest this is encoded using `Indices` - -Several types implicitly convert to `Indices` - -[source, csharp] ----- -Nest.Indices singleIndexFromString = "name"; -Nest.Indices multipleIndicesFromString = "name1, name2"; -Nest.Indices allFromString = "_all"; -Nest.Indices allWithOthersFromString = "_all, name2"; -singleIndexFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(1).And.Contain("name") - ); ----- -to ease creating Field's from expressions there is a static Property class you can use - - - -[source, csharp] ----- -var all = Nest.Indices.All; ----- -[source, csharp] ----- -var many = Nest.Indices.Index("name1", "name2"); -var manyTyped = Nest.Indices.Index().And(); -var singleTyped = Nest.Indices.Index(); -var singleString = Nest.Indices.Index("name1"); -var invalidSingleString = Nest.Indices.Index("name1, name2"); ----- diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc b/docs/asciidoc/auto_map.asciidoc similarity index 96% rename from docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc rename to docs/asciidoc/auto_map.asciidoc index 4d9740b2209..04e388cdc21 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Mapping/AutoMap.doc.asciidoc +++ b/docs/asciidoc/auto_map.asciidoc @@ -1,4 +1,6 @@ -# Auto mapping properties +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Auto mapping properties When creating a mapping (either when creating an index or via the put mapping API), NEST offers a feature called AutoMap(), which will automagically infer the correct @@ -9,9 +11,9 @@ in order for your attributes to be applied. We'll look at examples of both. -For these examples, we'll define two POCOS. A Company, which has a name -and a collection of Employees. And Employee, which has various properties of -different types, and itself has a collection of Employees. +For these examples, we'll define two POCOS, `Company`, which has a name +and a collection of Employees, and `Employee` which has various properties of +different types, and itself has a collection of `Employee` types. [source, csharp] @@ -33,7 +35,7 @@ public class Employee public TimeSpan Hours { get; set;} } ---- -## Manual mapping +=== Manual mapping To create a mapping for our Company type, we can use the fluent API and map each property explicitly @@ -67,9 +69,9 @@ var descriptor = new CreateIndexDescriptor("myindex") ); ---- -Which is all fine and dandy, and useful for some use cases. However in most cases -this is becomes too cumbersome of an approach, and you simply just want to map *all* -the properties of your POCO in a single go. +This is all fine and dandy and useful for some use cases however in most cases +this can become verbose and wieldy. The majority of the time you simply just want to map *all* +the properties of a POCO in a single go. [source, csharp] @@ -112,7 +114,7 @@ var expected = new Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- -## Simple Automapping +=== Simple Automapping This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work @@ -841,7 +843,7 @@ var descriptor = new CreateIndexDescriptor("myindex") ---- and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) it will apply the transformation defined in each Visit() respectively, which in this example -disables https://www.elastic.co/guide/en/elasticsearch/guide/current/doc-values.html[doc values]. +disables {ref_current}/doc-values.html[doc values]. [source, csharp] diff --git a/docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc b/docs/asciidoc/bool_dsl.asciidoc similarity index 59% rename from docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc rename to docs/asciidoc/bool_dsl.asciidoc index 8cb24e88afc..20ec761cb73 100644 --- a/docs/asciidoc/QueryDsl/BoolDsl/BoolDsl.doc.asciidoc +++ b/docs/asciidoc/bool_dsl.asciidoc @@ -1,4 +1,11 @@ -Writing boolean queries can grow rather verbose rather quickly using the query DSL e.g +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Bool Queries + + +Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, +take a single `bool` query with only two clauses + [source, csharp] ---- @@ -13,15 +20,17 @@ var searchResults = this.Client.Search(s => s ) ); ---- -now this is just a single bool with only two clauses, imagine multiple nested bools this quickly becomes an exercise in -hadouken indenting +Now, magine multiple nested bools this quickly becomes an exercise in +_hadouken indenting_ [[indent]] .hadouken indenting example -image::http://i.imgur.com/BtjZedW.jpg[dead indent] +image::{imagesdir}/hadouken_indentation.jpg[dead indent] +=== Operator Overloading +For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. +The previous example now becomes the following with the fluent API -For this reason, NEST introduces operator overloading so complex bool queries become easier to write, the previous example will become. [source, csharp] ---- @@ -29,7 +38,7 @@ var searchResults = this.Client.Search(s => s .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) ); ---- -Or using the object initializer syntax +or, using the object initializer syntax [source, csharp] ---- @@ -62,13 +71,15 @@ join them together to become a single bool query -The bool DSL offers also a short hand notation to mark a query as a must_not using ! +The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator + +And to mark a query as a `filter` using the `+` operator -And to mark a query as a filter using + +Both of these can be combined with `&&` to form a single bool query -Both of these can be combined with ands to a single bool query +=== Combining/Merging bool queries -When combining multiple queries some or all possibly marked as must_not or filter NEST still combines to a single bool query +When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query > bool > |___must @@ -109,11 +120,19 @@ Even more involved `term && term && term && !term && +term && +term` still only > |___term -You can still mix and match actual bool queries with the bool dsl e.g +You can still mix and match actual bool queries with the bool DSL e.g + +`bool(must=term, term, term) && !term` would still merge into a single bool query. + + +=== Locked bool queries +NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, +NEST will treat these as locked + +Here we demonstrate that two locked `bool` queries are not combined -`bool(must=term, term, term) && !term` -it would still merge into a single bool query. +neither are two `bool` queries where either the left or the right query is locked [source, csharp] ---- diff --git a/docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc b/docs/asciidoc/children_aggregation_mapping.asciidoc similarity index 83% rename from docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc rename to docs/asciidoc/children_aggregation_mapping.asciidoc index 6e375883cb6..45fe74e251c 100644 --- a/docs/asciidoc/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.asciidoc +++ b/docs/asciidoc/children_aggregation_mapping.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + To use the child aggregation you have to make sure a `_parent` mapping is in place, here we create the project index with two mapped types, `project` and `commitactivity` and diff --git a/docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc b/docs/asciidoc/connecting.asciidoc similarity index 96% rename from docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc rename to docs/asciidoc/connecting.asciidoc index 4aabac1d5b1..67251c1c4ca 100644 --- a/docs/asciidoc/ClientConcepts/LowLevel/Connecting.doc.asciidoc +++ b/docs/asciidoc/connecting.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Connecting Connecting to *Elasticsearch* with `Elasticsearch.Net` is quite easy but has a few toggles and options worth knowing. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc b/docs/asciidoc/connection_pooling.asciidoc similarity index 92% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc rename to docs/asciidoc/connection_pooling.asciidoc index 87b60162c38..e77ddcbb488 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.asciidoc +++ b/docs/asciidoc/connection_pooling.asciidoc @@ -1,9 +1,11 @@ -= Connection Pooling +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Connection Pooling Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which we can use to issue client calls on. -== SingleNodeConnectionPool +=== SingleNodeConnectionPool The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always ready to go. @@ -54,7 +56,7 @@ client = new ElasticClient(new ConnectionSettings(pool)); client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ---- -== StaticConnectionPool +=== StaticConnectionPool The static connection pool is great if you have a known small sized cluster and do no want to enable sniffing to find out the cluster topology. @@ -99,7 +101,7 @@ var client = new ElasticClient(new ConnectionSettings(pool)); client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ---- -== SniffingConnectionPool +=== SniffingConnectionPool A subclass of StaticConnectionPool that allows itself to be reseeded at run time. It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. diff --git a/docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc b/docs/asciidoc/covariant_search_results.asciidoc similarity index 95% rename from docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc rename to docs/asciidoc/covariant_search_results.asciidoc index 67386673400..efb9f19e931 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.asciidoc +++ b/docs/asciidoc/covariant_search_results.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Covariant Search Results NEST directly supports returning covariant result sets. diff --git a/docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc b/docs/asciidoc/date_math_expressions.asciidoc similarity index 94% rename from docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc rename to docs/asciidoc/date_math_expressions.asciidoc index 37b078ccf03..b8e9f87bde7 100644 --- a/docs/asciidoc/CommonOptions/DateMath/DateMathExpressions.doc.asciidoc +++ b/docs/asciidoc/date_math_expressions.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Date Expressions The date type supports using date math expression when using it in a query/filter Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc b/docs/asciidoc/date_time_providers.asciidoc similarity index 88% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc rename to docs/asciidoc/date_time_providers.asciidoc index d3f7c9d7308..96710d5b8d7 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.asciidoc +++ b/docs/asciidoc/date_time_providers.asciidoc @@ -1,4 +1,6 @@ -= Date time providers +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Date time providers Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover @@ -41,7 +43,7 @@ Plotting these defaults looks as followed: [[timeout]] .Default formula, x-axis time in minutes, y-axis number of attempts to revive -image::timeoutplot.png[dead timeout] +image::{imagesdir}/timeoutplot.png[dead timeout] The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc b/docs/asciidoc/descriptors.asciidoc similarity index 94% rename from docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc rename to docs/asciidoc/descriptors.asciidoc index 426b4734e4f..dcc4e0624f0 100644 --- a/docs/asciidoc/CodeStandards/Descriptors.doc.asciidoc +++ b/docs/asciidoc/descriptors.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface diff --git a/docs/asciidoc/disable_sniff_ping_per_request.asciidoc b/docs/asciidoc/disable_sniff_ping_per_request.asciidoc new file mode 100644 index 00000000000..a0df0b0e0b7 --- /dev/null +++ b/docs/asciidoc/disable_sniff_ping_per_request.asciidoc @@ -0,0 +1,79 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Disabling sniffing and pinging on a request basis + +Even if you are using a sniffing connection pool thats set up to sniff on start/failure +and pinging enabled, you can opt out of this behaviour on a per request basis + +In our first test we set up a cluster that pings and sniffs on startup +but we disable the sniffing on our first request so we only see the ping and the response + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) + ); +---- + +We disable sniffing so eventhoug its our first call we do not want to sniff on startup + + + +Instead the sniff on startup is deffered to the second call into the cluster that +does not disable sniffing on a per request basis + + + +And after that no sniff on startup will happen again + + +[source, csharp] +---- +audit = await audit.TraceCalls( +new ClientCall(r=>r.DisableSniffing()) { + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, +new ClientCall() + { + { SniffOnStartup }, + { SniffSuccess, 9200 }, + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, +new ClientCall() + { + { PingSuccess, 9201 }, + { HealthyResponse, 9201 } + } + ); + +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) + ); +audit = await audit.TraceCall( + new ClientCall(r=>r.DisablePing()) { + { SniffOnStartup }, + { SniffSuccess, 9200 }, + { HealthyResponse, 9200 } + } + ); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) + ); +audit = await audit.TraceCall( + new ClientCall(r=>r.DisableSniffing().DisablePing()) { + { HealthyResponse, 9200 } + } + ); +---- diff --git a/docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc b/docs/asciidoc/distance_units.asciidoc similarity index 92% rename from docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc rename to docs/asciidoc/distance_units.asciidoc index cc4333ee7b1..e4c875fd76a 100644 --- a/docs/asciidoc/QueryDsl/Geo/Distance/DistanceUnits.doc.asciidoc +++ b/docs/asciidoc/distance_units.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Distance Units Whenever distances need to be specified, e.g. for a geo distance query, the distance unit can be specified as a double number representing distance in meters, as a new instance of a `Distance`, or as a string diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc b/docs/asciidoc/document_paths.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc rename to docs/asciidoc/document_paths.asciidoc index cf7c5ffb3dc..f619676519e 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.asciidoc +++ b/docs/asciidoc/document_paths.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + = DocumentPaths Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes diff --git a/docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc b/docs/asciidoc/elastic_client.asciidoc similarity index 98% rename from docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc rename to docs/asciidoc/elastic_client.asciidoc index 5c8ca551f5c..5207fbd972f 100644 --- a/docs/asciidoc/CodeStandards/ElasticClient.doc.asciidoc +++ b/docs/asciidoc/elastic_client.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + [source, csharp] ---- var fluentParametersNotNamedSelector = diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc b/docs/asciidoc/falling_over.asciidoc similarity index 84% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc rename to docs/asciidoc/falling_over.asciidoc index 1149214a473..fe4606f88df 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.asciidoc +++ b/docs/asciidoc/falling_over.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Fail over When using connection pooling and the pool has sufficient nodes a request will be retried if the call to a node throws an exception or returns a 502 or 503 @@ -19,7 +21,8 @@ audit = await audit.TraceCall( } ); ---- -502 Bad Gateway +=== 502 Bad Gateway + Will be treated as an error that requires retrying @@ -39,7 +42,8 @@ audit = await audit.TraceCall( } ); ---- -503 Service Unavailable +=== 503 Service Unavailable + Will be treated as an error that requires retrying @@ -60,7 +64,7 @@ audit = await audit.TraceCall( ); ---- -If a call returns a valid http status code other then 502/503 the request won't be retried. +If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. [source, csharp] diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc b/docs/asciidoc/field_inference.asciidoc similarity index 96% rename from docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc rename to docs/asciidoc/field_inference.asciidoc index 277325a18f4..d03c68464ab 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc +++ b/docs/asciidoc/field_inference.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + = Strongly typed field access Several places in the elasticsearch API expect the path to a field from your original source document as a string. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc b/docs/asciidoc/first_usage.asciidoc similarity index 93% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc rename to docs/asciidoc/first_usage.asciidoc index 7aa893703be..960244331a1 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.asciidoc +++ b/docs/asciidoc/first_usage.asciidoc @@ -1,4 +1,6 @@ -== Pinging +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Pinging - First Usage Pinging is enabled by default for the Static & Sniffing connection pool. This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc b/docs/asciidoc/ids_inference.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc rename to docs/asciidoc/ids_inference.asciidoc index c927ec2443f..ca93a7b8ac9 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.asciidoc +++ b/docs/asciidoc/ids_inference.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + = Ids Several places in the elasticsearch API expect an Id object to be passed. diff --git a/docs/asciidoc/ClientConcepts/LowLevel/class.png b/docs/asciidoc/images/class.png similarity index 100% rename from docs/asciidoc/ClientConcepts/LowLevel/class.png rename to docs/asciidoc/images/class.png diff --git a/docs/asciidoc/images/hadouken_indentation.jpg b/docs/asciidoc/images/hadouken_indentation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..afe03b960d1203610f217e1045a22142c0acc720 GIT binary patch literal 43939 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 literal 0 HcmV?d00001 diff --git a/docs/asciidoc/ClientConcepts/LowLevel/pipeline.png b/docs/asciidoc/images/pipeline.png similarity index 100% rename from docs/asciidoc/ClientConcepts/LowLevel/pipeline.png rename to docs/asciidoc/images/pipeline.png diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/timeoutplot.png b/docs/asciidoc/images/timeoutplot.png similarity index 100% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/timeoutplot.png rename to docs/asciidoc/images/timeoutplot.png diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 873adf55c98..41313633127 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -1,4 +1,7 @@ -# Introduction +:github: https://github.com/elastic/elasticsearch-net +:stackoverflow: http://stackoverflow.com + +== Introduction You've reached the documentation page for `Elasticsearch.Net` and `NEST`. The two official .NET clients for Elasticsearch. So why two clients I hear you say? @@ -9,30 +12,29 @@ enough so that **all** the Elasticsearch API endpoints are represented as method Please read the getting started guide for both. +=== Who's using Nest +* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). +* http://www.7digital.com[7digital.com] (run NEST on mono). +* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). +* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. + They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] -## Who's using Nest -* [stackoverflow.com](http://www.stackoverflow.com) (and the rest of the stackexchange family). -* [7digital.com](http://www.7digital.com) (run NEST on mono). -* [rijksmuseum.nl](https://www.rijksmuseum.nl/en) (Elasticsearch is the only datastorage hit for each page). -* [Kiln](http://www.fogcreek.com/kiln/) FogCreek's version control & code review tooling. - They are so pleased with Elasticsearch that [they made a video about how pleased they are!](http://blog.fogcreek.com/kiln-powered-by-elasticsearch/) - -## Other resources +=== Other resources -[@joelabrahamsson](http://twitter.com/joelabrahamsson) wrote a great [intro into elasticsearch on .NET](http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch) +http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a great http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] using NEST. -Also checkout the [searchbox.io guys](https://searchbox.io/) rocking NEST [on AppHarbor](http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on) -with their [demo project](https://github.com/searchbox-io/.net-sample) +Also checkout the https://searchbox.io/[searchbox.io guys] rocking NEST http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] +with their https://github.com/searchbox-io/.net-sample[demo project] -## Questions, bugs, comments, requests +=== Questions, bugs, comments, requests -All of these are more then welcome on the github issues pages! We try to to at least reply within the same day. +All of these are more then welcome on the {github}/issues[github issues pages]! We try to to at least reply within the same day. -We also monitor question tagged with ['nest' on stackoverflow](http://stackoverflow.com/questions/tagged/nest) or -['elasticsearch-net' on stackoverflow](http://stackoverflow.com/questions/tagged/elasticsearch-net) +We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow] -# License +=== License This software is licensed under the Apache 2 license, quoted below. diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc b/docs/asciidoc/indices_paths.asciidoc similarity index 91% rename from docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc rename to docs/asciidoc/indices_paths.asciidoc index 2b12be8ad23..9e084e4b450 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.asciidoc +++ b/docs/asciidoc/indices_paths.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Indices paths Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc b/docs/asciidoc/keeping_track_of_nodes.asciidoc similarity index 93% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc rename to docs/asciidoc/keeping_track_of_nodes.asciidoc index 664157e5f65..26f177a925f 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.asciidoc +++ b/docs/asciidoc/keeping_track_of_nodes.asciidoc @@ -1,4 +1,6 @@ -= Keeping track of nodes +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Keeping track of nodes diff --git a/docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc b/docs/asciidoc/lifetimes.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc rename to docs/asciidoc/lifetimes.asciidoc index 8e37cfba354..313a3668ae4 100644 --- a/docs/asciidoc/ClientConcepts/LowLevel/Lifetimes.doc.asciidoc +++ b/docs/asciidoc/lifetimes.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + ## Lifetimes diff --git a/docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc b/docs/asciidoc/naming_conventions.asciidoc similarity index 94% rename from docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc rename to docs/asciidoc/naming_conventions.asciidoc index fd550dbbe3f..2614827f0ac 100644 --- a/docs/asciidoc/CodeStandards/NamingConventions.doc.asciidoc +++ b/docs/asciidoc/naming_conventions.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Naming Conventions NEST uses the following naming conventions (with _some_ exceptions). diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc b/docs/asciidoc/on_connection_failure.asciidoc similarity index 95% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc rename to docs/asciidoc/on_connection_failure.asciidoc index 778eb9a4056..49376513a51 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.asciidoc +++ b/docs/asciidoc/on_connection_failure.asciidoc @@ -1,4 +1,7 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Sniffing on connection failure + Sniffing on connection is enabled by default when using a connection pool that allows reseeding. The only IConnectionPool we ship that allows this is the SniffingConnectionPool. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc b/docs/asciidoc/on_stale_cluster_state.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc rename to docs/asciidoc/on_stale_cluster_state.asciidoc index 58593850e06..d3d40aa21f4 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.asciidoc +++ b/docs/asciidoc/on_stale_cluster_state.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Sniffing periodically Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc b/docs/asciidoc/on_startup.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc rename to docs/asciidoc/on_startup.asciidoc index 411e888a1d5..7550fbd4e44 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.asciidoc +++ b/docs/asciidoc/on_startup.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Sniffing on startup Connection pools that return true for `SupportsReseeding` by default sniff on startup. diff --git a/docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc b/docs/asciidoc/post_data.asciidoc similarity index 95% rename from docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc rename to docs/asciidoc/post_data.asciidoc index ed7f47c0819..bd2322b36cd 100644 --- a/docs/asciidoc/ClientConcepts/LowLevel/PostData.doc.asciidoc +++ b/docs/asciidoc/post_data.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Post data The low level allows you to post a string, byte[] array directly. On top of this if you pass a list of strings or objects they will be serialized in Elasticsearch's special bulk/multi format. diff --git a/docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc b/docs/asciidoc/properties.asciidoc similarity index 88% rename from docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc rename to docs/asciidoc/properties.asciidoc index 0a0242448e8..8766c544364 100644 --- a/docs/asciidoc/CodeStandards/Serialization/Properties.doc.asciidoc +++ b/docs/asciidoc/properties.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + Our Json.NET contract resolver picks up attributes set on the interface diff --git a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc b/docs/asciidoc/property_inference.asciidoc similarity index 89% rename from docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc rename to docs/asciidoc/property_inference.asciidoc index b7cd1b429f4..4fdb46cf639 100644 --- a/docs/asciidoc/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.asciidoc +++ b/docs/asciidoc/property_inference.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + Property names resolve to the last token. An example using the `.Suffix()` extension diff --git a/docs/asciidoc/CodeStandards/Queries.doc.asciidoc b/docs/asciidoc/queries.asciidoc similarity index 95% rename from docs/asciidoc/CodeStandards/Queries.doc.asciidoc rename to docs/asciidoc/queries.asciidoc index 821fa33f5be..fb845b9b1ca 100644 --- a/docs/asciidoc/CodeStandards/Queries.doc.asciidoc +++ b/docs/asciidoc/queries.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + [source, csharp] ---- var properties = from p in QueryProperties diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc b/docs/asciidoc/request_pipelines.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc rename to docs/asciidoc/request_pipelines.asciidoc index 8dcbe1f5eef..119366843dc 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.asciidoc +++ b/docs/asciidoc/request_pipelines.asciidoc @@ -1,13 +1,16 @@ -= Request pipeline -Every request is executed in the context of `RequestPipeline` when using the default `ITransport` implementation. +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current +== Request pipeline + +Every request is executed in the context of a `RequestPipeline` when using the +default `ITransport` implementation. [source, csharp] ---- var settings = TestClient.CreateSettings(); ---- -When calling Request(Async) on Transport the whole coordination of the request is deferred to a new instance in a `using` block. +When calling Request/RequestAsync on Transport the whole coordination of the request is deferred to a new instance in a `using` block. [source, csharp] ---- diff --git a/docs/asciidoc/request_timeouts_overrides.asciidoc b/docs/asciidoc/request_timeouts_overrides.asciidoc new file mode 100644 index 00000000000..a4284d4860a --- /dev/null +++ b/docs/asciidoc/request_timeouts_overrides.asciidoc @@ -0,0 +1,95 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Request Timeouts + +While you can specify Request time out globally you can override this per request too + + +we set up a 10 node cluster with a global time out of 20 seconds. +Each call on a node takes 10 seconds. So we can only try this call on 2 nodes +before the max request time out kills the client call. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) +); +---- + +On the second request we specify a request timeout override to 60 seconds +We should now see more nodes being tried. + + +[source, csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxTimeoutReached } + }, +new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) + { + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 }, + } +); +---- +== Connect Timeouts +Connect timeouts can be overridden, webrequest/httpclient can not distinguish connect and retry timeouts however +we use this separate configuration value for ping requests. + + +we set up a 10 node cluster with a global time out of 20 seconds. +Each call on a node takes 10 seconds. So we can only try this call on 2 nodes +before the max request time out kills the client call. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) + .ClientCalls(r => r.SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) +); +---- + +The first call uses the configured global settings, request times out after 10 seconds and ping +calls always take 20, so we should see a single ping failure + + + +On the second request we set a request ping timeout override of 2seconds +We should now see more nodes being tried before the request timeout is hit. + + +[source, csharp] +---- +audit = await audit.TraceCalls( +new ClientCall { + { PingFailure, 9200 }, + { MaxTimeoutReached } + }, +new ClientCall(r => r.PingTimeout(TimeSpan.FromSeconds(2))) + { + { PingFailure, 9202 }, + { PingFailure, 9203 }, + { PingFailure, 9204 }, + { PingFailure, 9205 }, + { PingFailure, 9206 }, + { MaxTimeoutReached } + } +); +---- diff --git a/docs/asciidoc/respects_allowed_status_code.asciidoc b/docs/asciidoc/respects_allowed_status_code.asciidoc new file mode 100644 index 00000000000..d2814867afa --- /dev/null +++ b/docs/asciidoc/respects_allowed_status_code.asciidoc @@ -0,0 +1,22 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Allowed status codes + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(400)) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(0)) + ); +audit = await audit.TraceCalls( + new ClientCall() { + { BadResponse, 9200 } + }, + new ClientCall(r => r.AllowedStatusCodes(400)) { + { HealthyResponse, 9201 } + } + ); +---- diff --git a/docs/asciidoc/respects_force_node.asciidoc b/docs/asciidoc/respects_force_node.asciidoc new file mode 100644 index 00000000000..fd95567d129 --- /dev/null +++ b/docs/asciidoc/respects_force_node.asciidoc @@ -0,0 +1,22 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Forcing nodes +Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` +request configuration. This will ignore the pool and not retry. + + +[source, csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9208).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); +audit = await audit.TraceCall( + new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { + { BadResponse, 9208 } + } + ); +---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc b/docs/asciidoc/respects_max_retry.asciidoc similarity index 95% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc rename to docs/asciidoc/respects_max_retry.asciidoc index 7789c95c8cd..ffcd07c6c7e 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.asciidoc +++ b/docs/asciidoc/respects_max_retry.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == MaxRetries By default retry as many times as we have nodes. However retries still respect the request timeout. Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc b/docs/asciidoc/respects_max_retry_overrides.asciidoc similarity index 92% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc rename to docs/asciidoc/respects_max_retry_overrides.asciidoc index 40b678d12de..ada9e0ac7b2 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.asciidoc +++ b/docs/asciidoc/respects_max_retry_overrides.asciidoc @@ -1,4 +1,7 @@ -== MaxRetries +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Maximum Retries + By default retry as many times as we have nodes. However retries still respect the request timeout. Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc b/docs/asciidoc/revival.asciidoc similarity index 92% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc rename to docs/asciidoc/revival.asciidoc index a8bd14380a3..6ba6c41ad98 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.asciidoc +++ b/docs/asciidoc/revival.asciidoc @@ -1,4 +1,6 @@ -== Pinging +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Pinging - Revival When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.asciidoc b/docs/asciidoc/role_detection.asciidoc similarity index 98% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.asciidoc rename to docs/asciidoc/role_detection.asciidoc index 576d9500d74..e1e87529c21 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.asciidoc +++ b/docs/asciidoc/role_detection.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Sniffing role detection When we sniff the custer state we detect the role of the node whether its master eligible and holds data diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc b/docs/asciidoc/round_robin.asciidoc similarity index 94% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc rename to docs/asciidoc/round_robin.asciidoc index 76322255b04..da10d7e09ed 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.asciidoc +++ b/docs/asciidoc/round_robin.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + Round Robin Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc b/docs/asciidoc/skip_dead_nodes.asciidoc similarity index 91% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc rename to docs/asciidoc/skip_dead_nodes.asciidoc index 0cb4f4f4d5f..0cbe619ea0e 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.asciidoc +++ b/docs/asciidoc/skip_dead_nodes.asciidoc @@ -1,8 +1,11 @@ -Round Robin - Skipping Dead Nodes +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Round Robin - Skipping Dead Nodes + When selecting nodes the connection pool will try and skip all the nodes that are marked dead. -== GetNext +=== GetNext GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. @@ -26,7 +29,7 @@ node.Uri.Port.Should().Be(9201); node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); ---- -After we marke the first node alive again we expect it to be hit again +After we marked the first node alive again, we expect it to be hit again [source, csharp] ---- @@ -47,7 +50,7 @@ node.Uri.Port.Should().Be(9201); node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); ---- -If we forward our clock 2 days the node that was marked dead until tomorrow (or yesterday!) should be resurrected +If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected [source, csharp] ---- diff --git a/docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc b/docs/asciidoc/time_units.asciidoc similarity index 95% rename from docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc rename to docs/asciidoc/time_units.asciidoc index 0cd133a1c36..fe1d7422eb7 100644 --- a/docs/asciidoc/CommonOptions/TimeUnit/TimeUnits.doc.asciidoc +++ b/docs/asciidoc/time_units.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + # Time units Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc b/docs/asciidoc/transports.asciidoc similarity index 91% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc rename to docs/asciidoc/transports.asciidoc index 44786fca5fd..f70933bdff8 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.asciidoc +++ b/docs/asciidoc/transports.asciidoc @@ -1,4 +1,6 @@ -= Transports +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + +== Transports The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote @@ -16,7 +18,7 @@ e.g in the low level client, transport is instantiated like this: ---- var lowLevelTransport = new Transport(new ConnectionConfiguration()); ---- -In the high level client like this: +and in the high level client, like this: [source, csharp] ---- diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc b/docs/asciidoc/unexpected_exceptions.asciidoc similarity index 95% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc rename to docs/asciidoc/unexpected_exceptions.asciidoc index 5c991fcffd2..71921521717 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnexpectedExceptions.doc.asciidoc +++ b/docs/asciidoc/unexpected_exceptions.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Unexpected exceptions When a client call throws an exception that the IConnction can not handle, this exception will bubble out the client as an UnexpectedElasticsearchClientException, regardless whether the client is configured to throw or not. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc b/docs/asciidoc/unrecoverable_exceptions.asciidoc similarity index 93% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc rename to docs/asciidoc/unrecoverable_exceptions.asciidoc index 31f22d65f29..802512fdd5e 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.asciidoc +++ b/docs/asciidoc/unrecoverable_exceptions.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + == Unrecoverable exceptions Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. By default the client won't throw on any ElasticsearchClientException but return an invalid response. diff --git a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc b/docs/asciidoc/volatile_updates.asciidoc similarity index 90% rename from docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc rename to docs/asciidoc/volatile_updates.asciidoc index 902a069e86a..c4e8592ac87 100644 --- a/docs/asciidoc/ClientConcepts/ConnectionPooling/RoundRobin/VolatileUpdates.doc.asciidoc +++ b/docs/asciidoc/volatile_updates.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + diff --git a/docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc b/docs/asciidoc/writing_aggregations.asciidoc similarity index 95% rename from docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc rename to docs/asciidoc/writing_aggregations.asciidoc index 84ee2a45592..6be9d4ac159 100644 --- a/docs/asciidoc/Aggregations/WritingAggregations.doc.asciidoc +++ b/docs/asciidoc/writing_aggregations.asciidoc @@ -1,3 +1,5 @@ +:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current + Aggregations are arguably one of the most powerful features of Elasticsearch. NEST allows you to write your aggregations using a strict fluent dsl, a verbatim object initializer diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index 47487b5fe03..c413261ff99 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -16,6 +16,9 @@ internal CSharpDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } private string RenderBlocksToDocumentation(IEnumerable blocks) { var builder = new StringBuilder(); + + RenderHeader(builder); + var lastBlockWasCodeBlock = false; RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock); @@ -26,9 +29,14 @@ private string RenderBlocksToDocumentation(IEnumerable bloc return builder.ToString(); } + private void RenderHeader(StringBuilder builder) + { + builder.AppendLine(":ref_current: http://www.elastic.co/guide/elasticsearch/reference/current"); + builder.AppendLine(); + } + private void RenderFooter(StringBuilder builder) { - builder.AppendLine(":ref: http://www.elastic.co/guide/elasticsearch/reference/current"); } private void RenderBlocksToDocumentation(IEnumerable blocks, StringBuilder builder, ref bool lastBlockWasCodeBlock) diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs index 6831fb5b779..1fdaba08261 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs @@ -1,6 +1,8 @@ using System; using System.IO; +using System.Reflection.Emit; using System.Text.RegularExpressions; +using Nest.Litterateur; namespace Nest.Litterateur.Documentation.Files { @@ -26,7 +28,9 @@ public static DocumentationFile Load(FileInfo fileLocation) return new CSharpDocumentationFile(fileLocation); case ".gif": case ".jpg": + case ".jpeg": case ".png": + return new ImageDocumentationFile(fileLocation); case ".asciidoc": return new RawDocumentationFile(fileLocation); } @@ -37,13 +41,17 @@ public static DocumentationFile Load(FileInfo fileLocation) protected virtual FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; - var testInDocumentationFolder = Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "") + ".asciidoc"; + + var testInDocumentationFolder = + Path.GetFileNameWithoutExtension(testFullPath).TrimDocExtension().PascalToUnderscore() + ".asciidoc"; var documentationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, testInDocumentationFolder)); var fileInfo = new FileInfo(documentationTargetPath); + if (fileInfo.Directory != null) Directory.CreateDirectory(fileInfo.Directory.FullName); + return fileInfo; - } + } } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs new file mode 100644 index 00000000000..a9ee3bfc9f1 --- /dev/null +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs @@ -0,0 +1,21 @@ +using System.IO; + +namespace Nest.Litterateur.Documentation.Files +{ + public class ImageDocumentationFile : RawDocumentationFile + { + public ImageDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } + + protected override FileInfo CreateDocumentationLocation() + { + var testFullPath = this.FileLocation.FullName; + var testInDocumenationFolder = Path.GetFileName(testFullPath).PascalToUnderscore(); + + var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, "images", testInDocumenationFolder)); + var fileInfo = new FileInfo(documenationTargetPath); + if (fileInfo.Directory != null) + Directory.CreateDirectory(fileInfo.Directory.FullName); + return fileInfo; + } + } +} \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs index eb1a4d01550..a976cb3080f 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs @@ -17,7 +17,7 @@ public override void SaveToDocumentationFolder() protected override FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; - var testInDocumenationFolder = Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "") + this.Extension; + var testInDocumenationFolder = Path.GetFileName(testFullPath).PascalToUnderscore(); var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, testInDocumenationFolder)); var fileInfo = new FileInfo(documenationTargetPath); diff --git a/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs b/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs index 7f67ed50c2f..5ea9733336e 100644 --- a/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; namespace Nest.Litterateur { @@ -38,4 +39,26 @@ public static IEnumerable Intertwine(this IEnumerable one, IEnumerable< } } + + public static class StringExtensions + { + public static string PascalToUnderscore(this string input) + { + if (string.IsNullOrEmpty(input)) return string.Empty; + + return Regex.Replace( + Regex.Replace( + Regex.Replace(input, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-z\d])([A-Z])", "$1_$2") + , @"[-\s]", "_").ToLower(); + } + + public static string TrimDocExtension(this string input) + { + if (string.IsNullOrEmpty(input)) return string.Empty; + + return input.EndsWith(".doc", StringComparison.OrdinalIgnoreCase) + ? input.Substring(0, input.Length - 4) + : input; + } + } } diff --git a/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs b/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs index 80578ed3a1b..11eaab86d96 100644 --- a/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs @@ -11,6 +11,24 @@ namespace Nest.Litterateur.Linker /// public class Linker { + public Linker() + { + + } + public void GenerateIndex() + { + // TODO: harvest all the doc ids and write out an index file containing links for all + } + + public void GenerateHeaderIds() + { + + } + + public void GenerateAttributes() + { + + } } } diff --git a/src/CodeGeneration/Nest.Litterateur/LitUp.cs b/src/CodeGeneration/Nest.Litterateur/LitUp.cs index d4256b43960..66dfd2771cc 100644 --- a/src/CodeGeneration/Nest.Litterateur/LitUp.cs +++ b/src/CodeGeneration/Nest.Litterateur/LitUp.cs @@ -21,8 +21,9 @@ public static IEnumerable> Input { yield return InputFiles("doc.cs"); yield return InputFiles("asciidoc"); - yield return InputFiles("ping"); + yield return InputFiles("png"); yield return InputFiles("gif"); + yield return InputFiles("jpg"); } } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs index 8b783966feb..4fde0cd5202 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs @@ -9,12 +9,12 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class ConnectionPooling { - /** = Connection Pooling + /** == Connection Pooling * Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which * we can use to issue client calls on. */ - /** == SingleNodeConnectionPool + /** === SingleNodeConnectionPool * The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls * It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always * ready to go. @@ -46,7 +46,7 @@ [U] public void SingleNode() client.ConnectionSettings.ConnectionPool.Should().BeOfType(); } - /** == StaticConnectionPool + /** === StaticConnectionPool * The static connection pool is great if you have a known small sized cluster and do no want to enable * sniffing to find out the cluster topology. */ @@ -74,7 +74,7 @@ [U] public void Static() client.ConnectionSettings.ConnectionPool.Should().BeOfType(); } - /** == SniffingConnectionPool + /** === SniffingConnectionPool * A subclass of StaticConnectionPool that allows itself to be reseeded at run time. * It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs index 472e0af5659..b65850ad8ea 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs @@ -9,7 +9,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks public class DateTimeProviders { - /** = Date time providers + /** == Date time providers * * Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` * in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover @@ -42,7 +42,7 @@ [U] public void DeadTimeoutCalculation() * *[[timeout]] *.Default formula, x-axis time in minutes, y-axis number of attempts to revive - *image::timeoutplot.png[dead timeout] + *image::{imagesdir}/timeoutplot.png[dead timeout] * * The goal here is that whenever a node is resurrected and is found to still be offline, we send it * _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs index 31419eb4e5a..49c64481fe7 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs @@ -8,7 +8,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks public class KeepingTrackOfNodes { - /** = Keeping track of nodes + /** == Keeping track of nodes * */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs index 5ce62fa6731..10ea5b93474 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs @@ -10,9 +10,10 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class RequestPipelines { - /** = Request pipeline - * Every request is executed in the context of `RequestPipeline` when using the default `ITransport` implementation. - * + /** == Request pipeline + * + * Every request is executed in the context of a `RequestPipeline` when using the + * default `ITransport` implementation. */ [U] @@ -20,7 +21,7 @@ public void RequestPipeline() { var settings = TestClient.CreateSettings(); - /** When calling Request(Async) on Transport the whole coordination of the request is deferred to a new instance in a `using` block. */ + /** When calling Request/RequestAsync on Transport the whole coordination of the request is deferred to a new instance in a `using` block. */ var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); pipeline.GetType().Should().Implement(); diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs index a399c373213..27907f1d0b7 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs @@ -8,7 +8,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class Transports { - /** = Transports + /** == Transports * * The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. * It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote @@ -25,7 +25,7 @@ public async Task InterfaceExplained() */ var lowLevelTransport = new Transport(new ConnectionConfiguration()); - /** In the high level client like this: */ + /** and in the high level client, like this: */ var highlevelTransport = new Transport(new ConnectionSettings()); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs index a7d23a0873b..266d4772651 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs @@ -33,7 +33,8 @@ public async Task ExceptionFallsOverToNextNode() ); } - /** 502 Bad Gateway + /** === 502 Bad Gateway + * * Will be treated as an error that requires retrying */ [U] @@ -55,7 +56,8 @@ public async Task Http502FallsOver() ); } - /** 503 Service Unavailable + /** === 503 Service Unavailable + * * Will be treated as an error that requires retrying */ [U] @@ -78,7 +80,7 @@ public async Task Http503FallsOver() } /** - * If a call returns a valid http status code other then 502/503 the request won't be retried. + * If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. */ [U] public async Task HttpTeapotDoesNotFallOver() diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs index 7339fd73400..b45e7f72c9a 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs @@ -11,7 +11,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.Pinging { public class FirstUsage { - /** == Pinging + /** == Pinging - First Usage * * Pinging is enabled by default for the Static & Sniffing connection pool. * This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs index 3a2fce7d519..cef68dd016a 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs @@ -11,7 +11,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.Pinging { public class Revival { - /** == Pinging + /** == Pinging - Revival * * When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping * before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs similarity index 96% rename from src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.cs rename to src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs index 427ff1156b3..f4cab6e9b1d 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs @@ -1,92 +1,93 @@ -using System; -using System.Threading.Tasks; -using Elasticsearch.Net; -using Tests.Framework; -using static Elasticsearch.Net.AuditEvent; - -namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides -{ - public class DisableSniffPingPerRequest - { - /** == Disabling sniffing and pinging on a request basis - * Even if you are using a sniffing connection pool thats set up to sniff on start/failure - * and pinging enabled, you can opt out of this behaviour on a per request basis - * - * In our first test we set up a cluster that pings and sniffs on startup - * but we disable the sniffing on our first request so we only see the ping and the response - */ - - [U] public async Task DisableSniff() - { - var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); - - audit = await audit.TraceCalls( - /** - * We disable sniffing so eventhoug its our first call we do not want to sniff on startup - */ - new ClientCall(r=>r.DisableSniffing()) { - { PingSuccess, 9200 }, - { HealthyResponse, 9200 } - }, - /** - * Instead the sniff on startup is deffered to the second call into the cluster that - * does not disable sniffing on a per request basis - */ - new ClientCall() - { - { SniffOnStartup }, - { SniffSuccess, 9200 }, - { PingSuccess, 9200 }, - { HealthyResponse, 9200 } - }, - /** - * And after that no sniff on startup will happen again - */ - new ClientCall() - { - { PingSuccess, 9201 }, - { HealthyResponse, 9201 } - } - ); - } - - [U] public async Task DisablePing() - { - var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); - - audit = await audit.TraceCall( - new ClientCall(r=>r.DisablePing()) { - { SniffOnStartup }, - { SniffSuccess, 9200 }, - { HealthyResponse, 9200 } - } - ); - } - - [U] public async Task DisableSniffAndPing() - { - var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); - - audit = await audit.TraceCall( - new ClientCall(r=>r.DisableSniffing().DisablePing()) { - { HealthyResponse, 9200 } - } - ); - } - } -} +using System; +using System.Threading.Tasks; +using Elasticsearch.Net; +using Tests.Framework; +using static Elasticsearch.Net.AuditEvent; + +namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides +{ + public class DisableSniffPingPerRequest + { + /** == Disabling sniffing and pinging on a request basis + * + * Even if you are using a sniffing connection pool thats set up to sniff on start/failure + * and pinging enabled, you can opt out of this behaviour on a per request basis + * + * In our first test we set up a cluster that pings and sniffs on startup + * but we disable the sniffing on our first request so we only see the ping and the response + */ + + [U] public async Task DisableSniff() + { + var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) + ); + + audit = await audit.TraceCalls( + /** + * We disable sniffing so eventhoug its our first call we do not want to sniff on startup + */ + new ClientCall(r=>r.DisableSniffing()) { + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, + /** + * Instead the sniff on startup is deffered to the second call into the cluster that + * does not disable sniffing on a per request basis + */ + new ClientCall() + { + { SniffOnStartup }, + { SniffSuccess, 9200 }, + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, + /** + * And after that no sniff on startup will happen again + */ + new ClientCall() + { + { PingSuccess, 9201 }, + { HealthyResponse, 9201 } + } + ); + } + + [U] public async Task DisablePing() + { + var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) + ); + + audit = await audit.TraceCall( + new ClientCall(r=>r.DisablePing()) { + { SniffOnStartup }, + { SniffSuccess, 9200 }, + { HealthyResponse, 9200 } + } + ); + } + + [U] public async Task DisableSniffAndPing() + { + var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) + ); + + audit = await audit.TraceCall( + new ClientCall(r=>r.DisableSniffing().DisablePing()) { + { HealthyResponse, 9200 } + } + ); + } + } +} diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs similarity index 97% rename from src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.cs rename to src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs index 703726dd4dd..447b5f430e8 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs @@ -6,19 +6,20 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class RequestTimeoutsOverrides - { + { /** == Request Timeouts + * * While you can specify Request time out globally you can override this per request too - */ - - [U] + */ + + [U] public async Task RespectsRequestTimeoutOverride() - { - + { + /** we set up a 10 node cluster with a global time out of 20 seconds. * Each call on a node takes 10 seconds. So we can only try this call on 2 nodes * before the max request time out kills the client call. - */ + */ var audit = new Auditor(() => Framework.Cluster .Nodes(10) .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) @@ -30,70 +31,70 @@ public async Task RespectsRequestTimeoutOverride() audit = await audit.TraceCalls( new ClientCall { { BadResponse, 9200 }, - { BadResponse, 9201 }, + { BadResponse, 9201 }, { MaxTimeoutReached } - }, + }, /** * On the second request we specify a request timeout override to 60 seconds * We should now see more nodes being tried. - */ - new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) - { - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { BadResponse, 9205 }, - { BadResponse, 9206 }, - { BadResponse, 9207 }, - { BadResponse, 9208 }, - { HealthyResponse, 9209 }, - } + */ + new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) + { + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 }, + } + ); + + } + + /** == Connect Timeouts + * Connect timeouts can be overridden, webrequest/httpclient can not distinguish connect and retry timeouts however + * we use this separate configuration value for ping requests. + */ + [U] + public async Task RespectsConnectTimeoutOverride() + { + /** we set up a 10 node cluster with a global time out of 20 seconds. + * Each call on a node takes 10 seconds. So we can only try this call on 2 nodes + * before the max request time out kills the client call. + */ + var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) + .ClientCalls(r => r.SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) + ); + + audit = await audit.TraceCalls( + /** + * The first call uses the configured global settings, request times out after 10 seconds and ping + * calls always take 20, so we should see a single ping failure + */ + new ClientCall { + { PingFailure, 9200 }, + { MaxTimeoutReached } + }, + /** + * On the second request we set a request ping timeout override of 2seconds + * We should now see more nodes being tried before the request timeout is hit. + */ + new ClientCall(r => r.PingTimeout(TimeSpan.FromSeconds(2))) + { + { PingFailure, 9202 }, + { PingFailure, 9203 }, + { PingFailure, 9204 }, + { PingFailure, 9205 }, + { PingFailure, 9206 }, + { MaxTimeoutReached } + } ); - } - - /** == Connect Timeouts - * Connect timeouts can be overridden, webrequest/httpclient can not distinguish connect and retry timeouts however - * we use this separate configuration value for ping requests. - */ - [U] - public async Task RespectsConnectTimeoutOverride() - { - /** we set up a 10 node cluster with a global time out of 20 seconds. - * Each call on a node takes 10 seconds. So we can only try this call on 2 nodes - * before the max request time out kills the client call. - */ - var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) - .ClientCalls(r => r.SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) - ); - - audit = await audit.TraceCalls( - /** - * The first call uses the configured global settings, request times out after 10 seconds and ping - * calls always take 20, so we should see a single ping failure - */ - new ClientCall { - { PingFailure, 9200 }, - { MaxTimeoutReached } - }, - /** - * On the second request we set a request ping timeout override of 2seconds - * We should now see more nodes being tried before the request timeout is hit. - */ - new ClientCall(r => r.PingTimeout(TimeSpan.FromSeconds(2))) - { - { PingFailure, 9202 }, - { PingFailure, 9203 }, - { PingFailure, 9204 }, - { PingFailure, 9205 }, - { PingFailure, 9206 }, - { MaxTimeoutReached } - } - ); - } } } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs similarity index 95% rename from src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.cs rename to src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs index eca019f4184..aba2328ac53 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs @@ -1,34 +1,34 @@ -using System; -using System.Threading.Tasks; -using Elasticsearch.Net; -using Tests.Framework; -using static Elasticsearch.Net.AuditEvent; - -namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides -{ - public class RespectsAllowedStatusCode - { - /** == Allowed status codes - */ - - [U] - public async Task CanOverrideBadResponse() - { - var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(400)) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(0)) - ); - - audit = await audit.TraceCalls( - new ClientCall() { - { BadResponse, 9200 } - }, - new ClientCall(r => r.AllowedStatusCodes(400)) { - { HealthyResponse, 9201 } - } - ); - } - } -} +using System; +using System.Threading.Tasks; +using Elasticsearch.Net; +using Tests.Framework; +using static Elasticsearch.Net.AuditEvent; + +namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides +{ + public class RespectsAllowedStatusCode + { + /** == Allowed status codes + */ + + [U] + public async Task CanOverrideBadResponse() + { + var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(400)) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(0)) + ); + + audit = await audit.TraceCalls( + new ClientCall() { + { BadResponse, 9200 } + }, + new ClientCall(r => r.AllowedStatusCodes(400)) { + { HealthyResponse, 9201 } + } + ); + } + } +} diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs similarity index 96% rename from src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.cs rename to src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs index 4f7d0bdd40e..3095f90f84c 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs @@ -1,34 +1,34 @@ -using System; -using System.Threading.Tasks; -using Elasticsearch.Net; -using Tests.Framework; -using static Elasticsearch.Net.AuditEvent; - -namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides -{ - public class RespectsForceNode - { - /** == Forcing nodes - * Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` - * request configuration. This will ignore the pool and not retry. - */ - - [U] - public async Task OnlyCallsForcedNode() - { - var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9208).FailAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); - - audit = await audit.TraceCall( - new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { - { BadResponse, 9208 } - } - ); - } - } -} +using System; +using System.Threading.Tasks; +using Elasticsearch.Net; +using Tests.Framework; +using static Elasticsearch.Net.AuditEvent; + +namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides +{ + public class RespectsForceNode + { + /** == Forcing nodes + * Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` + * request configuration. This will ignore the pool and not retry. + */ + + [U] + public async Task OnlyCallsForcedNode() + { + var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9208).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) + ); + + audit = await audit.TraceCall( + new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { + { BadResponse, 9208 } + } + ); + } + } +} diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs index f419cfacc34..c4db54d687f 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class RespectsMaxRetryOverrides { - /** == MaxRetries + /** == Maximum Retries + * * By default retry as many times as we have nodes. However retries still respect the request timeout. * Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can * but give up after 20 seconds diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.cs index 18624805b34..2429ad96fbf 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/SkipDeadNodes.doc.cs @@ -12,11 +12,12 @@ namespace Tests.ClientConcepts.ConnectionPooling.RoundRobin { public class SkippingDeadNodes { - /** Round Robin - Skipping Dead Nodes + /** == Round Robin - Skipping Dead Nodes + * * When selecting nodes the connection pool will try and skip all the nodes that are marked dead. */ - /** == GetNext + /** === GetNext * GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance * over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without * suffering from noisy neighboors advancing a global cursor. @@ -51,7 +52,7 @@ [U] public void EachViewSeesNextButSkipsTheDeadNode() node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); } - /** After we marke the first node alive again we expect it to be hit again*/ + /** After we marked the first node alive again, we expect it to be hit again*/ seeds.First().MarkAlive(); for (var i = 0; i < 20; i++) { @@ -76,7 +77,7 @@ [U] public void ViewSeesResurrectedNodes() node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); } - /** If we forward our clock 2 days the node that was marked dead until tomorrow (or yesterday!) should be resurrected */ + /** If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected */ dateTimeProvider.ChangeTime(d => d.AddDays(2)); var n = pool.CreateView().First(); n.Uri.Port.Should().Be(9201); diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs index c2ed84ad5ba..c1f52b4f2d0 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs @@ -10,6 +10,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.Sniffing public class OnConnectionFailure { /** == Sniffing on connection failure + * * Sniffing on connection is enabled by default when using a connection pool that allows reseeding. * The only IConnectionPool we ship that allows this is the SniffingConnectionPool. * diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index 1f6149a4993..89dc690f749 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -8,7 +8,7 @@ namespace Tests.ClientConcepts.HighLevel.Mapping { - /** # Auto mapping properties + /** == Auto mapping properties * * When creating a mapping (either when creating an index or via the put mapping API), * NEST offers a feature called AutoMap(), which will automagically infer the correct @@ -20,9 +20,9 @@ namespace Tests.ClientConcepts.HighLevel.Mapping public class AutoMap { /** - * For these examples, we'll define two POCOS. A Company, which has a name - * and a collection of Employees. And Employee, which has various properties of - * different types, and itself has a collection of Employees. + * For these examples, we'll define two POCOS, `Company`, which has a name + * and a collection of Employees, and `Employee` which has various properties of + * different types, and itself has a collection of `Employee` types. */ public class Company { @@ -44,7 +44,7 @@ public class Employee [U] public void MappingManually() { - /** ## Manual mapping + /** === Manual mapping * To create a mapping for our Company type, we can use the fluent API * and map each property explicitly */ @@ -75,9 +75,9 @@ public void MappingManually() ); /** - * Which is all fine and dandy, and useful for some use cases. However in most cases - * this is becomes too cumbersome of an approach, and you simply just want to map *all* - * the properties of your POCO in a single go. + * This is all fine and dandy and useful for some use cases however in most cases + * this can become verbose and wieldy. The majority of the time you simply just want to map *all* + * the properties of a POCO in a single go. */ var expected = new { @@ -121,7 +121,7 @@ public void MappingManually() [U] public void UsingAutoMap() { - /** ## Simple Automapping + /** === Simple Automapping * This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, * explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work */ @@ -835,7 +835,7 @@ public void UsingACustomPropertyVisitor() /** and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) * it will apply the transformation defined in each Visit() respectively, which in this example - * disables https://www.elastic.co/guide/en/elasticsearch/guide/current/doc-values.html[doc values]. + * disables {ref_current}/doc-values.html[doc values]. */ var expected = new { diff --git a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs index 7082f9fe20c..7b25522564b 100644 --- a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs +++ b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs @@ -9,11 +9,15 @@ namespace Tests.QueryDsl.BoolDsl { + /** == Bool Queries + */ public class BoolDslTests : OperatorUsageBase { protected readonly IElasticClient Client = TestClient.GetFixedReturnClient(new { }); - /** Writing boolean queries can grow rather verbose rather quickly using the query DSL e.g */ + /** Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, + * take a single `bool` query with only two clauses + */ public void VerboseWay() { var searchResults = this.Client.Search(s => s @@ -27,22 +31,23 @@ public void VerboseWay() ) ); } - /** now this is just a single bool with only two clauses, imagine multiple nested bools this quickly becomes an exercise in - hadouken indenting + /** Now, magine multiple nested bools this quickly becomes an exercise in + * _hadouken indenting_ * *[[indent]] *.hadouken indenting example - *image::http://i.imgur.com/BtjZedW.jpg[dead indent] + *image::{imagesdir}/hadouken_indentation.jpg[dead indent] * - - * For this reason, NEST introduces operator overloading so complex bool queries become easier to write, the previous example will become. */ - + * === Operator Overloading + * For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. + * The previous example now becomes the following with the fluent API + */ public void UsingOperator() { var searchResults = this.Client.Search(s => s .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) ); - /** Or using the object initializer syntax */ + /** or, using the object initializer syntax */ searchResults = this.Client.Search(new SearchRequest { Query = new TermQuery { Field = "name", Value= "x" } @@ -51,9 +56,9 @@ public void UsingOperator() } /** A naive implementation of operator overloading would rewrite - + * * `term && term && term` to - + * *> bool *> |___must *> |___term @@ -61,16 +66,16 @@ public void UsingOperator() *> |___must *> |___term *> |___term - + * * As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and * join them together to become a single bool query - + * *> bool *> |___must *> |___term *> |___term *> |___term - + * */ [U] public void JoinsMustQueries() => @@ -80,21 +85,25 @@ [U] public void JoinsMustQueries() => c => c.Bool.Must.Should().HaveCount(3) ); - /** The bool DSL offers also a short hand notation to mark a query as a must_not using ! */ + /** The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator */ + [U] public void MustNotOperator() => + Assert(q => !q.Query(), !Query, c => c.Bool.MustNot.Should().HaveCount(1)); - [U] public void MustNotOperator() => Assert(q => !q.Query(), !Query, c => c.Bool.MustNot.Should().HaveCount(1)); + /** And to mark a query as a `filter` using the `+` operator*/ + [U] public void UnaryAddOperator() => + Assert(q => +q.Query(), +Query, c => c.Bool.Filter.Should().HaveCount(1)); - /** And to mark a query as a filter using + */ + /** Both of these can be combined with `&&` to form a single bool query */ + [U] public void MustNotOperatorAnd() => + Assert(q => !q.Query() && !q.Query(), !Query && !Query, c => c.Bool.MustNot.Should().HaveCount(2)); - [U] public void UnaryAddOperator() => Assert(q => +q.Query(), +Query, c => c.Bool.Filter.Should().HaveCount(1)); - - /** Both of these can be combined with ands to a single bool query */ - - [U] public void MustNotOperatorAnd() => Assert(q => !q.Query() && !q.Query(), !Query && !Query, c => c.Bool.MustNot.Should().HaveCount(2)); - [U] public void UnaryAddOperatorAnd() => Assert(q => +q.Query() && +q.Query(), +Query && +Query, c => c.Bool.Filter.Should().HaveCount(2)); - - /** When combining multiple queries some or all possibly marked as must_not or filter NEST still combines to a single bool query + [U] public void UnaryAddOperatorAnd() => + Assert(q => +q.Query() && +q.Query(), +Query && +Query, c => c.Bool.Filter.Should().HaveCount(2)); + /** === Combining/Merging bool queries + * + * When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query + * *> bool *> |___must *> | |___term @@ -145,12 +154,10 @@ [U] public void JoinsMustWithMustNotAndFilter() => c.Bool.Filter.Should().HaveCount(2); }); - /** You can still mix and match actual bool queries with the bool dsl e.g - - * `bool(must=term, term, term) && !term` - - * it would still merge into a single bool query. */ - + /** You can still mix and match actual bool queries with the bool DSL e.g + * + * `bool(must=term, term, term) && !term` would still merge into a single bool query. + */ [U] public void MixAndMatch() => Assert( q => q.Bool(b=>b.Must(mq=>mq.Query(),mq=>mq.Query(), mq=>mq.Query())) && !q.Query(), @@ -161,10 +168,10 @@ [U] public void MixAndMatch() => c.Bool.MustNot.Should().HaveCount(1); }); - /* NEST will also do the same with `should`'s or OR's when it sees that the boolean queries in play **ONLY** consist of `should clauses`. - * This is because the boolquery does not quite follow the same boolean logic you expect from a programming language. + /* NEST will also do the same with `should`'s or `||` when it sees that the boolean queries in play **ONLY** consist of `should clauses`. + * This is because the `bool` query does not quite follow the same boolean logic you expect from a programming language. - * To summarize the latter: + * To summarize, the latter: * `term || term || term` @@ -189,12 +196,13 @@ [U] public void MixAndMatch() => *> |___term3 *> |___term4 - * This is because when a bool query has **only** should clauses atleast 1 of them has to match. When that bool query also has a must clause the should clauses start acting as a boost factor + * This is because when a `bool` query has **only** `should` clauses, at least one of them must match. + * When that `bool` query also has a `must` clause then the `should` clauses start acting as a _boost_ factor * and none of them have to match, drastically altering its meaning. - * So in the previous you could get back results that ONLY contain `term1` this is clearly not what you want in the strict boolean sense of the input. + * So in the previous you could get back results that **ONLY** contain `term1`. This is clearly not what you want in the strict boolean sense of the input. - * NEST therefor rewrites this query to + * To aid with this, NEST rewrites the previous query to *> bool *> |___must @@ -220,7 +228,7 @@ [U] public void JoinsWithShouldClauses() => lastClause.Bool.Should.Should().HaveCount(3); }); - /* Note also that you can parenthesis to force evaluation order */ + /* NOTE: You can add parentheses to force evaluation order */ /* Also note that using shoulds as boosting factors can be really powerful so if you need this always remember that you can mix and match an actual bool query with the bool dsl */ @@ -251,8 +259,12 @@ [U] public void MixAndMatchMinimumShouldMatch() => nestedBool.Bool.Should.Should().HaveCount(4); }); - /* Nest will also not combine if any metadata is set on the bool e.g boost/name nest will treat these as locked */ - + /** === Locked bool queries + * NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, + * NEST will treat these as locked + * + * Here we demonstrate that two locked `bool` queries are not combined + */ [U] public void DoNotCombineLockedBools() => Assert( q => q.Bool(b=>b.Name("leftBool").Should(mq=>mq.Query())) @@ -261,6 +273,7 @@ [U] public void DoNotCombineLockedBools() => || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, c=>AssertDoesNotJoinOntoLockedBool(c, "leftBool")); + /** neither are two `bool` queries where either the left or the right query is locked */ [U] public void DoNotCombineRightLockedBool() => Assert( q => q.Bool(b=>b.Should(mq=>mq.Query())) diff --git a/src/Tests/QueryDsl/BoolDsl/hadouken_indentation.jpg b/src/Tests/QueryDsl/BoolDsl/hadouken_indentation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..afe03b960d1203610f217e1045a22142c0acc720 GIT binary patch literal 43939 zcmb@t1yCH_@;AJ=6I=s97Wc*77I$}-;K3yXf_rdxcXtR5K^Aup!Civ{2;tr5KKItW z-(S9}x9UAxJM%l;J>6%I%=C1heO-Cofqg3{DQTjrt|Bd`Ckl~?)(?Ffnq#!`+wk1e_>Z>1EKWzzwrCNaq&N7{>JV9 zkkM3^gvv}nvDo|nz~=vf|7jO00)Vps{dM|(TimU@q3s6%q$L1=zxwoV?f>qpf79Ry zpiSU}jz#gmX&(v!0KPjYJ^tS`^9%r>EffGCTKhK*m=6HF2>}3Fr!72OJ^!`=Ac3C8 zVaDJr5E7B?(eANC@zqGVD6bjfK}3Ry(gTdgl{l0FfiZZ;bRk0kyBGsl2cI7Fmkid(1GYFC|E_=K)n1y zLP9_m32AWwX>LIw{=byKprWE;qGOW2c|*!iOF_&3e_dV&0NBVdudp+404e|sHViB_ z%%l_Nme?zEVl_07%@7beg z5k}^{FPHDJceDPKCXm|ALTue+*@mqz_#3~Y1G0F(G3;0cCzvCSuY{1G-6OBv`J?Fk z#=7|t#O;$|GxE8^_56V$<9s!ZrJOU9TJ&p?0E=11Mf^d^-6Z~{Ou&Cy0}vbAqdtCB z#p}#Gjw7$5`QZ2~LCQw0i8)ejweq+$Gl+B`Npg_4n_N4N_ep;7(ph`PDLfqTi`cXE%*kmhqQZk>*gx~C?4Wxx&Q$F?2oeI{oeRnKUCeey-+ z5BC{W1n5&NNwMA8;aO@mKF?Us=KS`|PYrHDwr_ap^s`mClh57d8xkne}`USnLs~nF_+g#&H~QPQPOGLG%hsmj*?BqudJJ}Y(e)VV0#~>Cv-SpJF~i% z?JhMLL7bFPqFcG8pixED#TzP8Lzw+SGil(Dn%eiD>Y*4ZH>yXgHFu1te*F4__`CNx z0xJATg$x$;UC(ErheMv~xY$Ai?%#r7SqpjTbWm*iR`-|JG#b?+>uZ0HML{f|nZMEvRqzhs%I zPtv_2s$3lft3?Qyga(j}l41|_hmN_l_CRi-$DW!Fd*?Lb?wUI^6oIl$w*?!gRWzv z<`rPKuKY4~?V;JJK+d37a*DP7={D^2(2_T~@lCOryJOG$rlT$XR^3m%bc-CF+`lJV zl}rBdn1CUsDjQL_%l_l@-PgbP_roRku$k#!?ZH&egSv zUyeHCv&>#eC~Z?LiMP$Z3T77Z04WAB_`?k7&4K)SChRj(9a0@^OTuaYX+K`U$Uk)9 zxpdTx*QPoxeCjk^S`9kg?^XD=bUvtXc=l=gR?vj^HjT160002Fi@1IIx*C1>(Pgfi zJmkIoAd*O1%Hy!JZn&!lL%j^vVOvFEty{wO>2^>F&1vY9YS83|$QGgN{detHH}m3@ z>$QiLpDy#RLg}ZUV-%$0a#YjAa|VtXp3=Ie;=dmD=$!^mBwMTa6)mP|d9yww)v$?( z6L|STerwg)-Z$OhdGS0$NB=MTe-%u{mFpHCCj&X0Qm0bTnM}>a;qYYJP5ai|sk!6j zKN`W#yS>D5>vDK{c(0f_*3xFY#U_)zFgBue>6TJJgQ>*Z^S3JK@y%cU%HM_j(`C=k z`NN)hT9e$4*m;dJ7p~$(wJe_o?U|o*0e{J0CR@L!70i`Y?+e=(rL{z>#dCIEA@!G=i(6ZmiqF#kvaiYtiRA#Fk^QEu~|Id`Hk&1VphMQdI z81`mV9G$vjX?*%GKgE4K98lg(Jk0+~B>)||@+(PrDh^IQt^FxgS@pUo8}NCEW_Rrw zIs92$D>iVRzIPfAl|?YnimfoJ^g2w$S?)j+`MB*M$i~&oq~vxfSwWq`lv~#&x4q!% zEn|*`qS9+&-}`Z2Fp;12<3Ei2eUJ$)k%@EIDt-KlW4o=t`Q3DZHz1$k)7H}OGT~zn z10O#!{s8D`+?F9s$tSGe#`WyU=S(R3>6$RDa!Xl^c`NMbDC^m;g;MW))9?+NtzMxZ$p@TzaIpiD*QzrFdtkT7KA&*tIxkbTIFe6LgH#?e<9?V9FC61 z=GkwJK6BouiV8hpZv2V)01#hpB$_lvH&P%g!F2bL=Xts_YrVD;FB)3ZnnukwzAE|9 zlNd+%+phWMptrIjC!iRY8v!!^4t$HZNbd#FH@#$!q?g>*)isnF)-N~}!d`Kw({U8{#eP7?Dn!pH;91h@BX$61@(#;N5~C%?uo!S8+Z z>F?a4fmdSxG7de%Y#)zFFXZHLF3-m0K4Eq#>T!2BaZ2Xy*NI9u>D#(ycHs%n?iDOv zr_WzikOzWpKN9O3ebfk7w0tNvwy|LjO0DDs_88XQc5!yk;t7A<&+(@C5A{&!LV4gZ zCeQy_20P|EK7#`;Qw@C_`9zoX@g1vzV#kY38i*`#%D8}uB}u>_s6|+Pb{DLEztbo7 z|JCwW4Y^qO0kX&4(#=ujIAyugrP$LP=2+Wp-vd102XgKoA$Fxby2802wL*g8+M#xt+K>DW%|p@}gsE|~6Znsw z`^|A#n$m8B^cXHsEk9OtAXg>t*Ep@o^>~F(?T=PmSz&cb{AlldlGo6WUC-m@it!FYVO0!Y+Pn`O4tU>n;%bK zx@&O_wQU1T0dPZ=EpK**3R6)zQ@6w#C4Xp9HcDCRCw z$?tZ8X?YEuTI#0=#IR+C#3gH6bRK~ImcI;|HS;wqva)pigW41wK z?Q-sO4z?5m-BM?^puOU(GU@z8`{K+%xmSQ=sf5uhplmf7up|34S8tZkLLIKp41+^0 zh$p@z37$BMD!2t&MRoHe)sOBTbt!hv;gm%2&%@8T7SXXJOrY=O8= z)K*?Y1qBv{qz>wDQk+UCYs>zUWz^uH?hQna0Y*M>|Q*RRn0O*kk@@=e2Is0Ouu;i8-x_y5h_UaNy@B%yJ2F4N`R$0;K znPm*QOncT3lrb%O{=~MJkO~&E(+gtUkbpQ*;mu3ey&b32gQMoDXxQL`)Z2M!)^xwf zh&^Jk5~PYvF0TRuC3zSOm_rhz)n;P>IkKEJqyeaM&4DihrD(O_C$YaOICHkGS#Q-@8Um~kO9P6k}-@B z+kv%kVS>w6HlrJM!+~TMFx6L-n)E?Z0AM9HPSqp`k7$YdUUi(2)3^EZ1})$f@KL0| zRJC-IqaRdJLBS1;gFOx`BA|g`u(uI0!yzMWsYc{fqqB%f-xt5Rv$MDne<8NCTJiB1 z!5>v(LMZPmZD#?>mo(MAxsD>=^8E>~x7HkoCOV}hgNQMvX zxGl2edl*Sa6c>1Nt5C2t-g1;BIG~wgKo|~Oy^+{K%RbN%Y^dH|!WjC7e2&>v0mltz zWL6X|)^I~t4p_yB_l6o}U7)xTA2jymV2#!~jRqzUZT)+#?&uTdLD#T+qLC-Z24^wr z{`;!;M|nYL-jd(&Tu`uNQ5pP5I%>NTn++@N_9ZdZmZEb2H5hL4dnuEk@+$RV8ufrN z*-U?I=54n8l)c`J$3Yk8D{0yfoNp&?d;;Q0Gq_HhXZd*vk#z4r;`Geko;&EB@5c`d z<}8^{!lmhz(EGNI@mRh|m+7Wqrj-$~_H>WkNW$g6`0~?nrE#MH<)H>IzA6z0mU~&% zUaAI9JKAt~ZAQM2J1`r4IGSXaJ5WE0N!(sdKWagnzOX4o^*eb=00SOH0$knJhrI(j z^M?hau3%8{8!DfaR4~cveWRq%99v;WuVVL;o~K9%xW)wH)$vaUcVv z(_^0-t9=D<6L~BkZzr?V7qI*-|{>#Y?fhi;r%0j zJ~2)!08CnkbW;QSoxc4@60v{cG!{pY@pF0wtZJcMb%{g1Xg7$9A+oE)Mw$G;-rc5P z$1Z<|#@bJXa$SvD_G8w)Flx)F7+mCn{H}a!Vxi&;36XS+#h8IW^XW_?(kW&UzZ2B# zN?{Ob!LGDCu-6{b97tS-JN&Z+!ZmK|VEBz`w23*53~qW@@j6Mwj)#SJgDzW2S<8m| z>*8YLq;><-H$NxyBpDVf?4YH*JJg`-;-nMfDSVcKxVH<8+@NqtQWggEj&HEYqxpSH z1I4n%C5zHhmKL*Ni1uc2ha+Z^%g2ZKc>(bvZ)1J~f`2Fr!AvhUPc(tU^soYGN?M)g z@2h-@VpF$QgpZ;w#pIs%r03G7ov^SILWL6V5|kTD#Ok|0Dx5EF{7< zN7K^rC8L{l|4We<6AMjo0haPY8G7|jXJ)&98V@0%0#3cz?Lnxu<|783` zgtG;nu(nOG58!w^pX9MUw=exd6iCkiO>*sKx5gu_s8TSB!FbQEca-;q&0D)5^ZWgYvNifvRr0i0K z2PIQ=BNAmF>e!A4HyTdnE3CGq-zH#^MvkPF7->;1$tW%UfE=w8MV9Z*j1wG=L!WUG zD^#%f1*^ZiecY5V7Y8>I?0z!XBzUOQ`MQ)C3>HqpLikk>0|gVtZ%8V3@clwlpt+nsh1FEMQ<1=;a(fX z)cA`TVoPS66E&M4=_xOxQx;Eo!h6yoty5ujD6QhdM;3-&4wE8&l5vr4t7TtlWvT60 zA0^3lTPv!jStT|%T7)+l)&3QGu4Qx1AT|x<=Cdj+UV+PE7;M>-!N*sCc+uMStff?= z)R!}L+26^2qL~Cg;2es%=-f`_qk0gT+h8OB`6K7GuK`7`0)XVx_8x^@s_V zh~s&?eM3Ywt_o@#wNM367%U?@lWH8s{<2V5Db@njAhWo!77NK2ohMF3>jKAPOKyop z4=?Rj6=w)+WHmzWP-qMsSaHcnT%QNcx+XhRe7Gf510ROsz4lj`$cmT>?yrP zgQoVXf4?u(@wl~mG(fhqZ*{XZr~Z|@CvT>>I5rw%E?S;&3T$AmTykmTE>@y404EBB z8#5TELP%EvWa*E=9 z_uX?A(NaNF58IEn9ZhA<$I(%J)1S0-?)#i<{jv+=K&iJ#N^|Jk!Lg}uWC!8(ZA%C4 z;!sTfhFRCZIbK$V74}?qICIrvs83*QPvHj>j^hIcWr^|T9Ms`?d!v`l*lUHkk~GQn z&EC4tmPxk8#o-fqrrnN?=SllNZAvpQ%}C_fgYZK|sGMnD0kqyVDG@L-bCLYT@gpog z-U`v)l2Yg{8in1iF$pAacoJ;EiS}bmQtO#IM5l?~ZmK@C{1tDLgwiKk zHb_7b6e68J&!GISR0c*~RaRb4novZlqOSHBnWyBwKj$W2QD0Wn{mWwp?l%^1ue;bo zb<<`ZgWEHyuT^q6cx8*b8C=syrt->@Fq%tka;7~x9IE%KS&j6yb;?#XCm`q}PSy4e z%U{(ua4a3Mt@(M8jKiDDupjs$qr;NJ^-vr~V|h099Td8ySRw4TB}}67fn%y}isuVG zb_CXXM8mx+S^mls6Ezh-mAbsp1G4jqW-FX>Y>e7Vlj~o&S;c<=#g3)0>Z61ricl-@ z>^KXxqbn(-t|&-mmFzlZ?WJmM^;xhm>{=$7RP7&Y?E?Tc(jNLY$#vKI4BV64HH3qi zr@F-XfHJAi=R)=rFP&?>PHn{vfuveB+Aa7%21fraN0T-Ko%5x|XO9;D%@5GZ^7+!; zvqv|yqPjYW=53f*rTSg=0ecg#(f%0B!C~_R8r!^j@8ptQ$W^jpsc>$_6x7&Yl`^5i z3D3zh3z_)YA-)-O@3`aEJ!n^IJ@8biIM6w&R?1{#x!z<=$fCm%g}>Q$w$ch5p70&s z+mQbz?p4IGY3WdXUXgHRLmYjyBze z+sItuv+t4_UjZcJ&4SjZL%A6dpsr`r`(=#fH);$+d*#mq^&Yj6^ZlzDJCM1?wlF{2 zbb5H~D*`k<_&*4?xn2!Q40E5^>y11cqHIp~i7N_|T;6W7G-X(@DIC@IeE$$sT_*De znO1J0QAnvmPQWe6>}^ZY{P44>R_n%}rweSEx*++O$16}}@8F`C4mziJ;MIFA#=e+e z)=fXEiTvS2yoXAtQYXJ(#=Kb6Czv)z4B}D~r>>@kpeGoxHgLh@7OO){fz?XAEJ}@b zjno7`ymV!)g7>@7A*SZD1KM)^yF^Q(ePlt5Jdn9^7XeGfV&Y_m6iMLdH>)?q2~tiS zt8TrGyg0N2y-|7zVaGuyqR1&;;71#C)*S*o3V|C(bZ~MwjsX)hNa|~}D=HXVljE3N z(h*8LT~2T)>3DRNvnxUS8&hWfx?=aFH)hf~UMDBq=3@3}a{#-}ToqF$U9n~XOng)7 zuBX1OAG#r>)`p`v;Nl$Gwej&Wz`~Y0T_Ei@xebB&(rj~&vGBJT0pVg-c-1Hh{hQNC z$3GedRs4Y{H>U+>MX81c`BbZ1JiFRTC7MHdK|-NUqQr+8pMQ@)16j1#&@B%zaPY9O zaR16O!(dawV&PD*i>bnKP>JKJnf@KXf~KTJVO{}J@ZDhA<)wa8{RErzt%?xba7s{e zp|jJIjX0l1GCy9)njF33U9_0{(iHToS4$Q)mf#U#qSC*x% zkpQk33di~2C(Mr$ACBW4`EKynY{lwlM&);qkW0I?q1n=G9@|#i`RvS|ryeCWFq!ug(oXC_aB$p?8ra33syv8k)LidlHO{jChQU9P&|J zWCFIOKt9u*SmYmHL?doX?dApYlUBJjHF*;Y_Z;!ctL*%e+q(5UORTJ{{4}hBQZVX{ zlrRc7_*_k9RnyZ~!H}q^u;1P^Eer~Yk$)h(UYG`WA^VTjKB; z33k>}@(^A>42D1|lxElW)CqdyvjbSl_?IZJ06OS2puvX5GvN>b&}s0m@F#Q=0v6>z zrU4ZPoHMSt+CRdW(7g$wFfaaHi#CCJKJ*e;)vaHdD2>p%s%yL7JLq}Ehp@!i5e5y5 zGORw9YkPXeajf3yRSB7lFpTA=8$DHWCul3FA!u13h#HiK13MD!=-3}Xd_*G+t5=#* zv`IiPa{}6_2LgQ^)$qegB115TVu%?t|{l%|+=_b#XH6?GU_Xrfi`j1BDcpeSkKlCoBsSan_aTb8 z!kCJ{5RvhaOZ|)Is%x;Ib68U*T8P%Sz)6nn=A~bxzh@j(v4fFuKB-~G&{yF) zXJNk8J!#>Z0$`#nTGg_Mam5=RWsmfm*p@CoMv8B)+YxcZ4othB1sj#l%?3#HB)u8q zYgLFnWSD@3MuPAOk~akh%|&DdSP60WTtk(p_$lbIu(%>orionx4=R9hY{7~|iWpR{ zfI5c4C6r<+>_#8sJvBVPfG!T~2zl1Gs-hmENLfL|0f z)@qexEwvgXBr@rtB_bp$l`drm`8-ARNL(EWfsGE$iPV1}KqLcy8#H4p=P9aD?}QBX zo8yyA7+zA^QDKcPgQAQ)E!wJ^Rg`iA2YFj(!ADjcw?=IB=>Dxly39Xxx0+`xAZTat z>T_!-?N0yT1r5c7Y?mo1O)%xpfm3K?-OQ9EgcdaECb5tc;#(>8iq?7vk>MH-8>#Ct zW^sUy_R3l1o)~id=PaCG zOEvhBqT(q&&B9Cq&*_P}OS+bWb2?}hMB8ul@4HR5o!yc-PfD+6`KRJ}5<^+@sPa{6 zv3TRS&f+rDKEh_D=i0l{Wm4AS9u)p5Cz!ZnXmaJ%j~DL$qscuJa4C<}B}KB`RRT(P zCZ-Qq9TH3geJ6bd%(P5m$x0?R4^27eBwyk^mb1oP(9c2pvU`L}>P5ps#E$hN#9#cu zDcfY=4Jb>oUFn#~TRLf)<{e?BMT*u%AZDz56R~ z(Ss_o?lr&np>#-PRk#C!E3q`STq`hfq66dc?oIvroDNqgEU8Y~4RQxya0Jm_X6iHN z(=688_RkhgtymhmAxjHx1`5}Rr)o80j;T2;ScoVCPURRv6nGC`l`>K@6Kv5DE4%cR z5NbGdxO>Emn76r;<_7lNeUsjJ4r)(ozKB zb@%sJdATx1s=l4OP_GiAu=W&7YsF+sUdrwu_zqF5=q-dj(4u-jM%Zd*yk5OY8qI|7 z3LDwk6a+NJ@<|uZ$|_Wb#WaI=LsmZGbn_npuZ--j5FNClU!&-M+-nMv32*AGryN&w zPOG2%7QZ08icL;hqo2D*PBpNNWz#{bKUO%*%@`1TFdBeNmoD+!!Xtr~cC0-x%gSE1 z0fgGBijSrYv83bczadm3F93g87=J&el(1=QD?^BWdqxuy;3N@3O8r8wAA9L-!V`n1 zf4IPNlqF{q;EL;^FB3*aDLnF(W>~5g+dg-!vH*t5S-+;EhLCiSfnl0&e^QkI1bXI-xUM53);Bc|P)g_U0^(7w&O#Q?H@JYqoJ6UHI4 zcOl^!gnvoOp5^$!tx3TkVmp}FkTPVZK_;U~gv}AEMTfg0w#q-_cqcIg`JlNyW+-Di zALLW$T7SIarpq}d#j4^!PPTaN0V>o2(a5m}X3c#Lwi4VL^p!tQ6rs9 zu|`QjYl6a#okzvKdvBF1J}?&xn=|=po@QfS zA0w!$nChf4n`=UV*@prpw`=CpwiHnL2;jtP%<7tMC&Z+AwoBc}$Y{kk0SQ9W)SC28 zhH#{m6xoAocpb)sLlaCLA8pmQ2?GM@7!#c;a7E;eLRkhbE_D*~N&g(R;{paMsjez| z%=jCFv2Ci0GvXJv&z}HgWaPoKc?Ys z!K4CCu*t2@e5yti6>PI!T;49Di3y6$ z6&H!%iiSrw!$nyWi$~V!tYnRhDev5lI4N1x)m6nM6TwKj<8>7r1D2s<}_6D;Yyn3#L5E0aJ6R4r!5R z^@%RTyUw>V5C>V`@xjDt;4$9FUaALyjl{8huYBIr<|sgrSW9YP=TjWbUk(5RfmmOB z?(sD}ubONq`xkbUO&5~z#H-M4e_Fr!kEvEPQL07^$*5LfefK*FRw?6m^>jKA-K(-@q=hFwY0z`@EHy z3ThgIJ=FYEAf7H&Jn@2C*nhvqw3wY1lwnfRh_w;y3IexI^DpY&!}>^_W3)H zK1SWyjxV=~robzJrfkHn!^$?JL;uIMket1l@FE(RNZpW3FyL#$rMKfr?!2{lw3(ef zA*`e|U|@cS?st9*8VU!)Li@Z!X=hs?d-Iy1BIly;+5Ak`;hgfcA08rLQd)k$9Qbec3^tTW|>df}aO(Ha+I& zk8cm(-8LJ(y;eeUc>#Ca<9FYiJA-Rl#1Cg< ztmINK{%d0O8g$DmZ(=EXn?QbkiI~UvT#_#HYta=5Tb$>?8ZUl{qj>kQQtNTOJH9d* z>K=M0!S07j;R}_c4dTT}uHutEo~dXkFY&&L&3^z%0R^RD{x8ryx-yFd9S?u1Ad~}X zF|ku9le>xYI}05k+f~G|Kx~Jf$v-UFr&h!ZJJ(@`;#U0%Is-Kc(J|We>)$#YB{)SM znDE4s)`-wy83VIeh`zrcvx`h^ij z^J@2;0^8&Cc(&Dnbwwlo_<5q!hcZQ@k)!r0wGywm29XP2iX%LjsH&s@GWt_L-&M-ZSUf(AFyNNWK5vrArdSluJ5$f%EEUPt{}T zC|qU5lSb83fW~I?=e?fAwiT{1hP7JwNOnS8v$gcNF18?xMA}MS&rmDvHn=N%B}j0H zgs)1cDHWA!CCpwWMmC*at`(oErk^SHe%!*BMo z+r%pG7PM{x(L8W!Pg!wAtdImhJX`8sZr>>gu$S5qJUBX$5Uycm&juiy1!gNR{3D?K?!aE5{D%ASY)_0kaQ(EmJcNWM(5FNC* zQH&|tWtk!dq7t~#s3ZeJ)!bn#vi>kk@1u3kUu74bO+oTavr*I(92eD} zepUNWYS=sKxz!f??FsnHXJ%f{Tk1_}Y%X!C|IsVnh7`I+hCKXfVvMKV(U3aEcV0Y7 zKbs}L*P;G4q9YQygPz`^piF9dWk~D$7J!j6yZ`i_9_B-4E$zlt3x$+!Cr_ZgJls>q zeWn=eDrx{`bpAG0w7xiy+DR6+|=QF#cE@*!3a|#`MRtT5+Zhr^lmUY1qWl{LIM>+zN{RpzPx&*QUJ5;<`Ul+p9-q ztpu^Txq7+sg4~ou9xNfU<4q4GvHcRM4>3?{nPcdH91H1)1X^n8;4;~#x zMx2NQN-CIv-r|-0ggyObIW>~cD&uZ!p35LpS1@$XDjPZsa(i}EoZEJ{ZLVoH*k~80m z@$AXN#cRR%_cs&kHHa^ot9H?2K2g|#gUv(vlUX_Wr0;WOJ3n>OvwnB(G66%g+l*L_ za;07F%4vF=xH*~-g!e~P6$A@xv*Mtt3hx^C3rhb86EZAL)5;3rnn-H*rJLV?dD~qt z=!=}VA!h2AG+ZrT2(0O*t3)=vYP7P<55#OsMW~a$;Gafpny&w0folm!F>p;IUonut zXxA8|nKEFd>r_z!-o%*?nI}HumHwslr*@D>o8G`faTA+QTa0XxKC)d~%t_Tj<(GP~ zL#Y<0J9rz{mpPw?AlTjT84yS$8q6|>&-anK{HJU9doH6=z=whSE<;)k0}S8htZsDd0K_!wE+3@Wt6GUAKr1#4y~`Xp^sT*i~K zxTdxNJimQ&M&(&u(%uz{7$vvvdpTbFZsOPOCY=j!65U&?W8G1o69GTfACxYP}I zz0oAzAQoBk>VILOisamj;hv1(JqZOO;N@{`!%I-5hX8Tu$!#xMLKCu9%rJ31V9GMv zL%H73Y;%smO%lNT1ZVY2222CtNeke@UIAPVs@OD$b00!}ui}t8hodM_T$O>|V7>z4 z+nr7kJo>#gbII*;I262GON!PLqr*c#%RZG8J=d=$GdT>rx%j5kzZV@0pVGII%t)kT z)0r+)*ML_Zs%hk{6Kc_DenK^lYO4i6L2(O~(JCdm?<8x` zllh7}NswYL5m@eT9~a@nw)diQ^ZA8sFYl284NZpMWD=P>Ghl4xUK3wwOEISa8aX9uF53@u(NKDyf9v>E7gRVNWq;@c7`HD)W1D8qVTb@Q%9h*C`0AWr2^yD2DtL^SKbubmxz^ba)J8tSI zjD>`~VDr%kP^3FR;QoEEe?$PXGOM%bw)`}c8<>k&1;??|=>d-8SK5O=Un4h;iWa?K ze25IUs7H$B$3ju{orIFH?_*~D(2$4j+;%W>?s?+p5`r&0bFS2kBmgpegV1feVgQV0 z>!9~rb ztvY){VEndOubD+A$@(Ai{&yle58Ju9Q7=537l>ByxbV- z+ZmFGgOK(>d3$-P!QYG}X$C46)duoGp&b5pO7v(FZidpToP?6(pJwRjM+h_uSvrwe zjsiG%a?5vLs5L2F>BwRUz9pou?=|rn;Ra@#>2WXeeAv^F$}cl?ekzL0zESj0itJbw zi@VSByn=Xp&GJxPz(RvETnW)}?co+TfzWil&RXuj5&eSk;G)xc1JxX^)C1 zM-lroH{L@u}QXN~+@?2DOGKro~0y`ObQ0NRMWJxk@4@*DF9BZ}Cg&D`18>2Km4NO@w>B0+$( z1}?vDdlDa!=j};qRV9^Ve%ePmuj2DGc}FVEtv_Sv+oOK8ODijEDjQy-$pCEL-%33Zb!Zsbf8Mtp=#2aW|w4KNW=$5%D_Jxi>@uW<5<9O=G}S)c_hhPQQ9EB4I zFgu5s%IQ0LN@{_PunG%uWl=*rX}>+DRNjz&!@i<+q)5N{Wm^+qphGyQRB5#mNY9ms z@}+@Ee~N5&FZYqFiRU1YTK(q*J~e{i5W`qBywZ8I5fYEni4&p6$F9`kaY+maYcHll zDe})o>m+G#q9$smfrxy&pXhord7sk>c$Fi>yIvz5wDB8jVCPzCh{$Mvu&qZUk9B7> ziw@*LIV&XB!haAi6P<~H3!ocwc{55w5G1!&m^sot$2MSwl(-|Kd7SQVz(e0ywp9u9 z#eRgBFZh}Eq&@zMoy^MoB5eS@Vvp;m7*_^n<#Ft47F}nd-P0%3;Y5bdmsc}BeAw?^ zte{C7CM;-@1{RvlfJ0pc3V^dgFoVVs%Bxb(SFSHP@ z9DOuhk816%@=2HAfF+yJm{8tFCN`oyk9P?w9Ut^Otm2SERQ zI_niBj~c7BKn~H;x}wW)7&o+jjLy-+|7>jSZvLa&&D+pK453f$ZESL&H(mq@c2!Um zdP?ln>5;@h(Aww*#yW-i)Ikh;=RnRl`nUpGfIYv4%w1JxIP7nKG}nAw1>09ZZ&+PF z?a}P+)%g}`@=UL2HspdkCiYkMuq)N3nEnf8iNm4<;%7ZQ#2@WAgK_CMO#pmfOr-WA zn*fl%Ty(C-Xzzl2{|G(XyPHww+i7P<>NdOP>tXZac|-{((y91>D;v zNYKLYVp&<2WPew*5*>8Jq^6~WVP_J?Wc&r&sHRfKz8w{Ic#+B<1N`Igxz1Z4%4E!h zBhxS?bp<=bkW)VEXA5t*9dBo{%b<$`zM@!3B%7jWNB}P7&>Q%|TZudER_K4!taA~A zuTmL2>y4McVLP&fioHj|;ugcA>4WLl`TV_QqIaUb^|>-ctTNQ+F{QqQyBi3P@1e|P zY=+z6!r{6UXc-2(q0r&4?4SbKPq-sgLoadj`W!?rW>|8e%_I3ce%+UB{|HTiEfEc% zPCF_KpclAP#TVm`(*MJN4CC%~k7aAckR^tNIkhj*2__L{?reN|1~fNL<~B2KzWg~? zpLKTvv@R{Od~Tzc%YZS7|64e4*Hme|WY@v{R&n?2WJ zF$-a?JE=1n%m)v(417z8<9P40@=iYJD~7H;yQHUi>S_D>%s0t54u0GkMAw{BeO18- zAc#Y|aLEuP`VNa}Z=6WF-#k}~uaCKN>YCfK;B#9SHu~Iwz#zkROhe5c&qY~VhgaP7 z=YVqip%xp3FUCcQS7g)Z95$F6;#3Q)y7}tCsU~wgkzjC>zM7&^!xc7?-2q639_6s3 zj(lVdjAqDzrqM4#!-CL~r>M(RnZhjJDxR9U>F`@*wA^Oy3#3211-zz@FwR-oI?fyl z2xw7Mc*>7`x_f$B?)r6Gp(;jQe>&IgRJqonVI17f?bttdjiryhXQpMK9eg2?@kXn- zw`6>MJ=kiBiV7^Chw}AT2Y3A zbTLd^Xc5?cecRY$ToFv6#@DrDEz$E+-Nz_nO`~rgm=uD@CvrVEu;B7|zni`$IkVQa zCX+{n$DYC1P%Tv@HY}}nZnHXzh|mP@>=4)EJ3^|YNS1kt`@WC1qp)rqFjz=g@JCRv z@Mlu1)_3{WXRC{qHsC=FYD1bic$*JUq64KJ!kRl#B8w}}?~s|28%lh3;H2$}EZPxg zCoPl1Y;gexdI-1!zsjYoOI&NsS%xC6x;{brDzwV^8<8wrCnInd03TWnbwL_YDO_E) zWN$Z6yo-%;R|3hk!r8c4ef8?cD2xCiiP5wzwN8j&Zj^6Bn^qKiY!@EFs~SWj8BTA} zBvsN2(%@kw8ZHcv3T$_D(I=ypT#n%3`!}$tJe5<>%9Hp?)eC}pJXl_qtZHj8+pq%W zIp~*XUIDPkJ}8p)em^i^&W}WNKMkZeywmE4iwGr!8N);H&FKy`|4g z%|54h@3k5;+B3N*L~SB_apZLkuQj5-DvHB+H&|9Zrp=rKtElTUvjy-yfc;L&8X|QG z)lo`#9rWZZD(j}oIyUU(cSlxFcpm;UISg&~>S>mi95`dlznG!4ab|T~H1D1sMnhvv zhHKhaQQf8YJWT#bo z<01v2J;bt^;Z6$zl}ae9#YG1xxoZIH2paMR=DVj)0-X%S*1VFfm6z3>cmWVM`so_f zuDe$;L=a%_maJzM6eG>7*e;57?3WRm7$82LKg7QaZZTIPPKf2X+(C?1?3Xd>=lrc; z#qH`i)fZJ*sF)LXHX}!XxiL-sJc-6GiVTE14Y?tz`bK0h@q#B7_zkSGb=Vx{>JwY> zx>hW-B7XQ8p@wCnU}M~l7RqnLmx7ndW%MGXSVe8v2sHiZ9Fb7L{sn2J0lrS7 zzJ=vx2>IjpoWH{M8pN?k^)`k2O2g`S1q=u4ZIrr;PC|c;R*&+07iQ^n1Bb z^R{qCQOcz9`@{?EXlZN|jV6`W&dsh6bm&Np122uaBfuzA^k%0*cSgqb5-dfX@c#EpPpv~6zlHMnl>G;=E(D__!EO_y+l52ZAH;-k&>Zp|GP zG>Lqw`X0lg04!a~(LI@QgWn|Ru)eD&sKr_y7K$`?i!LUi8MDrLa2gN=02tjVbzcRZ zWE9XqDBoWIGpaN&VnLUP90%y}M3d(nYjkdr532LP6iq7eI}@VmhV+TXlI?tpT&1~e z23J0JPMb1kVyIO@rvhO!AgUSfP(_MNAi5~#uPeE`BVvkli2(Z$Db1}4lLuh=A0e-j zy%tc2rS5q$lsi^_6lk)TTEe8J-P0=5^Dqdw2c*}6An0=x)2U)S{ zAFgOpD@{rrWk&Mp0L@D>MSR8OEHb`-pvCMEYYaz1=NU1K*6f7AtsC2Qg8lS_pvWPLxn<9cb&Lh|| z@T@vA_G`h@*VHz4@7{&Ym%eGZD0Q&0{30oSGpj8ce%QvK`sD>QxqaLC;8)=*O^JixV;({f2 zS<_e1N*_8~!$$-}$6R~#behK^2Ye@#iNF}KzU`8OaYxg{v7{xGAVz$1aA!8G2JO@I z2dqVfdQGk748s=nxO-$cA86rKO~)}XPhjsee}#Yw?}nRvYHHy0&?xj?Oaj2R(Qen*jrMpdt58GRO78)~d7Zf} zwx|{c!+g1M&JyWfq>AcKYeTUmD#=q&(6GC4;b^jcz#S~RZWO|jRiImRS)b0jai0C7 z01#^p(&aQ0lQkslA3g2|m9JP&i6rE^34+n$$S5t8M;G*0fITv226XB479qof)Q)Ie zg$9O($1nrEpF+wsQT0Aa5eB1Sx1l+xKpwr@s&R`uBKr;qTiMi+6C@(>E(BC~LVTfl z_oL7h9#5)(QMH!e9uXj#O6Du<_<0VdXgU|UA=@7!7B9I)s)-nLxbLu1Sca3{(J2i< z)G$KwkpN~j_*TFMw-+}Jg|_%c8DV~6R+OU?4Kz-~fS%u-b8M!$c7`N# z84%R+#9-C(J_#Ri-Xk{E(H!z?(@8RzQll2fyJ(ZL z#$1q}8WkxOAa01-<`yZmDcP8O2#(Y(LBfE>lLv2(oq{a|!|!zx8bP{gCutHG zPlo{7!PjLXEA#c&#VWaCkXfoIqQkg_?HZC9;-t&50=1)ln({G_(Pbe_r7JX$%0P2T zzwDNQ2*u^{$7LOyc#zszw-wG!9b4_}wUvFNg0*}j-%`IY9?7u>uLG!n`#3Z5_32X9 zt*#f+=yVGZif}C|>+}Y$Q{ukdgJ*XFB&?@0ze?v)_R;ud-rDTi>LFGIi1V>2xSg~@ zd^4Me+bJa96Wl&gw3Oh3^5+^l!dkRAsU4kh8pc9zr}+^)9mb7-qZb7s@lK*Q97GXW z)yklP`H4@yhAAFST)UE)*P()&X}f#b?|JmCg2f^-Q8%yy2c)yWYdzPZ($H&!I+A9N zK_;-m$#Ug9#cM}rVxI&JYR>CBv?M4QC+8~l1%oOl>}dD&J(Tu!U)(KPTK)MJ3F57a zzko>jOlSH=L8-c)1_u3|s!mJV68mbAb=567 zqOP3C`QI^r0Xy^#{!+J@nE%onMVYRTbW<7FNTt6?|GC8ODtWr^z?l(N@0e!_wo255 z&#(lZ8$qR*)-9F*yWyeV`*Zl&&o3e!!4m1>FF;9@_P3){bN9*UDzy-;7?UbN>uHD> z^%_FJ=PiS-+c&6Bv2gG*5o+@M^=lCe9ePqw{+~Qrp?jlP&4b33+^_LMG+z*AzsBo3 z(J5Sm0G2Vj6g9mwODxZ%P2IH^5|&jyi3dt$K7C+>TG@k%e*t$~l~5;tKr}(C>$%e( zEEg$H#;rpM0n z^1!YR<{-6a^N2aJKC2yQ)=0#}u*4skhCMQ{uDQb?l?iETI0=|Oi>@E`1CCyWGgTfe-}rx+`t^z57Vart1Xcsan3(i{OV1U zuAoPd{)ZHyT5U;ha2HM&D}I^ew`DaJ;Uw|nYkI?)^9LD#BT#q4iA?IS&@uI~>tJep zK>LJ{7ywJd6BJcR^wU9{A96K(aWC1LEnnq$!j6Rk-!n6I0fL3mNF$e(_*ma20T7sz;j~pF(|fPTW4wC@aU#hCMx6tt zq$zxZ_CnG1hdPoS+Ow4g+qjjaJ-4wV!!P&H^%9U)$dBAb5R>#qPyt%ni0_C& zSJ|R?wFIy8?vfkZ|EdX9N9ai`-45)Gqtu2Od%o~Y<*A&A@??@nbIKw|L=?;#nplxV zPlcSlw_KPgDBe`Z2?f86uxrKaE>MmJrKiE$Mr!Nee+{~^1ZNt!z)JT)1-Lo)qOmU6 zqr>lHxJDswFQ4}9=w9Ks;zxPX`1y!&S0y<2G3YbHGF1txr3byR44-XO;S-OZcqLKRGV!IpCe$w4N0HFB0^;-#9_WkHUJ3C!P>2z3EPNS7h>4kcCY)F0K#G& zX82nZuVk`r!6SC*_;AK$9LV92UNq%uE^N`WoKk4HIVEItz|p=Tlk&(DDn^;u5{lt5 zSs2;m@AFm&$dtmT2J}pl1Oi8))CTKJN@}TH-8y8vs{z$t{J_C)Hk-NfJ9L%}1}|ED zYlu9iu-=0YeX<55%A0n-e}<{_`bCWyP0BkyN2|&gR~`(u$yqXOtoqHHH)y)=t7JGm zX#X)*m$n(Dbbl%!&u>v;qWuE{UToofDahs#17#*Y7(oQlx8F{hpO)6xRaIqqN+H}6jL3gq#C*uX6u4eki^=e5R0}wF-4rcCS37ofMo}F zuri&aC`_GRD<-n?Ih-NiWGqc*TPAG|R@-U2YCdtYt9pWK!f&6 zsvc&BR}eSpPhJ@1&`id*rD9k2sUf}4coYogM%ITo?>1^B-w8izN8l8J$X>sfo1`Q} zTVh|6M8*1gw<;h{!qg#(EwfBsq?xB%^;7fQ zV0MvJh61Ej6C`m@zN0|pl}BA6?P(0TWe<2cO!rhJ)xUso`--+LnS_S({JJ`v30=C{RNbh&Qj-#tEGx~H<4EftF>_rHIjsAR(5i>N zcN;J|3ZtcMoBsuM{4*hy|VQ~ZG z^@>rA%BOU~j8wY-7Z*6^3uHuDT_HJOyG3=|>3G01Z(3TjR)dOx2qw;3F(e0+K)erU z*)}gQ@}X#%CoRGaojyL|LPaNCNFvUaaVCNkKl-lCx)WjZ-pRK!3L`W= z{?{t6lL^aLy8hdy2YK+Sb6ggWB?|gEUsP0uP?#M%2Nw zQdLC!z@~&@xk0@xM_V0WsVha7#A0w7G4gf9LgT6i+xDNgq&FK}0skep@-e>8c&t_? zG*!mi)z=6Kh`G|x>OR-qoo3GX)*DWC$GC)1Cy~?I_05wNESKZM|HuL|1W&{H4_g4F z+M?5*%s~pv5SwMcSE?2Th^gd(o{l&$v5UGR7)hjl6AZ2-2Y2(mmeS#^_!}hSWQ4Wc zihPj_*_c$06#RF7)gHr&{FDsGtjNwte4q?Z{7|FjOkONOd6i0e8oC~HYCb;Z6kuyv z6x8ol70r^vP{|#PzTW>+u^gFt6IPaLykax|Jq2H+P08%f;AZOr?UHlm5U4f~>`Phl ztSyIcYKf8p67sT~%MI#=y>T_s{rUvplq=%{;wzanyOE4rcU_$oR_GayKAgt)ZPF0m z8ItOPD4#w{%YxTbY=pUoHV~L6F*^^lxU#vjpIdDp|?n zJJBphITJ3BmZ|Ib?|hMCW1|$qb&_g}MMju-mF$G!eD|$@GbIeaO@E`HHnci<|3+R- zVQMCS&x6oVXL3bFA=p*yLt1q|lwZadEIl<>p z7caod(=lRCHAWU zI3f}(^jl?7vC5mMb!Dn_mF?ksC+?58WPkL9heC4X<>SKqqRZ#JVOhOOwVOoydftgTplvu_59z%2xz=qNX5fHhl6CaRdtH(19f)lBv9)+Vp{< za*zGJe(j+V$1={+2m!Xfttaft=<%Bml6qutaK8FgNC~_Jn!LJS3@b^xtZ~JKb6F~( ztvf0c@g4a--z(tkb-$2t%1q0Ew`U)73*~=n#tbqYx78ELr{94W9bnoNPi^!Sb>yKL zF;~Wn1cCMI;s28PjR$eYDj{Dhel5VoIJOt7Yzyb5m5EVnMx-Ug9W>yM483}Mgrx@7 z;xohv;FclbgdC|z0N~+oQpf}$Q68s~$rvBl;)CkTu0&OQvSg)AFqufE;pj>6~#QnzMc6D?Xb2pP|B9Ax4gB_LpbWHT}FYdT9x%g>FiKIys4 zfFmyuigHj0HfGOvRBsp|5lp3X1c)$55 zx}p-sIEPbPs!CE>wT>f(BRFJnAcR%fCu1#TxR89&mix!TBv3;?iOjBxuI(=%RB-R> z^Sn_?$7rd+uf~s5|DS(~ODpXnJu7RKzcBMRbEjH2J39OB!N@V3`Wu4=v5_4_PmP%2N}MO(%-AP<4c!oNx|=;x?iu8gHcFm?62^ ztgGGbqGaE}mu*m^(YLv2w1g@K7!Fl3t$(9oj%%JUw=|a>lVo!Hdxqic#F7aq(^G(@ zSmF(#Rn8Z!Ky!2E?kghC-EVozUV-!p7TUF?fuk8hdi4_V?(3H3Fhz}FNo{6nU9nJY z6t~RYx1z$jgOmA{cHSw(2eVQFGa+Z2G%rfOZc&hU0fpdH_*7B+6_#nFc zt@ilwOm1s(D2-4p1{P=jjn^524y6Wzx|JH*MWFU%uZ-tqN1!;Qzzih?VJ=~^0UD9z z8`s_0>_)AOzzB2{NZkO*-(^dkWJ!Wm|F$JbCl!?$9iuSDGcM2;)B;YV$n^XpZ!hw7l`E_;b;n2%$}qsfy=&I6UQk$-_;d|>19_{t>p;cFw6MV1U<=^SX5|)< za^ieTU4`uyI*n0X{XT413Ey;m^n%_}Jp~ev4^NNm!aZA5DqLF^v8?)R(65?NxQ^x?jF|O6xN>JV1-+vUvh>o`D-8-^*0& zpd{@p9NUc}W@_k6Ery$`=08FiBLvSV>(?1OK&^wQ7qOb^c@3v_+@tx~B4P~giP&=q z?uNTlXb7idzczF`pLvdwZzE}2*KAVs`1_YOfW;lcbGG{B5k8zSO3U`Dsqg zDAcrX=gx85QHf}VoF+AzKe6p{gZ89@oYjzJOYCPQBhwarL*}##(=gSJAMsFUsDr@l z4byvRd{l~cONzTbv6Nb^07d0|hS3n~xAQzcsTz$b=z^4&JNj;nifTlAZ3r<<_%jCq zb+6 zopd+r;$yOsKh&`&<=KdmN;6QkQjE}ek~n3Pkrg&!}pI1P<>q?t^M5X9p8Djz-~hVT6%aHOPadF?Sh{vgGO1G!_6V*#}dN}(u1%NjAllQATH2*%fxaHeo=WJZG)27#N4y%dR; zKNQ=be3=8v`fWe6c1*e$(N_D%Z4}Y=_N`RLTub8%cj!x(tLU5zVuTJkQ-MMic2maH zDyM1ukjV_IBYBqGK^WLySzfre`h}LVGU7QJXxC}9s~>-SP$E=BK_Ra*DNYdd2J$$y zytq7D-4fd_BMqv-AL%qMQ{XSg(?gZObV1RDGfM|_*I5n@&6yTDG?86G8YeKiP+bLu z{o+omASR$FcFG>4Id2a1oh&mYUc#Rwmm#zM_9j|GTV;oxWhf8Iow9|!Ue|C6B2XjU z_z><>1)KN_u(wQT=jM8qv>Gm{y%kv@h)R|nBu$BJkd+gUYF zF(T92a@lR}(s z&SMQ=WE}z$gVlcdkk#ueO^Uc)N9Tcp+EvshhnN<8xLvStj%#hbU5Otg`oyOH?~?$K zA7BAdG1!B%d=LL!8~*Qy{-?@4LKjJg_0!k?k0kCw4ECpsh5xDYf4dV2VXLO?FLd*L z*!u76fc4f}KF1A6!EQYvaGl6`uIPG>68?wq-KhJQu8SFmwz?s$Pdbypn^FDfm6-hh z^m-SBX&HR6k|I?3oK;CS2yWVMv(ZT<}FZ%P7#!-0NB|Mvn zuizH{aVh^HJj18hL0oq`pOO>^qG|V=3(j(0+x#=i5&+HL z=$WsJpSr&)@n0n0KRX$86ME*2KT_=OF2x9VJ)UIw9!5VE`5q!tUiF^-)!7iy?rvN7 z$Lzx_|NVb;_#URqQThE{{`Ho>4oDb(v7Tt<@u;n;vs&DI=JPMbvCcS}zNdfWZ7V*1 zJT*fi-{^W5_XPxMtK5HljE*;ydgl87t8d(Qe;eaPDwJ4I`;YR!-Ati1`18fb^F2)P z0lJ?^+~wth{0gbw|7HEZTIEQiJ?GWq!&ui&duS4m3)x3D7?W+z`~MQ)b9=aQ|BQit z6C4$h@dRmPJhPF%@1s}`V$%M7q5oxw>kg~5^e+IA43UP&eHXE4jK+ZfKb`#B7*m2+ z18?@@#JB+8Al-is{ab+QHh(6_ZblgG>;G%?Q--ZN^mBmdvge<(!$MTGoWdHF9UnSWSB{;9h} z{w%yC7GhF#`flhL_zx+@zldazyEmT&KKD0r{d`T~8HxnURK^Bg?tThZ(77-^?e?cj zoqpy&vN0uVx&PqWjW0uwa{oexE#=g&eIRJNK85;|gm0E=A@FUwDbBWGlI}Zi!x&oc z;v{!)x)8;$Ty;qBMIz-73X&p$2G^xf6T5?zfSG(KmFwm?-Hp)N$dh&?W{RHboh8p! z##(6Ic0-=n=nRg1XEmmCDdI)< zYEf?3P62OlI+}&VZFJfJ1Dpi5c(ce3e8wu7Tn?VPYw*CkNx zrm*XQtQJYkjhy&QEYEY;-G1M-%~d43?5%wvKQY-18qwj%#aIdL4=u86`RLqxk-eC` zi(BE%Z+7t+4C%9eoImV_L{-vX$m&<7Z<(NwjuByWz~HCb&$o6G>PC1-w&ChrZ~cyS zM@VdZVj^MvA+?U4MX&I(XEn!TvB}cX!Nb!HHL?U0z3WJp;aZT)L9zRedr9~{gZM2r z?StW2o(B&USIJ#E*>$hqJsWvC{gK}AAn6^L4)D0IJ)N8c?;P8h<0X|wvp%o{_V7E> zB>aDK4-IW3x)ICnS)nN zG2@x+(TVZU`_O+UP4KCPVi|dXJ8kz$qZb^zlzJxl<>UhzU+m4lH;GLA{zQAxHxG%$ zGQj5ZuK!NE0M6ckWj4HsRmK#KMR^#*O}rbJBZH6DA5wBgGD?9O@`Eb}{X#v>I>+xc(tp^pza<+7SE&^%*Bf z|HU}3wdj1j!ebwl((u#is}ch*qB5lF;ZT)Bw68-G=z|aTznY0J;xx;nG_eq z&%<2!ti%}eT8FlUkx!Cp%XGEy3HAsUyA7qwf8YqIlS5G^Y3Tu3rGcDdd%;}$TU5(2 zc5A{;L_LZvYeANk#999A&Dau?WbzHLu+sOU^7M%t<63OwavvD64Gp0~BhWDj3}HJ` zc2h9*`hNipW=*E|)Y_sJBBdmShZ_vcZbtO6z87sFXU~Lta8gnuNm$eRn)$)?+c7^o zgV}0!$I7nyHdyB~E)^O=z435i>iuE%pk+d`oREO3oQ)Lk7-2kugWyT{!r$kWwqs^} zFv7eD(lH25-3$3~3O<+y2;_07q#{VAq{>St>m5jga?)=A0jhwKbsya;f zE4V)Hvny8{&0edRnJ20!mJH^sEa@UkG1!qZ=bg^OMxi7SI0 z%Ez&kQM4tLE#Eif%QZ|p%slZtDIv2KP;;VbK1(HQN#!(OlfX=75lZ8}1pjf$=W9?l zG1d~C>yFIixzr6QUH(nS=a|iy7)vSk#yl7sOBqqk7ltWtF5yObWoF9xz3Dgk25Aus z32~zKJIosP0xQ&^S^=SWKwZo|D*tzfJ>`^?SiN_Qln%tP?$0Mc-+$vA{(ZXz zf`LH)aJKK&H?!Y&^I<8hzh%64Z+AovlZC%mh5%C zOOaNG{va9|WWQg?5v4xhdr$%$rbpt&iTFG`(k*&P7A_g{)kG--8HvhE9-5(FU?W{N)tLDk_VW5Lh(gZ>e1hs0Mvbt?{cjDsST{;IEh(FLC`lpyg7K{q1{3=scgm=Xb6 zEI_!_5zi$+3g`Dam+IyI1!o&{un-~gGDk|&8fnLN^Y4RhqD^L)7SSqnsnR?)#nmE? z-H2v7Fw2=03q&{qOgOci<%_Q6P1Iy$Z#smnBjw3Eg}KaK0VcJTp7p%6?;ahKjVGBf zy{B~~^78>X7qu4S8P9z&R^L2n&zESy})XX#SgB#{t-=1_wzP zpjgk7_5|Tn3QQJR+ymcxx)GjACeIB@qZBwn3a<}_$k%WQ;Vv$$=pg-Vw@2~vqHovm zg-OpWBGZ!26;0xrSfnBd+66xvt*;=DA(M2vtsktQz?KCoJjU#BaxPjgMbDTT0G*6- zKi`92ABYQXa?jXxKlRnnJ{CrQQ)(9XBN706*y2JpRSi3vhn(liGV+wb>3g)wpR&?Q z2_{5B0ujPq<%p$3OWbj6!%@_VVQtBBZTO>um?H|WxvlaNCKAKv;%R8tfgHcrmWZvX z?RF3y;QRIT01>?~xyEQ2Xc?#K<<+mnWg&(HRQJ@CA1J0PciI=)1fsmKp7?#%xzQz) zTETS(4-RT6d{yn1gh44>HBUL(s>kUNyM1#E{nj9WdDeBor4v5dig=lHun@}wOPIP7 z`FfCHj8{h4<2d6U3xSZ|?NIrLoE=>8Hl8dvZ&6eiXKK@(>32X#;3@&u$}MPDH$I$< z%RNl{c~`x+GSQ{>w+Y?KFOlwGP#~}T!BU@=vLbRn_{&3;M7n|pf{V%xf4nFZ_(Zv{ zLLCmoZ~!T++KH9NWYQ%*nkf!hHo}J32Tw%FsONA1 zm(1<{Na(!QlA2@eZU=jSN4@V`0p90)8WX6OWq2q(K@&FYYj9z#@$GETW zP(jR-=^dH{F&M-)xuU@t9)O_`aNKP~@$F~7K=w-5665&|^?|_suFIUw>JLVb^eLez zXxi=O2+JUH$u8bXMBpx>U|7pxf!hy@S5$})g0v{tq`l`4*gg!PnGd1C$peVdtOm)C zsYQ7}o5w7>=|J;Aga__1=lr}3C{8F z(%lbiX1nXL&_V7F1iSaaUB7g0aM7uy+l2@`cs~N#ori)dRALAeu#}pWIk;OFEvr5F z;}1|%gr#T^-j950S_I&E02M-fHORwP^H*%#l}ZuMg!uT8q^WmsJDO_9LIrmUvP%B$mwAdIdM!sZ;&u1o_vH{O8NTIT8_Trp#u(>+Zpadx z*sJf1viE;JC;m|I=`uoAzk@jQdEW%87(_RcUGyWEQ;Ct(8$X^L*Dm{3xUDQ>!qLjn?1_i~K2&_fFB7Ck!Che%xLq&B9Zyyf>ZmL|MT@?K-!wnTjUCXDTC0i4l$=WM!Ue z^q%{^aH4=A>?i+mG9OrN0dPB(Q(XrsF=j(6{+Xu|gcXcYRTd9hcB#1q zqb!F-iHOIkC2=3e*NehS#>j<4UaB`a?4qvRKUz~#n1zg~G)`@CDR$ZP&D;m z*7)0qg;I%8v^P8U4hZwM7L35&4$!TIEOEj3noEZ!-mj~xQc+M7@%O|80_NreCQ2O; zY4SMwX(E>o%%=!~t^>)ZgY;p_OsHzDIj@L&vGpsVN|x=v)Oh!kmM#XIDY(WU!%>Js zJ6NDu#6T+PBzjRjny`F~d>GK?(*D+i5p=4zhFO2qt*AAT8AW2CL`nRO3kL z&|ID{)AvU+9aBHMc)q9I@0Qo=T&o08F8tDuYQyT)a92(qP)t_0LWHOo#Uay&*?A_Q zYZ}0pF(Y$WLypVGs%5}goreejlMQv}wpxzox`nJewc4p-R)=UK0o`BF?z=VtC#}cC z^6_R)Nyxyx1Si zCu4R#E7G+yyqtYjb#9M9Kj-8Ws-ispe8w4;JRzxkdC!InyHXDU$Q#sT9YASe7vxVx zkk(AMd)7#HfI%9TiRF+0l1IoNSu%YX&l!|sj91sdoOXH@qpi$o@jSy?r=^1v0Vi6D zxiSx~N3#p^gEY160KT?7a#P3SYk!CbnuvGRD0c!wv3j^vkG#_GaKi9_sAr5()qLM^ zLQfmuDGB5uhSg5Y5gtTCtX6;pRcvBqLn)!Nf;#DH<(!J23Uvhg4ZQHZ3gVT-dL;tk zU2-=$f8-c;8wc5Yyog-%PJ;fn+pJfsk`jYGv0TBBloSm#UuCazBp z)2)%P@@?Y`BGxXB9|Ig6RX}ONwCFYN;17I7)_K&>TrP#Q;qPEM7_^!Ep14BH_Yz$u zDQ0lsIe30`9o>okv)I;}_5oFlRYl-rG7th%D={bR5WG@{Un!RU0&*>hjPo+d5B#!C zWEwi6`@~NBorK;-80hV+lnB=DjUhEP2<9Zd?NHtWS1`vFSK06KSk$r7^HhhgYDcKP z3pa%l%H9P-T0W$qA3A|qKEVa>gL8FAVeh+IHzye zzsxn}sm;&F_B$qw*BZM=YS@Po&SJ0T+d&=_oEwYe=;N>xIE8)bI6l`ofRXw=4>_BS z#8YAPP5!Z0XQD8ICIU&IS6A$GELOuV13s>Z$5GFWkgLf(^r5_#tJA<8xzC!UJBzc& zu>>AXx!mW6Gu_tmheE0Dk(OKIJ-=U8Q;p)`i8`|m^X-y{h|3SSWE z)vA@MCE%1!%2Pz}l7tqd>}9*qA!u-^%HoTm9(9g zaSJivRk9-BWe-)`g(`;n>Oa$NIQcPR4yi`o*q6C+jLa7u){mCi!j@5ZB$4RZA0+j^ z$q|Wl@s#jSe`FvORBaqb-X*0?f(1@!xE;@cR~DK-Gne#tT%jP`K5QgNV%!RizT4oM z3gyF1`yTicqZ6}K?h+U_@bc9mO&ds{D2YjQjT&UDMM5IV>^c}Q%&?*>73A7s3t_KthkccU z{E3Gc`s>%-4Md5f+IZq%i+omJpk*_cll$l!FzNYG`l5n)V z^Wo#D3_m=a`mGCc@Oy%?MgY`sr+yQ@TP&5~W*d-tv-YYcfj5o!<9)KS>Z63a zwU_Y!g_x%+z95Dze8x2H2+vZ3KK8MHHhiJka zDMR0-AWqF$n7&r$v*#F7{w55VZDq|(mG^4t?~S)4*}LA|BA#$Meye3ZwLA!jqR)CN$XU)&F8c(l{RH21I7I%W6i=r! zC@{l2gDOGA$f2<6W0$140MBn5r-B+-mJ-4xY*`*RG5LA>>kTbI*_ zOC>1HUM-s9dkHK@&>iJS@$r5N#PTTawc!CS=9&;@Etf?u#~N^Z)|?Kx_Z#BX-opuk zssO~vXIxFkhz$`r{?kuGp%L?ZWpiYu$VqpQMEBD! z?Qnx)&2LhE`@%%l@#OvTiP$w7+(Lq4sv%!t?L9eOFhhyNCt|Bfap3IO;qn5(5x=;{ z^lx%y#;?kuk&T;uz7uE#6GzbV29kGV#`(xGFSzGQeIlYn{f z@7b=XbR78A<>JB$*h8q=8GY+Az7YwPD*MI2ptjP{wX=f|rF>QG-4@N&w`1fL^x>3_ zx6K%QC2%`7M(#$m%8wmbts+H=G~&?X?Vq;*A|~bK#o+W#Tq#k>P z^f_uWkCI+ky%V@*il(w8nQ@U|MK17=5_r&6(L~d6>Yl}MB9AB%C$ioLi`!$Dc`}%f zy$DneKb?<}u@+{_dGdb(3O_%nhMWHdT)@17>1DG%O$Okw`~F~(=2(OdehbHiF6Kd( zAOsUpL|HokNMV$+quqU%gUgUoDC-;$PqGn*IRpH$n1LfclLm8H+Q~gt0_6Ewz728l zSoY{T!l{$UX-S9={{>8~EtV4V>4p!PNR9}SkR<9m!|SJxR%xMi)^P{~y_*muN>W{; zXEHvSK&OjFj@UrkVzzYLfUW=}4{`|J@G3z&JJ1P-P)J->V8M1S;kn?3Q5SDRNKx48 zw1pB5lPXsqpuEP`F@E=th!=kmY%=f7a5#VE{ggJnGmVz5XUAGHKB@#?Q~VvVN#K=B zzE8*Q)$N6r3)XLGvb=f&Yz}-NSQ!`aDQk7_fL=22xdc&RVkYmyKmsgW@eE3%d3J^d zz>k4U`8Yg;Vki%hR)Y~n))4ZeZ~Hylbb^`umf%7&5*LR+#0MBx49s9_{>|8RrJ|<6 zgHr?5>7X*0aC@8QO|*cO;|v{3xbbR4NkL&6$!BocuM_c5=kGor&`xh%k5!BPa;v$; z{TI+8Ebkx|KNiLij1(n$-E(gd0WsKo$Yth@OZt> z5I}VX|MHg$1H=tn>4(XFraUeTW+IZtR24X99Dg?pNTy-nc_^OYgDO+|MW?zKgR0}uIhQ-RWX(7Cwm(Uw0DO0kXe*@(Sg2C~&rv758qv5*1n zq`jV4XhX0ak6r`2=0_}|vO|vnrP7Gd@H!Pej?)}UlxA12_?wq}je&Wz3Cy$V(4qts zE5ax$Qv)X2JkUgvx2>3ZQ(4TTu)+4+U0Z7TJ{3paOwDYT@k&g~UmZq18)(;{>IdTi zsq>d*&~Cdv5ud49%)^h;yYJbYLw((h%Nl7190vgBUYvgoDF^dSi5>dgb4dIJ(7MYg z7^|MqKQW7lxfGOH7pHAaC%%l@$)J*x)Cc(NwsAKH+!mc|4)ixtg8M3buKec#&txxc zG}TRMMLfKmUDl*|?ET!MfE&-LUe>REqO#Rn-GdZCAw2GGze+XxvC)4@@bdCF zm#LYq{f_{EB!Anpcis#*k=RW{ayJmmi{7<^$Rw{>up|MfYeQnC>lVQ9jfgwbi2=J{ zftthzAzcyhZcGabI#6^^W=-WVcCnjr6LLi4H{ZhJT4=hz6|Pz&JgN zal*W|&V_!Syq+}Ac0p3 z4tD6E$wo<*Xs$zuLcj}kagdnN85D-;74owzw8hRHL`Pe3S2rj|+-_{0_`#__bSmg6 zr08oj_!J0;nH&5C!{P)@NRVy9rrIEsMIp%dagx^#K`Ze3$VmGnL3M+-m`T79+!g-- zgvtOy`=27G%M7ex5*NUbUxmRCMvs5+z(5Bo!v>V&HS6)6ar`2IP&ijEYr|f%qetT| z{rQ{7aSz5X8UfGX!btFJp5F7z4f4!HL5gx=YB1{u69@%WxEN?BCPGb56FQxIW6D2x zT%Ql{>S}yvQ&Zy*MxUl70z4vqGhV+LuV0M+02GORB9K$c~QB|5yTWf7~qAZAUn|z=R*uI5f4o89>?_I{t6R8`Bn#y z%Y+3<6R+Sl1MS2IWa^~{9KRSjm-M*4h?V^_ONpb7{G{jJAPH6L*gej0(sTCx1@zbN z5)3+ET|V)r*mO5kc^dt3)TOGt6QaZKBFH7w29HucbEbuHQV;we%uKYJN*>X{>zDF~ zRAB(eh@{c`zHu(6CwFGH;nIRgbLtL`@q!C*C|Dca--G8We>(sHur%-Yz=b(v*G7%c zuQ@N%he0aGy|3_^i`nX~*dQGC{9<^9ya~6yIes7aL^9@hNUwgr{8nmEq)wZ$$bkh# zSwo(FGm4ZOtQd$YV4k83xOi5M^VQpdN;m@j4*lV7P!gS$KT`<;6Ga}(K#Czd z4;KQd3f2<7a!0um5a)eJ;}d|QiSyX!)12UdiI>31^Kd1C#;*PQGwJ>xPH)HX`N@GZ z>CdMa7!>dua!^GdBgQF#KvMB|`seYVoR5qHZmHlLxJdvaaE}gtbABcj>2veM?L6nx zoygqXoBjw8Aswvsyex@8FO`9tw{rlbe>kQ|&-;SeN`gqh=SG9kiMVX)2SH5*;|&5{ z0UxsCg~R~rF8KLz;aTKaxRS~kMaJQT*}CfH-dMwWifFA_dBcb=3y+d8bRb3*lu>7^ zg{q4{HX-1ax4feOs9-9dL4!BH_XJX=;Pig4p~qnLRD=@2-u^LM3?dJoXS^0rL1Elz zO{>oJfYQ+D#9;*vp0F?o0Yi!Z0GOm{L>WYw0ENTc68)|u$wdPdW#!ixb~O+nT5G4w z!K!yyqS`#h{&3c58bEMPR^)la0QR)t8u_>-&OjO~PL%5!)jyDz(nm)(9YEwoN)y`O zlL`FOTgrP!5u*djK|dE01c9@lM9kHxIde`OY5g)*W|auqc4Ii8;zZL^BOMN1a%J9C zSVT5m{Fx?ffl@T_&O);{L?NCo@@_)x!Dg@^M35%G?fJ(A#XE;Kd~1=KAYq5g5Za~agHnz9PrV>*;GPsiQLw*Hi8F~w?~{sgeGk^_pBp?2F0%i zEj^)l#xiL$@WaN0p{rmSASR<%3toR*5W-HtRzH!$C?|g2`^dym9!G}*p!cugbP<`wDg1Pao^#{; z?qYI4s=77G;j;KTPY?cJDJmzF=l=k?yCPSS;{5f1hC&C2Ka4~Xyd%#2OwvN2&2(jp zNL#(|f7S}h&oA(pjZTk?ic)aDzx~7lT1(#e{M=DMjDGhlc>B5*{qHmy$wf4Lv@rsK zGTosBd_TYOSSC&s+59j1KoAJ@mjVzVY9H^du>QTMFhT`5bgILtH*z3@h@&QpYvU5@ z?1)A5?p30-Hilbj^J z58$`wpVKMikdO&yS6HSk3fV^9#3!t!A;H(*-nz$}2osU#4})p&=)DV$;Oyvh9>K*U zB7N(seX;8(QBDMomoB^ODP{eW10)kuKzmuan@dOh1K%z9F;=HWfI#ui@K6eK)oOFv zKJ&A1qcyE`;IJEoDx_ZfKNzUBxR^GB_rz$ssmcWTaKKNJg^-Sso5mDKViFNvUS@4I zeRNG9HeditymTC29R6{7G}W8x1B!|WdK^>bLooMQPK;3KY%hEN0FnR^2=MHg1p`yK zI@824rx2fL?8Ri-lFDOhkieD}Ka4s7f++wP)$Gv%gJ_68XE>#*;UoV5SZq0LISB!3 zP~S5I34>bQT6mXu?uNt7Yx{q@Jt`{|8$O#m=S{3ZL{JEqoC^SnUGjd|)Ew1QcR~5y z5=j7XLr$L@{bK4`_K~Xo$C;9N#pot&V#)wK?~IcyqJZrm@0!3vQ4O!Vue^4KHN(mJ znX*JCQ}+}5X8=(LP2+#J`_S-yKhxvZU*oR>^Mvpp=oI0f!=8WSO#o{}Rp1WS1tdkg zAd+3Qwie@lhH{_KGxb|`}QH_mgIX-!S3Vb8VEmL{NIFrUGK zDTP=w$Dzp@6Js=m5%YqP33x#P`u_lQ-HHkLPYA?(n2d^p19~01G;8XlQ^JsAsBq& z;}?h!aD(zGy@y5T< zvGuJezGoNQz(BkR2hslk1m++bH-+`qPP@Rw>SJgB0B|`8(2key90n1&-1xwEB}$1e zKJpPvIZI2|J>*1PnpYq7i}F!)XC@j0fOmLvY^ft{bB4Kyd8{RQd2?kpdb; z;Cy7@uwG6d*9kH(RJyYShQW9SFW2|Mx}UJ)@?hLw#83Uh4oFg0qXN*E11zIQmOUoV8;G2Yt=pb zg=jru>IfmQ5O`PXB-80jM%qcI79~J?1Tgp-S4Ts!)(Qv(2wwpC!>~g`lIh^rTf}c> zdeE6f=)X5V!Gb#m+HU|NpI(HWEI(ZEgv@uY{!F%l>Ua`w=NOSz%0v=hA;W2tVHzjv zj$uP2YDa!Goe?iJ8{V);IqU)vh1RhIr+Vm~4iAms0Hv_6A?C9Lu~pRBX?AZe1eVwk z#WwO`Yydw7E%(+tB{}sn$s`$4+4*3paJSs~U#;ST_!?^N`oe(bz#Eai@p&?dHlMy2 zPalRCUs-6aCU^ke8~~!eYqs^2iAoY}cw8eIBZIAC?gyKR(B2$PPlXpd>4-K<00&K8 z^Kf;>gk4>6iEs%!=>q2}1%#cA_`|t2ZKTt)B!gQ631?p)@DZ4hsIHpnb{}s=09Y0C zb;T^#Wu=Y6#1?hq7lxY!Y1_BF zBJXw7{NiBj<|iLm*l;SZdg;b-Q)aC(TJ90{f4~4kteXLkgnu~wQ1k$+i-m@}3wP2C z^O~p{OM>y@mo-v*?Z&!#TtsCJ0k|9)Tp&T_7p@p0JY+g#>aZ@o35_5v1k1p^TZyD< zp9U~OBO2$A+YEc4Sx0zKD`?m~hcE{$lN>0pzvsq7WTQu=E))kl!uEN?L*prnNmOX6 z{y%J)B#iCYA31GNj-abpuB$>XpVG(MJfafom7PFJX(qyD53>qr0M)6eF8PG;w znBX)uPJx5#DdN=lDbJ6=nANXm(k?_t^bG>!HIGz(Ka@2ru0WeVpj^{d=aCQo- z)aL{yuvIuuSScC_f{w~=UH<^z3D&nNDgz8V>ipIr)2+|fEk=+oUT&E2#%db3c%>MH z;o~(Pw56>4;~QwI_}iSMXvw4h0Dn*T1sXW2SUms_=Qp;1lp})F7X(nb#9ndia$1N> zH2?<<8e%~R)4F$tp#>Pk9~r8MSzthZ2k#u4g6pyUhFCC5uTHyXcLxTNyEE_0cl;dg zheoGE&hQqH*%Ox*9bPezVM*#)^36Q78brYBr)$~X}9-q z&{zfKtlJ((Ao5A_;xmZ=X9Ha4z!5g}ZeA)v1biP^TTBfB{rF1d&LIdxES-B4WO?-B zUG&>I{{X*uGKKtcv%dF>IcG zpRBlaw(KXS0%(AG+^>4h=qn6@KRtWP)+n?SsfB zpRPt8)x=oIyE@1WV+CrO^RdJ|-Vp-s_~K&*y)cvX-bbBP&|qcoVZ9U1ZGmB-%HRyD z>-?v@d|Mk@au;*^X6QnJ?7H)c6-vN~`fb5lom3#Ded`9m6!aOWs$wkcjPT4rTS1q~ z{!D|FB^|%(5B6dkLcDXV(NJubYHPN2nhY6Z5|r!t0)h%}9_*(_htv75)@#r}#~-c& zFQH4$x8J-{;SOH;@cGA5NG()%1pfdo8XMqxSEWA(UT_Z|=ulN4ZORz~Y=KdUHdpcE z4l#vG==r}`1hf;*v6h6X;R62vyJSryB8B!^_0A?#)W>NZCT{QMlG=9o@sx05y@d1T zbBI6;zQk}ByfrbAQC>$CtK|%< zQu$)*Hd;H|_s$L;HLGvuB-6;&d-=mmMIDY6Rt0K2BkT3ZMFQU-H2nO6jS8DDFzW9w zqKK*iz#SNYFb`LpF)u(}FURYIILbR5)FlWj(4VsBI5kaxG3!_Yw^|6{d}0Fj#K36( z0K8I)z0Q}~VAKQ@fK9J2{PzH;4p0_;n6eNBP$0mtGQr9M{F4|9LATHOagb2$lGB9p z8Mh6*fkG?9o<*rfyPbchcdZ2ET@TXVtagwJEnU5b`Epo55EHHKJ}{V= zWl%(~ndAMgbTM^sQTHOFuZjBNJx`#9HhbS4;jepK0NdHZb(913qM|DNWKnoR2~e84 z+13`*bWj(M7faR!!6#J}JChX%6Gl0K&LV1CK&>M5W1zy5#KAED8q)QQF(h&p-*`4H zu$5l?YxT$#ZIn3v_#>0;C_8J^X@V2dlDolim53#S@rj#&)KCR~Qx%{A5d^am2e1tQ z&(0D`VFff9h+q>5NbmL0h>Zt}Pk@~>D_&DdyKSx9pk^&1jr@)rk5hapU)K_4*#TEH z>jM@ctEja3o#HtYIO!Yx&zuKTgc?dMmw7^idy)!2Tqmg@2$%4izsOUNa`L-Rz~rE4 z6P-}U3Pgf1k9R6~5q41?LtK5}gs4^rTRSUFn)idy9Pclc{f@GKsO*VRfE>8$ofGl{ zUVPUKAOmxI0PC&$z&@Y|0nmT1obgJ-7*K+KqD&vBkcY$VUL&hwFgO z2Edz`u=2xZ;AvKHZP0kbgqnv5*Tal4xtD!;*0GUwD_(iiqW9+zE(bt|03SKWNAOAk zT12CQ0Apj5hV!gZ)>)|Uo$}uCDF6XRym*)z?7NDm{{Tz?{K9wdcm)#OA>wj%0|^K; z20cIp7VoEvfRNlmMLzJx1vdyhmz;(Ih}7Q(dCkbgTc?yP#c1gyQq_L*R-Xh>_@*kf zm3Pla#s&j4wC&B_Ya)WHrxkF7TAMywyTTy=Kn@I17p_PikMz&^duS3f`CKtVgd{|) z$UG6Y@E;zr*A!IiLe_VhmPiy9p7E;hy#2A0t+5G#q%75(bLS1^5h1LDLtDZfzvsps z-$=*)a}tk;f#wBr96Rs(g8>$1C@Zkwvz#R$ygSn6IE(_Y)hWRH>bTkjn?PRWt~mx8 zFg_z6^#@gOU|t`LAOor8HYPIbAvFjzJK5_A5gJaid{8%nfZCLA1Rcxk0fAg)VNuid z^^eX52CAL-ku}akghdUJ$v0i)MBYFhB53!%HHgHC>)~lN*SDa)bWxaFkBY^0QKX;+Rm4H1a+i zKs~xFMjJQh%*SX8b6-3iIdm}>YKKn-{;;T9VY_yG^D?-G((nn{#_`r7h1CssV{b%1 z5Ck#>kPivTh9KAVsz0OigehS9hd0J)pm5Qm{PXdUAfRxZnZal2rC0gm7GYw^alaQd zASx-_jcLbI8YrmK->&f@KjZ-f5QAe}>lFZd3wP)C!Er&YE=FW%M0wl!!?0JlGP=Y( zTBvuF{{S2i)xejVJ@Buu;eU(X3V_7OkmnPu4h<7v;~-J6HhS@j;(;Mn-E02-hi0>op z9)E1o0Q6tm+kkXCXV)3ns^2Q|xmhm1f)svCkJFqos#D>uXDUbvpAIsFBMCnBywRZn zCNqpcLYyHc?~gco7w!0X&I2qIeoR;0MAf(ujc`bLM)L0B&%9iT9u6-`_v> z8UFyV&;156{_8zQ+ZwMBY96kRdFS}g@KB+J96E0BkEeJ5$n7|W;Roa1CzUFe60-Po z`O8pc1kx^}yEUtkQ%-ul@WBaUdWv1yY=fHxoZ*A{pKeCOwdE@3;4z3MX^*?Z>&lYF6*iFf(aYe zZSd-0Py&=Ygb$ngYUFqrHVocV$7@qcSHrLEa;))I0@O|LAB>F#${@Rb2L76zZeOP z8ld{uC#)g>NCBYB{3nom*`DEi%;d1&I>Ge!$9Z0l#(qB;t?9m5hP-Bx_-B+a#zNR! zKC%fApBPR%@txRTjDvtavKr7%rV&L2JI!9N)tT{}qswvqU*Qgh{bsm_jxrOekhX6- zxS(w$@4?N;O-aG50psz8nnUY4p*}O{{ARg@IM!>|;|OS<8AOZ!00I1+kqT~xk0evh z-x#hGNExH^gCsqJKn;L4ao!@21&$#!sppx_HlALC)L%lwDBt|0I`^AeRjNj{%F67x z8(P{5&`ITWtbHiJ0yeE9N&Dd-&HM3sz!jnzj(g#7lqhoYVXTVgB7!QDo-&20R9^CH zXN9>?Nl!Q?Xgcn3a)A6wGWzYg^%%$pY;%4BdsCxF@lblHoSCu#nwmXQ%4t_38 zns8ExU1~MNK*LZwvtzU7~I$<1bwr-*O$`1xu@RD`=_Q95U~NJ7*ut+bTFmhu@BF z17|pZxNz_XyeS;&eAjOmtka*)Qjyw_3<8!^QOe0#pXI|u)8hp>TzOVOpmLv+7C@uI zXLCO}TvW>Wa`#*YcBLD?A5K&y)?Y3JMb-+o?#{>S0E(1*ypvObtRkoc*2N=5QB5_ znM~^d4x>qZ^)WXRF?eS3JcR^V`y|8?c~Re_>P%w^DmoD49nmmAef<8I4$ra;P4jLl zJ&FkrH>)sL?FcD_4;6Ro5RB+Z3r_=gCBj7n?a|K|a0v9>fW&`9MQnHgHu%Ss{%)YI zU2ZF*_vyF{bo&1QtU|))XPN6+0bn^fbuwXDU7svO*VLqQDp3_(lczXU8`ePvp zMRTo6%06eE<$YyQ5>~br5AUDlGomIq9*yD!Tn3)zZ<()-bAB@a0E4UzwEqB|;LM4) zlfm9`6hkCEXIuLdHCOn}sLr*ii(m|8VlgKuyB z$CNGV3M-dR{oxc4)y(4)kZZeM1R?PA{Q2C1$p;RP&L~tsdlKXV9Rlq!gUHzFHM5>D z3IWLjK5zhFI}?QY$P-!wh2p(f%sIh2wf!+vNy|-Q9fbI@19f1GDA$I$nGI4Z_Xv&JYik}jOMDnJ%TPBc)V=V!e5gWj`AVEg6B@*Xea z0U{~Y;~azyli0`V;NCWJ{{TRc1$n3-PrQh=ror6SPzJHJz!5tX_i-*3j8-nSO1%Bx|BLZDZCKIOs(5_xNMXiQan%1@xNtfr%T54w`uQ z&6NlaAHabNmN0K1?+$lmQz0uh!Yet-D0#8jTvzMw9yG;L6Q>_{APx^wi|%vpC6nVq zM#wuOSh+zaWMc{6rzC=IFM;TLS=K_}tZ8Yh%c;k_K-hY#XlGmg><*MIR1W8-8bTJA zwV@|o*9&SE!18hPkVjvtP%k^4-{=~mG&U;e4{mX&TZ6GPVx3wz7gss{yMkN4&TWO7 z4-9v5;T{eLgzNj@_yR$^0dPO}l?k^$C&0|sjQiU!!A@{QY6S(x!ZnuoA>Oib^)=tc zz(ABuY#KexK~hqZi?f{Dz2t4{9)Jq3h-0%LL~N+8#NJ72A~8;{tTBNCM@i(x3u6Rd z3-dqGf1tu$l#-`N_2(KT3bY%u)Z$?h3mO+9j}Nn0WGd#WpwuCHH=461YD%$LZ%(El zR+|Q(EkotWxIVRqW`-%bj-VGt+FiRUUiIS}>GX;%1nYS4DV`|XeSWxuPTsxzzD zLv0Sv>73n~~%CA&@>SQCaGrZ=7_2b)PVEKCS>MPI?Wpr+Fs~8ioPz4En|yF~}u5Q&$*; zq|j)q%kMc_G~N(GVye#kJYgrEaP3Jbc|y8)t|)-F=|v^Ivz!D7BN#>Op7YhGvsw(} z^>9bicFVa>oj$SMIg&-Gu%?bfCgCSrnx37$WpWd8`oT8wI>bqzwFB2QeB%?6M$#(r y0-t!>*SVPh<8@cx^e*#J=QarTohM)D>VLcc0H4t|R!WGGvzr6@Yp)OKkN?>Xy~@G> literal 0 HcmV?d00001 diff --git a/src/Tests/index.asciidoc b/src/Tests/index.asciidoc index 873adf55c98..41313633127 100644 --- a/src/Tests/index.asciidoc +++ b/src/Tests/index.asciidoc @@ -1,4 +1,7 @@ -# Introduction +:github: https://github.com/elastic/elasticsearch-net +:stackoverflow: http://stackoverflow.com + +== Introduction You've reached the documentation page for `Elasticsearch.Net` and `NEST`. The two official .NET clients for Elasticsearch. So why two clients I hear you say? @@ -9,30 +12,29 @@ enough so that **all** the Elasticsearch API endpoints are represented as method Please read the getting started guide for both. +=== Who's using Nest +* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). +* http://www.7digital.com[7digital.com] (run NEST on mono). +* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). +* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. + They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] -## Who's using Nest -* [stackoverflow.com](http://www.stackoverflow.com) (and the rest of the stackexchange family). -* [7digital.com](http://www.7digital.com) (run NEST on mono). -* [rijksmuseum.nl](https://www.rijksmuseum.nl/en) (Elasticsearch is the only datastorage hit for each page). -* [Kiln](http://www.fogcreek.com/kiln/) FogCreek's version control & code review tooling. - They are so pleased with Elasticsearch that [they made a video about how pleased they are!](http://blog.fogcreek.com/kiln-powered-by-elasticsearch/) - -## Other resources +=== Other resources -[@joelabrahamsson](http://twitter.com/joelabrahamsson) wrote a great [intro into elasticsearch on .NET](http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch) +http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a great http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] using NEST. -Also checkout the [searchbox.io guys](https://searchbox.io/) rocking NEST [on AppHarbor](http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on) -with their [demo project](https://github.com/searchbox-io/.net-sample) +Also checkout the https://searchbox.io/[searchbox.io guys] rocking NEST http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] +with their https://github.com/searchbox-io/.net-sample[demo project] -## Questions, bugs, comments, requests +=== Questions, bugs, comments, requests -All of these are more then welcome on the github issues pages! We try to to at least reply within the same day. +All of these are more then welcome on the {github}/issues[github issues pages]! We try to to at least reply within the same day. -We also monitor question tagged with ['nest' on stackoverflow](http://stackoverflow.com/questions/tagged/nest) or -['elasticsearch-net' on stackoverflow](http://stackoverflow.com/questions/tagged/elasticsearch-net) +We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow] -# License +=== License This software is licensed under the Apache 2 license, quoted below. From 7ee1afa8e4e101efbb94b375c5410b94a1b2ebfe Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 10 Mar 2016 17:19:32 +1100 Subject: [PATCH 06/18] Clean up emitted asciidoc and add attribute entries for common links When writing out the ExpectJson accessor value, compile an assembly from the anonymous type string in order to serialize the type and get the json for it. Temporarily checked in AsciiDoc assembly - will release something to MyGet/Nuget for this when MVP is done (e.g. Tables are not yet handled) Lowercase and hyphenate all files --- .../children-aggregation-mapping.asciidoc | 23 + .../writing-aggregations.asciidoc | 129 +++ docs/asciidoc/auto_map.asciidoc | 943 ----------------- docs/asciidoc/bool_dsl.asciidoc | 145 --- .../children_aggregation_mapping.asciidoc | 18 - .../connection-pooling.asciidoc} | 329 +++--- .../date-time-providers.asciidoc} | 119 +-- .../keeping-track-of-nodes.asciidoc} | 200 ++-- .../request-pipelines.asciidoc} | 69 +- .../building-blocks}/transports.asciidoc | 84 +- .../unexpected-exceptions.asciidoc} | 231 ++--- .../unrecoverable-exceptions.asciidoc | 51 + .../failover/falling-over.asciidoc | 88 ++ .../max-retries/respects-max-retry.asciidoc | 148 +++ .../pinging/first-usage.asciidoc} | 228 +++-- .../pinging/revival.asciidoc | 54 + .../disable-sniff-ping-per-request.asciidoc | 78 ++ .../request-timeouts-overrides.asciidoc} | 169 ++-- .../respects-allowed-status-code.asciidoc | 26 + .../respects-force-node.asciidoc | 27 + .../respects-max-retry-overrides.asciidoc | 73 ++ .../round-robin/round-robin.asciidoc} | 149 +-- .../round-robin/skip-dead-nodes.asciidoc} | 365 +++---- .../round-robin/volatile-updates.asciidoc} | 13 +- .../sniffing/on-connection-failure.asciidoc} | 308 +++--- .../sniffing/on-stale-cluster-state.asciidoc} | 191 ++-- .../sniffing/on-startup.asciidoc | 125 +++ .../sniffing/role-detection.asciidoc | 128 +++ .../covariant-search-results.asciidoc} | 441 ++++---- .../inferrence/document-paths.asciidoc} | 211 ++-- .../inferrence/field-inference.asciidoc} | 829 +++++++-------- .../inferrence/ids-inference.asciidoc} | 233 +++-- .../inferrence/indices-paths.asciidoc} | 97 +- .../inferrence/property-inference.asciidoc} | 60 +- .../high-level/mapping/auto-map.asciidoc | 954 ++++++++++++++++++ .../low-level}/connecting.asciidoc | 618 ++++++------ .../low-level}/lifetimes.asciidoc | 165 +-- .../low-level/post-data.asciidoc} | 222 ++-- .../{ => code-standards}/descriptors.asciidoc | 110 +- .../elastic-client.asciidoc} | 37 +- .../naming-conventions.asciidoc | 130 +++ .../{ => code-standards}/queries.asciidoc | 35 +- .../serialization}/properties.asciidoc | 39 +- .../date-math/date-math-expressions.asciidoc} | 213 ++-- .../time-unit/time-units.asciidoc} | 244 ++--- .../disable_sniff_ping_per_request.asciidoc | 79 -- docs/asciidoc/falling_over.asciidoc | 84 -- .../asciidoc/images/hadouken-indentation.jpg | Bin docs/asciidoc/index.asciidoc | 2 + docs/asciidoc/naming_conventions.asciidoc | 130 --- docs/asciidoc/on_startup.asciidoc | 121 --- .../query-dsl/bool-dsl/bool-dsl.asciidoc | 165 +++ .../geo/distance/distance-units.asciidoc} | 240 ++--- .../respects_allowed_status_code.asciidoc | 22 - docs/asciidoc/respects_force_node.asciidoc | 22 - docs/asciidoc/respects_max_retry.asciidoc | 148 --- .../respects_max_retry_overrides.asciidoc | 71 -- docs/asciidoc/revival.asciidoc | 50 - docs/asciidoc/role_detection.asciidoc | 123 --- .../unrecoverable_exceptions.asciidoc | 46 - docs/asciidoc/writing_aggregations.asciidoc | 124 --- libs/AsciiDoc.dll | Bin 0 -> 68096 bytes libs/AsciiDoc.pdb | Bin 0 -> 235008 bytes .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 53 + .../Documentation/Blocks/CodeBlock.cs | 13 +- .../Files/CSharpDocumentationFile.cs | 86 +- .../Documentation/Files/DocumentationFile.cs | 10 +- .../Files/ImageDocumentationFile.cs | 4 +- .../Files/RawDocumentationFile.cs | 4 +- .../Nest.Litterateur/EnumerableExtensions.cs | 26 +- .../Nest.Litterateur/Linker/Linker.cs | 34 - src/CodeGeneration/Nest.Litterateur/LitUp.cs | 7 +- .../Nest.Litterateur/Program.cs | 19 +- .../Nest.Litterateur/StringExtensions.cs | 63 ++ .../Walkers/CodeWithDocumentationWalker.cs | 114 ++- .../Walkers/DocumentationFileWalker.cs | 23 +- .../Nest.Litterateur/project.json | 15 +- .../Nest.Litterateur/project.lock.json | 167 ++- .../Aggregations/WritingAggregations.doc.cs | 196 ++-- .../BuildingBlocks/ConnectionPooling.Doc.cs | 26 +- .../HighLevel/Inferrence/IdsInference.doc.cs | 64 +- .../DateMath/DateMathExpressions.doc.cs | 50 +- .../CommonOptions/TimeUnit/TimeUnits.doc.cs | 34 +- src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs | 190 ++-- .../QueryDsl/BoolDsl/hadouken-indentation.jpg | Bin 0 -> 43939 bytes .../Geo/Distance/DistanceUnits.doc.cs | 56 +- src/Tests/index.asciidoc | 2 + src/global.json | 15 +- src/lib/dnx451/AsciiDoc.dll | Bin 0 -> 68096 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 0 -> 235008 bytes src/wrap/AsciiDoc/project.json | 10 + 91 files changed, 6256 insertions(+), 5601 deletions(-) create mode 100644 docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc create mode 100644 docs/asciidoc/aggregations/writing-aggregations.asciidoc delete mode 100644 docs/asciidoc/auto_map.asciidoc delete mode 100644 docs/asciidoc/bool_dsl.asciidoc delete mode 100644 docs/asciidoc/children_aggregation_mapping.asciidoc rename docs/asciidoc/{connection_pooling.asciidoc => client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc} (61%) rename docs/asciidoc/{date_time_providers.asciidoc => client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc} (56%) rename docs/asciidoc/{keeping_track_of_nodes.asciidoc => client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc} (83%) rename docs/asciidoc/{request_pipelines.asciidoc => client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc} (88%) rename docs/asciidoc/{ => client-concepts/connection-pooling/building-blocks}/transports.asciidoc (77%) rename docs/asciidoc/{unexpected_exceptions.asciidoc => client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc} (51%) create mode 100644 docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc rename docs/asciidoc/{first_usage.asciidoc => client-concepts/connection-pooling/pinging/first-usage.asciidoc} (66%) create mode 100644 docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc rename docs/asciidoc/{request_timeouts_overrides.asciidoc => client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc} (79%) create mode 100644 docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc rename docs/asciidoc/{round_robin.asciidoc => client-concepts/connection-pooling/round-robin/round-robin.asciidoc} (60%) rename docs/asciidoc/{skip_dead_nodes.asciidoc => client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc} (87%) rename docs/asciidoc/{volatile_updates.asciidoc => client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc} (77%) rename docs/asciidoc/{on_connection_failure.asciidoc => client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc} (84%) rename docs/asciidoc/{on_stale_cluster_state.asciidoc => client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc} (60%) create mode 100644 docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc rename docs/asciidoc/{covariant_search_results.asciidoc => client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc} (74%) rename docs/asciidoc/{document_paths.asciidoc => client-concepts/high-level/inferrence/document-paths.asciidoc} (79%) rename docs/asciidoc/{field_inference.asciidoc => client-concepts/high-level/inferrence/field-inference.asciidoc} (80%) rename docs/asciidoc/{ids_inference.asciidoc => client-concepts/high-level/inferrence/ids-inference.asciidoc} (51%) rename docs/asciidoc/{indices_paths.asciidoc => client-concepts/high-level/inferrence/indices-paths.asciidoc} (56%) rename docs/asciidoc/{property_inference.asciidoc => client-concepts/high-level/inferrence/property-inference.asciidoc} (67%) create mode 100644 docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc rename docs/asciidoc/{ => client-concepts/low-level}/connecting.asciidoc (74%) rename docs/asciidoc/{ => client-concepts/low-level}/lifetimes.asciidoc (78%) rename docs/asciidoc/{post_data.asciidoc => client-concepts/low-level/post-data.asciidoc} (83%) rename docs/asciidoc/{ => code-standards}/descriptors.asciidoc (55%) rename docs/asciidoc/{elastic_client.asciidoc => code-standards/elastic-client.asciidoc} (80%) create mode 100644 docs/asciidoc/code-standards/naming-conventions.asciidoc rename docs/asciidoc/{ => code-standards}/queries.asciidoc (54%) rename docs/asciidoc/{ => code-standards/serialization}/properties.asciidoc (79%) rename docs/asciidoc/{date_math_expressions.asciidoc => common-options/date-math/date-math-expressions.asciidoc} (55%) rename docs/asciidoc/{time_units.asciidoc => common-options/time-unit/time-units.asciidoc} (71%) delete mode 100644 docs/asciidoc/disable_sniff_ping_per_request.asciidoc delete mode 100644 docs/asciidoc/falling_over.asciidoc rename src/Tests/QueryDsl/BoolDsl/hadouken_indentation.jpg => docs/asciidoc/images/hadouken-indentation.jpg (100%) delete mode 100644 docs/asciidoc/naming_conventions.asciidoc delete mode 100644 docs/asciidoc/on_startup.asciidoc create mode 100644 docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc rename docs/asciidoc/{distance_units.asciidoc => query-dsl/geo/distance/distance-units.asciidoc} (57%) delete mode 100644 docs/asciidoc/respects_allowed_status_code.asciidoc delete mode 100644 docs/asciidoc/respects_force_node.asciidoc delete mode 100644 docs/asciidoc/respects_max_retry.asciidoc delete mode 100644 docs/asciidoc/respects_max_retry_overrides.asciidoc delete mode 100644 docs/asciidoc/revival.asciidoc delete mode 100644 docs/asciidoc/role_detection.asciidoc delete mode 100644 docs/asciidoc/unrecoverable_exceptions.asciidoc delete mode 100644 docs/asciidoc/writing_aggregations.asciidoc create mode 100644 libs/AsciiDoc.dll create mode 100644 libs/AsciiDoc.pdb create mode 100644 src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs delete mode 100644 src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs create mode 100644 src/CodeGeneration/Nest.Litterateur/StringExtensions.cs create mode 100644 src/Tests/QueryDsl/BoolDsl/hadouken-indentation.jpg create mode 100644 src/lib/dnx451/AsciiDoc.dll create mode 100644 src/lib/dnx451/AsciiDoc.pdb create mode 100644 src/wrap/AsciiDoc/project.json diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc new file mode 100644 index 00000000000..b118f2c2095 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -0,0 +1,23 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +To use the child aggregation you have to make sure + a `_parent` mapping is in place, here we create the project + index with two mapped types, `project` and `commitactivity` and + we add a `_parent` mapping from `commitactivity` to `parent` + +[source,csharp] +---- +var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c + .Mappings(map=>map + .Map(m=>m.AutoMap()) + .Map(m=>m + .Parent() + ) + ) +); +---- + diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc new file mode 100644 index 00000000000..9df658d1d0a --- /dev/null +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -0,0 +1,129 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../images/ + +== Aggregations + +Aggregations are arguably one of the most powerful features of Elasticsearch. +NEST allows you to write your aggregations using + +* a strict fluent DSL + +* a verbatim object initializer syntax that maps verbatim to the elasticsearch API + +* a more terse object initializer aggregation DSL + +Three different ways, yikes that's a lot to take in! Lets go over them one by one and explain when you might +want to use each. + +This is the json output for each example + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "name_of_child_agg": { + "children": { + "type": "commits" + }, + "aggs": { + "average_per_child": { + "avg": { + "field": "confidenceFactor" + } + }, + "max_per_child": { + "max": { + "field": "confidenceFactor" + } + } + } + } + } +} +---- + +=== Fluent DSL + +The fluent lambda syntax is the most terse way to write aggregations. +It benefits from types that are carried over to sub aggregations + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) + ) +) +---- + +=== Object Initializer syntax + +The object initializer syntax (OIS) is a one-to-one mapping with how aggregations +have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one +mapping, being dictionary based in C means it can grow exponentially in complexity rather quickly. + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", "confidenceFactor") + && new MaxAggregation("max_per_child", "confidenceFactor") + } +} +---- + +=== Terse Object Initializer DSL + +For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, +These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. +It also allows you to combine multiple aggregations using bitwise AND (`&&`) operator. + +Compare the following example with the previous vanilla OIS syntax + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) + && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) + } +} +---- + +=== Aggregating over a collection of aggregations + +An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations +on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor +(`childAggs` below) in turn, returning the descriptor after each function application. + +[source,csharp] +---- +var aggregations = new List, IAggregationContainer>> +{ + a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), + a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) +}; +return s => s + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => + aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) + ) + ) + ); +---- + diff --git a/docs/asciidoc/auto_map.asciidoc b/docs/asciidoc/auto_map.asciidoc deleted file mode 100644 index 04e388cdc21..00000000000 --- a/docs/asciidoc/auto_map.asciidoc +++ /dev/null @@ -1,943 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Auto mapping properties - -When creating a mapping (either when creating an index or via the put mapping API), -NEST offers a feature called AutoMap(), which will automagically infer the correct -Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if -you're using attributes to map your properties, then calling AutoMap() is required -in order for your attributes to be applied. We'll look at examples of both. - - - - -For these examples, we'll define two POCOS, `Company`, which has a name -and a collection of Employees, and `Employee` which has various properties of -different types, and itself has a collection of `Employee` types. - - -[source, csharp] ----- -public class Company -{ - public string Name { get; set; } - public List Employees { get; set; } -} - -public class Employee -{ - public string FirstName { get; set; } - public string LastName { get; set; } - public int Salary { get; set; } - public DateTime Birthday { get; set; } - public bool IsManager { get; set; } - public List Employees { get; set; } - public TimeSpan Hours { get; set;} -} ----- -=== Manual mapping -To create a mapping for our Company type, we can use the fluent API -and map each property explicitly - - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .Properties(ps => ps - .String(s => s - .Name(c => c.Name) - ) - .Object(o => o - .Name(c => c.Employees) - .Properties(eps => eps - .String(s => s - .Name(e => e.FirstName) - ) - .String(s => s - .Name(e => e.LastName) - ) - .Number(n => n - .Name(e => e.Salary) - .Type(NumberType.Integer) - ) - ) - ) - ) - ) - ); ----- - -This is all fine and dandy and useful for some use cases however in most cases -this can become verbose and wieldy. The majority of the time you simply just want to map *all* -the properties of a POCO in a single go. - - -[source, csharp] ----- -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - name = new - { - type = "string" - }, - employees = new - { - type = "object", - properties = new - { - firstName = new - { - type = "string" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - } - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- -=== Simple Automapping -This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, -explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work - - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap()) - .Map(m => m.AutoMap()) - ); ----- - -Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. -In this example, -- Birthday was mapped as a date, -- Hours was mapped as a long (ticks) -- IsManager was mapped as a boolean, -- Salary as an integer -- Employees as an object -and the remaining string properties as strings. - - -[source, csharp] ----- -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - employees = new - { - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - type = "object" - }, - name = new - { - type = "string" - } - } - }, - employee = new - { - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- -## Automapping with overrides -In most cases, you'll want to map more than just the vanilla datatypes and also provide -various options on your properties (analyzer, doc_values, etc...). In that case, it's -possible to use AutoMap() in conjuction with explicitly mapped properties. - - - -Here we are using AutoMap() to automatically map our company type, but then we're -overriding our employee property and making it a `nested` type, since by default, -AutoMap() will infer objects as `object`. - - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - .Properties(ps => ps - .Nested(n => n - .Name(c => c.Employees) - .Properties(eps => eps - // snip - ) - ) - ) - ) - ); - -var expected = new - { - mappings = new - { - company = new - { - properties = new - { - name = new - { - type = "string" - }, - employees = new - { - type = "nested", - properties = new {} - } - } - } - } - }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- -## Automap with attributes -It is also possible to define your mappings using attributes on your POCOS. When you -use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. -Here we define the same two types but this time using attributes. - - -[source, csharp] ----- -[ElasticsearchType(Name = "company")] -public class CompanyWithAttributes -{ - [String(Analyzer = "keyword", NullValue = "null", Similarity = SimilarityOption.BM25)] - public string Name { get; set; } - - [String] - public TimeSpan? HeadOfficeHours { get; set; } - - [Object(Path = "employees", Store = false)] - public List Employees { get; set; } -} - -[ElasticsearchType(Name = "employee")] -public class EmployeeWithAttributes -{ - [String] - public string FirstName { get; set; } - - [String] - public string LastName { get; set; } - - [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)] - public int Salary { get; set; } - - [Date(Format = "MMddyyyy", NumericResolution = NumericResolutionUnit.Seconds)] - public DateTime Birthday { get; set; } - - [Boolean(NullValue = false, Store = true)] - public bool IsManager { get; set; } - - [Nested(Path = "employees")] - [JsonProperty("empl")] - public List Employees { get; set; } -} ----- - -Then map the types by calling `.AutoMap()` - - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap()) - .Map(m => m.AutoMap()) - ); -var expected = new - { - mappings = new - { - company = new - { - properties = new - { - employees = new - { - path = "employees", - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - store = false, - type = "object" - }, - name = new - { - analyzer = "keyword", - null_value = "null", - similarity = "BM25", - type = "string" - }, - headOfficeHours = new - { - type = "string" - } - } - }, - employee = new - { - properties = new - { - birthday = new - { - format = "MMddyyyy", - numeric_resolution = "seconds", - type = "date" - }, - empl = new - { - path = "employees", - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - type = "nested" - }, - firstName = new - { - type = "string" - }, - isManager = new - { - null_value = false, - store = true, - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - coerce = true, - doc_values = false, - ignore_malformed = true, - type = "double" - } - } - } - } - }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -Just as we were able to override the inferred properties in our earlier example, explicit (manual) -mappings also take precedence over attributes. Therefore we can also override any mappings applied -via any attributes defined on the POCO - - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - .Properties(ps => ps - .Nested(n => n - .Name(c => c.Employees) - ) - ) - ) - .Map(m => m - .AutoMap() - .TtlField(ttl => ttl - .Enable() - .Default("10m") - ) - .Properties(ps => ps - .String(s => s - .Name(e => e.FirstName) - .Fields(fs => fs - .String(ss => ss - .Name("firstNameRaw") - .Index(FieldIndexOption.NotAnalyzed) - ) - .TokenCount(t => t - .Name("length") - .Analyzer("standard") - ) - ) - ) - .Number(n => n - .Name(e => e.Salary) - .Type(NumberType.Double) - .IgnoreMalformed(false) - ) - .Date(d => d - .Name(e => e.Birthday) - .Format("MM-dd-yy") - ) - ) - ) - ); -var expected = new - { - mappings = new - { - company = new - { - properties = new - { - employees = new - { - type = "nested" - }, - name = new - { - analyzer = "keyword", - null_value = "null", - similarity = "BM25", - type = "string" - }, - headOfficeHours = new - { - type = "string" - } - } - }, - employee = new - { - _ttl = new - { - enabled = true, - @default = "10m" - }, - properties = new - { - birthday = new - { - format = "MM-dd-yy", - type = "date" - }, - empl = new - { - path = "employees", - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - type = "nested" - }, - firstName = new - { - fields = new - { - firstNameRaw = new - { - index = "not_analyzed", - type = "string" - }, - length = new - { - type = "token_count", - analyzer = "standard" - } - }, - type = "string" - }, - isManager = new - { - null_value = false, - store = true, - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - ignore_malformed = false, - type = "double" - } - } - } - } - }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- -== Ignoring Properties -Properties on a POCO can be ignored in a few ways: - -- Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO - -- Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings - -- Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` - -This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the -property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` - - -[source, csharp] ----- -[ElasticsearchType(Name = "company")] -public class CompanyWithAttributesAndPropertiesToIgnore -{ - public string Name { get; set; } - - [String(Ignore = true)] - public string PropertyToIgnore { get; set; } - - public string AnotherPropertyToIgnore { get; set; } - - [JsonIgnore] - public string JsonIgnoredProperty { get; set; } -} ----- -All of the properties except `Name` have been ignored in the mapping - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - ) - ); - -var expected = new - { - mappings = new - { - company = new - { - properties = new - { - name = new - { - type = "string" - } - } - } - } - }; -var settings = WithConnectionSettings(s => s - .InferMappingFor(i => i - .Ignore(p => p.AnotherPropertyToIgnore) - ) - ); -settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- -== Mapping Recursion -If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive -in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only -traverse a single depth when it encounters recursive instances like this. Hence, in the -previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. -This is done as a safe-guard to prevent stack overflows and all the fun that comes with -infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is -often an edge case to have deeply nested mappings like this. However, you may still have -the need to do this, so you can control the recursion depth of `.AutoMap()`. - -Let's introduce a very simple class, `A`, which itself has a property -Child of type `A`. - - -[source, csharp] ----- -public class A -{ - public A Child { get; set; } -} ----- -By default, `.AutoMap()` only goes as far as depth 1 - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap()) - ); ----- -Thus we do not map properties on the second occurrence of our Child property - -[source, csharp] ----- -var expected = new -{ - mappings = new - { - a = new - { - properties = new - { - child = new - { - properties = new { }, - type = "object" - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- -Now lets specify a maxRecursion of 3 - -[source, csharp] ----- -var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap(3)) - ); ----- -`.AutoMap()` has now mapped three levels of our Child property - -[source, csharp] ----- -var expectedWithMaxRecursion = new -{ - mappings = new - { - a = new - { - properties = new - { - child = new - { - type = "object", - properties = new - { - child = new - { - type = "object", - properties = new - { - child = new - { - type = "object", - properties = new - { - child = new - { - type = "object", - properties = new { } - } - } - } - } - } - } - } - } - } - } -}; - -Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); ----- -== Applying conventions through the Visitor pattern -It is also possible to apply a transformation on all or specific properties. - -AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, -does nothing and acts as a blank canvas for you to implement your own visiting methods. - -For instance, lets create a custom visitor that disables doc values for numeric and boolean types. -(Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) - - -[source, csharp] ----- -public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor -{ - // Override the Visit method on INumberProperty and set DocValues = false - public override void Visit(INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) - { - type.DocValues = false; - } - - // Similarily, override the Visit method on IBooleanProperty and set DocValues = false - public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) - { - type.DocValues = false; - } -} ----- -Now we can pass an instance of our custom visitor to `.AutoMap()` - -[source, csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) - ); ----- -and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) -it will apply the transformation defined in each Visit() respectively, which in this example -disables {ref_current}/doc-values.html[doc values]. - - -[source, csharp] ----- -var expected = new -{ - mappings = new - { - employee = new - { - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - isManager = new - { - doc_values = false, - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - doc_values = false, - type = "integer" - } - } - } - } -}; ----- -You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit -directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types -to an Elasticsearch string (`IStringProperty`). - - -[source, csharp] ----- -public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor -{ - public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); -} - -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap(new EverythingIsAStringPropertyVisitor())) - ); -var expected = new - { - mappings = new - { - employee = new - { - properties = new - { - birthday = new - { - type = "string" - }, - employees = new - { - type = "string" - }, - firstName = new - { - type = "string" - }, - isManager = new - { - type = "string" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "string" - } - } - } - } - }; ----- diff --git a/docs/asciidoc/bool_dsl.asciidoc b/docs/asciidoc/bool_dsl.asciidoc deleted file mode 100644 index 20ec761cb73..00000000000 --- a/docs/asciidoc/bool_dsl.asciidoc +++ /dev/null @@ -1,145 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Bool Queries - - -Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, -take a single `bool` query with only two clauses - - -[source, csharp] ----- -var searchResults = this.Client.Search(s => s - .Query(q => q - .Bool(b => b - .Should( - bs => bs.Term(p => p.Name, "x"), - bs => bs.Term(p => p.Name, "y") - ) - ) - ) - ); ----- -Now, magine multiple nested bools this quickly becomes an exercise in -_hadouken indenting_ - -[[indent]] -.hadouken indenting example -image::{imagesdir}/hadouken_indentation.jpg[dead indent] - -=== Operator Overloading -For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. -The previous example now becomes the following with the fluent API - - -[source, csharp] ----- -var searchResults = this.Client.Search(s => s - .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) - ); ----- -or, using the object initializer syntax - -[source, csharp] ----- -searchResults = this.Client.Search(new SearchRequest -{ - Query = new TermQuery { Field = "name", Value= "x" } - || new TermQuery { Field = Field(p=>p.Name), Value = "y" } -}); ----- -A naive implementation of operator overloading would rewrite - -`term && term && term` to - -> bool -> |___must -> |___term -> |___bool -> |___must -> |___term -> |___term - -As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and -join them together to become a single bool query - -> bool -> |___must -> |___term -> |___term -> |___term - - - -The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator - -And to mark a query as a `filter` using the `+` operator - -Both of these can be combined with `&&` to form a single bool query - -=== Combining/Merging bool queries - -When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query - -> bool -> |___must -> | |___term -> | |___term -> | |___term -> | -> |___must_not -> |___term - - -[source, csharp] ----- -Assert( - q => q.Query() && q.Query() && q.Query() && !q.Query(), - Query && Query && Query && !Query, - c=> - { - c.Bool.Must.Should().HaveCount(3); - c.Bool.MustNot.Should().HaveCount(1); - }); -c.Bool.Must.Should().HaveCount(3); -c.Bool.MustNot.Should().HaveCount(1); ----- -Even more involved `term && term && term && !term && +term && +term` still only results in a single bool query: - -> bool -> |___must -> | |___term -> | |___term -> | |___term -> | -> |___must_not -> | |___term -> | -> |___filter -> |___term -> |___term - - -You can still mix and match actual bool queries with the bool DSL e.g - -`bool(must=term, term, term) && !term` would still merge into a single bool query. - - -=== Locked bool queries -NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, -NEST will treat these as locked - -Here we demonstrate that two locked `bool` queries are not combined - - -neither are two `bool` queries where either the left or the right query is locked - -[source, csharp] ----- -c.Bool.Should.Should().HaveCount(2); -var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); -nestedBool.Bool.Should.Should().HaveCount(1); -nestedBool.Bool.Name.Should().Be(firstName); -assert(fluent.InvokeQuery(new QueryContainerDescriptor())); -assert((QueryContainer)ois); ----- diff --git a/docs/asciidoc/children_aggregation_mapping.asciidoc b/docs/asciidoc/children_aggregation_mapping.asciidoc deleted file mode 100644 index 45fe74e251c..00000000000 --- a/docs/asciidoc/children_aggregation_mapping.asciidoc +++ /dev/null @@ -1,18 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -To use the child aggregation you have to make sure -a `_parent` mapping is in place, here we create the project -index with two mapped types, `project` and `commitactivity` and -we add a `_parent` mapping from `commitactivity` to `parent` - -[source, csharp] ----- -var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c - .Mappings(map=>map - .Map(m=>m.AutoMap()) - .Map(m=>m - .Parent() - ) - ) -); ----- diff --git a/docs/asciidoc/connection_pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc similarity index 61% rename from docs/asciidoc/connection_pooling.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index e77ddcbb488..fb625e86b05 100644 --- a/docs/asciidoc/connection_pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -1,152 +1,177 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Connection Pooling -Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which -we can use to issue client calls on. - - -=== SingleNodeConnectionPool -The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls -It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always -ready to go. - - -[source, csharp] ----- -var uri = new Uri("http://localhost:9201"); -var pool = new SingleNodeConnectionPool(uri); -pool.Nodes.Should().HaveCount(1); -var node = pool.Nodes.First(); -node.Uri.Port.Should().Be(9201); ----- -This type of pool is hardwired to opt out of sniffing - -[source, csharp] ----- -pool.SupportsReseeding.Should().BeFalse(); ----- -and pinging - -[source, csharp] ----- -pool.SupportsPinging.Should().BeFalse(); ----- -When you use the low ceremony ElasticClient constructor that takes a single Uri, -We default to this SingleNodeConnectionPool - -[source, csharp] ----- -var client = new ElasticClient(uri); - -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -However we urge that you always pass your connection settings explicitly - -[source, csharp] ----- -client = new ElasticClient(new ConnectionSettings(uri)); - -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -or even better pass the connection pool explicitly - -[source, csharp] ----- -client = new ElasticClient(new ConnectionSettings(pool)); - -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -=== StaticConnectionPool -The static connection pool is great if you have a known small sized cluster and do no want to enable -sniffing to find out the cluster topology. - - -[source, csharp] ----- -var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ----- -a connection pool can be seeded using an enumerable of `Uri`s - -[source, csharp] ----- -var pool = new StaticConnectionPool(uris); ----- -Or using an enumerable of `Node` - -[source, csharp] ----- -var nodes = uris.Select(u=>new Node(u)); - -pool = new StaticConnectionPool(nodes); ----- -This type of pool is hardwired to opt out of sniffing - -[source, csharp] ----- -pool.SupportsReseeding.Should().BeFalse(); ----- -but supports pinging when enabled - -[source, csharp] ----- -pool.SupportsPinging.Should().BeTrue(); ----- -To create a client using this static connection pool pass -the connection pool to the connectionsettings you pass to ElasticClient - - -[source, csharp] ----- -var client = new ElasticClient(new ConnectionSettings(pool)); - -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- -=== SniffingConnectionPool -A subclass of StaticConnectionPool that allows itself to be reseeded at run time. -It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. - - -[source, csharp] ----- -var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ----- -a connection pool can be seeded using an enumerable of `Uri` - -[source, csharp] ----- -var pool = new SniffingConnectionPool(uris); ----- -Or using an enumerable of `Node` -A major benefit here is you can include known node roles when seeding -NEST can use this information to favour sniffing on master eligible nodes first -and take master only nodes out of rotation for issuing client calls on. - - -[source, csharp] ----- -var nodes = uris.Select(u=>new Node(u)); - -pool = new SniffingConnectionPool(nodes); ----- -This type of pool is hardwired to opt in to sniffing - -[source, csharp] ----- -pool.SupportsReseeding.Should().BeTrue(); ----- -and pinging - -[source, csharp] ----- -pool.SupportsPinging.Should().BeTrue(); ----- -To create a client using the sniffing connection pool pass -the connection pool to the connectionsettings you pass to ElasticClient - - -[source, csharp] ----- -var client = new ElasticClient(new ConnectionSettings(pool)); - -client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Connection Pooling + +Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which +NEST can use to issue client calls on. There are 3 types of connection pool + +* <> + +* <> + +* <> + +=== SingleNodeConnectionPool + +The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls +It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always +ready to go. + +[source,csharp] +---- +var uri = new Uri("http://localhost:9201"); +var pool = new SingleNodeConnectionPool(uri); +pool.Nodes.Should().HaveCount(1); +var node = pool.Nodes.First(); +node.Uri.Port.Should().Be(9201); +---- + +This type of pool is hardwired to opt out of sniffing + +[source,csharp] +---- +pool.SupportsReseeding.Should().BeFalse(); +---- + +and pinging + +[source,csharp] +---- +pool.SupportsPinging.Should().BeFalse(); +---- + +When you use the low ceremony `ElasticClient` constructor that takes a single `Uri`, +We default to using `SingleNodeConnectionPool` + +[source,csharp] +---- +var client = new ElasticClient(uri); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- + +However we urge that you always pass your connection settings explicitly + +[source,csharp] +---- +client = new ElasticClient(new ConnectionSettings(uri)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- + +or even better pass the connection pool explicitly + +[source,csharp] +---- +client = new ElasticClient(new ConnectionSettings(pool)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- + +=== StaticConnectionPool + +The static connection pool is great if you have a known small sized cluster and do no want to enable +sniffing to find out the cluster topology. + +[source,csharp] +---- +var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); +---- + +a connection pool can be seeded using an enumerable of `Uri`s + +[source,csharp] +---- +var pool = new StaticConnectionPool(uris); +---- + +Or using an enumerable of `Node`s + +[source,csharp] +---- +var nodes = uris.Select(u => new Node(u)); + +pool = new StaticConnectionPool(nodes); +---- + +This type of pool is hardwired to opt out of sniffing + +[source,csharp] +---- +pool.SupportsReseeding.Should().BeFalse(); +---- + +but supports pinging when enabled + +[source,csharp] +---- +pool.SupportsPinging.Should().BeTrue(); +---- + +To create a client using this static connection pool, pass +the connection pool to the `ConnectionSettings` you pass to `ElasticClient` + +[source,csharp] +---- +var client = new ElasticClient(new ConnectionSettings(pool)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- + +=== SniffingConnectionPool + +A subclass of `StaticConnectionPool` that allows itself to be reseeded at run time. +It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. + +[source,csharp] +---- +var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); +---- + +a connection pool can be seeded using an enumerable of `Uri` + +[source,csharp] +---- +var pool = new SniffingConnectionPool(uris); +---- + +Or using an enumerable of `Node`s. +A major benefit here is you can include known node roles when seeding and +NEST can use this information to favour sniffing on master eligible nodes first +and take master only nodes out of rotation for issuing client calls on. + +[source,csharp] +---- +var nodes = uris.Select(u=>new Node(u)); + +pool = new SniffingConnectionPool(nodes); +---- + +This type of pool is hardwired to opt in to sniffing + +[source,csharp] +---- +pool.SupportsReseeding.Should().BeTrue(); +---- + +and pinging + +[source,csharp] +---- +pool.SupportsPinging.Should().BeTrue(); +---- + +To create a client using the sniffing connection pool pass +the connection pool to the `ConnectionSettings` you pass to `ElasticClient` + +[source,csharp] +---- +var client = new ElasticClient(new ConnectionSettings(pool)); + +client.ConnectionSettings.ConnectionPool.Should().BeOfType(); +---- + diff --git a/docs/asciidoc/date_time_providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc similarity index 56% rename from docs/asciidoc/date_time_providers.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 96710d5b8d7..816983a8a94 100644 --- a/docs/asciidoc/date_time_providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -1,59 +1,60 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Date time providers - -Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` -in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover -in run time not being bound to wall clock time. - - -[source, csharp] ----- -var dateTimeProvider = DateTimeProvider.Default; ----- -dates are always returned in UTC - -[source, csharp] ----- -dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); ----- - -Another responsibility of this interface is to calculate the time a node has to be taken out of rotation -based on the number of attempts to revive it. For very advanced use cases, this might be something of interest -to provide a custom implementation for. - - -[source, csharp] ----- -var dateTimeProvider = DateTimeProvider.Default; ----- - -The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)` -The default values for `timeout` and `maxTimeout` are - - -[source, csharp] ----- -var timeout = TimeSpan.FromMinutes(1); - -var maxTimeout = TimeSpan.FromMinutes(30); ----- - -Plotting these defaults looks as followed: - -[[timeout]] -.Default formula, x-axis time in minutes, y-axis number of attempts to revive -image::{imagesdir}/timeoutplot.png[dead timeout] - -The goal here is that whenever a node is resurrected and is found to still be offline, we send it -_back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. - - -[source, csharp] ----- -var timeouts = Enumerable.Range(0, 30) - .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) - .ToList(); - -increasedTimeout.Should().BeWithin(maxTimeout); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Date time providers + +Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` +in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover +in run time not being bound to wall clock time. + +[source,csharp] +---- +var dateTimeProvider = DateTimeProvider.Default; +---- + +dates are always returned in UTC + +[source,csharp] +---- +dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); +---- + +Another responsibility of this interface is to calculate the time a node has to be taken out of rotation +based on the number of attempts to revive it. For very advanced use cases, this might be something of interest +to provide a custom implementation for. + +[source,csharp] +---- +var dateTimeProvider = DateTimeProvider.Default; +---- + +The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)` +The default values for `timeout` and `maxTimeout` are + +[source,csharp] +---- +var timeout = TimeSpan.FromMinutes(1); + +var maxTimeout = TimeSpan.FromMinutes(30); +---- + +Plotting these defaults looks as followed: + +[[timeout]] +.Default formula, x-axis time in minutes, y-axis number of attempts to revive +image::{imagesdir}/timeoutplot.png[dead timeout] +The goal here is that whenever a node is resurrected and is found to still be offline, we send it +_back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. + +[source,csharp] +---- +var timeouts = Enumerable.Range(0, 30) + .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) + .ToList(); + +increasedTimeout.Should().BeWithin(maxTimeout); +---- + diff --git a/docs/asciidoc/keeping_track_of_nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc similarity index 83% rename from docs/asciidoc/keeping_track_of_nodes.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 26f177a925f..142b58176f2 100644 --- a/docs/asciidoc/keeping_track_of_nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -1,96 +1,104 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Keeping track of nodes - - - -[source, csharp] ----- -var node = new Node(new Uri("http://localhost:9200")); -node.Uri.Should().NotBeNull(); -node.Uri.Port.Should().Be(9200); ----- -By default master eligible and holds data is presumed to be true - -[source, csharp] ----- -node.MasterEligible.Should().BeTrue(); - -node.HoldsData.Should().BeTrue(); ----- -Is resurrected is true on first usage, hints to the transport that a ping might be useful - -[source, csharp] ----- -node.IsResurrected.Should().BeTrue(); ----- -When instantiating your connection pool you could switch these to false to initialize the client to -a known cluster topology. - - -passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy - -[source, csharp] ----- -var node = new Node(new Uri("http://test.example/elasticsearch")); - -node.Uri.Port.Should().Be(80); -node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); ----- -We force paths to end with a forward slash so that they can later be safely combined - -[source, csharp] ----- -var combinedPath = new Uri(node.Uri, "index/type/_search"); - -combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); ----- -which is exactly what the `CreatePath` method does on `Node` - -[source, csharp] ----- -combinedPath = node.CreatePath("index/type/_search"); - -combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); -var node = new Node(new Uri("http://localhost:9200")); -node.FailedAttempts.Should().Be(0); -node.IsAlive.Should().BeTrue(); ----- - -every time a node is marked dead the number of attempts should increase -and the passed datetime should be exposed. - - -[source, csharp] ----- -var deadUntil = DateTime.Now.AddMinutes(1); -node.MarkDead(deadUntil); -node.FailedAttempts.Should().Be(i + 1); -node.IsAlive.Should().BeFalse(); -node.DeadUntil.Should().Be(deadUntil); ----- -however when marking a node alive deaduntil should be reset and attempts reset to 0 - -[source, csharp] ----- -node.MarkAlive(); - -node.FailedAttempts.Should().Be(0); -node.DeadUntil.Should().Be(default(DateTime)); -node.IsAlive.Should().BeTrue(); ----- -Nodes are considered equal if they have the same endpoint no matter what other metadata is associated - -[source, csharp] ----- -var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; - -var nodeAsMaster = new Node(new Uri("http://localhost:9200")) { MasterEligible = true }; -(node == nodeAsMaster).Should().BeTrue(); -(node != nodeAsMaster).Should().BeFalse(); -var uri = new Uri("http://localhost:9200"); -(node == uri).Should().BeTrue(); -var differentUri = new Uri("http://localhost:9201"); -(node != differentUri).Should().BeTrue(); -node.Should().Be(nodeAsMaster); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Keeping track of nodes + +[source,csharp] +---- +var node = new Node(new Uri("http://localhost:9200")); +node.Uri.Should().NotBeNull(); +node.Uri.Port.Should().Be(9200); +---- + +By default master eligible and holds data is presumed to be true + +[source,csharp] +---- +node.MasterEligible.Should().BeTrue(); + +node.HoldsData.Should().BeTrue(); +---- + +Is resurrected is true on first usage, hints to the transport that a ping might be useful + +[source,csharp] +---- +node.IsResurrected.Should().BeTrue(); +---- + +When instantiating your connection pool you could switch these to false to initialize the client to +a known cluster topology. + +passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy + +[source,csharp] +---- +var node = new Node(new Uri("http://test.example/elasticsearch")); + +node.Uri.Port.Should().Be(80); +node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); +---- + +We force paths to end with a forward slash so that they can later be safely combined + +[source,csharp] +---- +var combinedPath = new Uri(node.Uri, "index/type/_search"); + +combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); +---- + +which is exactly what the `CreatePath` method does on `Node` + +[source,csharp] +---- +combinedPath = node.CreatePath("index/type/_search"); + +combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); +var node = new Node(new Uri("http://localhost:9200")); +node.FailedAttempts.Should().Be(0); +node.IsAlive.Should().BeTrue(); +---- + +every time a node is marked dead the number of attempts should increase +and the passed datetime should be exposed. + +[source,csharp] +---- +var deadUntil = DateTime.Now.AddMinutes(1); +node.MarkDead(deadUntil); +node.FailedAttempts.Should().Be(i + 1); +node.IsAlive.Should().BeFalse(); +node.DeadUntil.Should().Be(deadUntil); +---- + +however when marking a node alive deaduntil should be reset and attempts reset to 0 + +[source,csharp] +---- +node.MarkAlive(); + +node.FailedAttempts.Should().Be(0); +node.DeadUntil.Should().Be(default(DateTime)); +node.IsAlive.Should().BeTrue(); +---- + +Nodes are considered equal if they have the same endpoint no matter what other metadata is associated + +[source,csharp] +---- +var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; + +var nodeAsMaster = new Node(new Uri("http://localhost:9200")) { MasterEligible = true }; +(node == nodeAsMaster).Should().BeTrue(); +(node != nodeAsMaster).Should().BeFalse(); +var uri = new Uri("http://localhost:9200"); +(node == uri).Should().BeTrue(); +var differentUri = new Uri("http://localhost:9201"); +(node != differentUri).Should().BeTrue(); +node.Should().Be(nodeAsMaster); +---- + diff --git a/docs/asciidoc/request_pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc similarity index 88% rename from docs/asciidoc/request_pipelines.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 119366843dc..5da5cb7b29e 100644 --- a/docs/asciidoc/request_pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -1,26 +1,32 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ -== Request pipeline +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ -Every request is executed in the context of a `RequestPipeline` when using the -default `ITransport` implementation. +== Request pipeline + * + * Every request is executed in the context of a `RequestPipeline` when using the + default `ITransport` implementation. -[source, csharp] +[source,csharp] ---- var settings = TestClient.CreateSettings(); ---- + When calling Request/RequestAsync on Transport the whole coordination of the request is deferred to a new instance in a `using` block. -[source, csharp] +[source,csharp] ---- var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); pipeline.GetType().Should().Implement(); ---- + However the transport does not instantiate RequestPipeline directly, it uses a pluggable `IRequestPipelineFactory` -[source, csharp] +[source,csharp] ---- var requestPipelineFactory = new RequestPipelineFactory(); @@ -28,15 +34,17 @@ var requestPipeline = requestPipelineFactory.Create(settings, DateTimeProvider.D requestPipeline.Should().BeOfType(); requestPipeline.GetType().Should().Implement(); ---- + which can be passed to the transport when instantiating a client -[source, csharp] +[source,csharp] ---- var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); ---- + this allows you to have requests executed on your own custom request pipeline -[source, csharp] +[source,csharp] ---- var pool = setupPool(new[] { TestClient.CreateNode(), TestClient.CreateNode(9201) }); var settings = new ConnectionSettings(pool, TestClient.CreateConnection()); @@ -45,20 +53,21 @@ var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uri var staticPipeline = CreatePipeline(uris => new StaticConnectionPool(uris)); var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris)); ---- + Here we have setup three pipelines using three different connection pools, lets see how they behave -[source, csharp] +[source,csharp] ---- singleNodePipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); staticPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeTrue(); ---- -Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() -You can however disable this on ConnectionSettings +Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() + You can however disable this on ConnectionSettings -[source, csharp] +[source,csharp] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnStartup(false)); @@ -70,11 +79,11 @@ singleNodePipeline.SniffsOnConnectionFailure.Should().BeFalse(); staticPipeline.SniffsOnConnectionFailure.Should().BeFalse(); sniffingPipeline.SniffsOnConnectionFailure.Should().BeTrue(); ---- -Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() -You can however disable this on ConnectionSettings +Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() + You can however disable this on ConnectionSettings -[source, csharp] +[source,csharp] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnConnectionFault(false)); @@ -90,31 +99,34 @@ singleNodePipeline.StaleClusterState.Should().BeFalse(); staticPipeline.StaleClusterState.Should().BeFalse(); sniffingPipeline.StaleClusterState.Should().BeFalse(); ---- + go one hour into the future -[source, csharp] +[source,csharp] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- + connection pools that do not support reseeding never go stale -[source, csharp] +[source,csharp] ---- singleNodePipeline.StaleClusterState.Should().BeFalse(); staticPipeline.StaleClusterState.Should().BeFalse(); ---- + the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source, csharp] +[source,csharp] ---- sniffingPipeline.StaleClusterState.Should().BeTrue(); ---- -A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout -See the maxretry documentation for more details, here we assert that our request pipeline exposes this propertly +A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout + See the maxretry documentation for more details, here we assert that our request pipeline exposes this propertly -[source, csharp] +[source,csharp] ---- var dateTime = new TestableDateTimeProvider(); var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First(), dateTime), dateTimeProvider: dateTime); @@ -124,29 +136,33 @@ singleNodePipeline.IsTakingTooLong.Should().BeFalse(); staticPipeline.IsTakingTooLong.Should().BeFalse(); sniffingPipeline.IsTakingTooLong.Should().BeFalse(); ---- + go one hour into the future -[source, csharp] +[source,csharp] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- + connection pools that do not support reseeding never go stale -[source, csharp] +[source,csharp] ---- singleNodePipeline.IsTakingTooLong.Should().BeTrue(); staticPipeline.IsTakingTooLong.Should().BeTrue(); ---- + the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source, csharp] +[source,csharp] ---- sniffingPipeline.IsTakingTooLong.Should().BeTrue(); ---- + request pipeline exposes the DateTime it started, here we assert it started 2 hours in the past -[source, csharp] +[source,csharp] ---- (dateTime.Now() - singleNodePipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); @@ -156,3 +172,4 @@ var dateTime = new TestableDateTimeProvider(); var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime) as RequestPipeline; sniffingPipeline.SniffPath.Should().Be("_nodes/_all/settings?flat_settings&timeout=2s"); ---- + diff --git a/docs/asciidoc/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc similarity index 77% rename from docs/asciidoc/transports.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index f70933bdff8..c945d20d8e4 100644 --- a/docs/asciidoc/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -1,41 +1,43 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Transports - -The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. -It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote -the internals of the client, by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. - - - -Transport is generically typed to a type that implements IConnectionConfigurationValues -This is the minimum ITransport needs to report back for the client to function. - -e.g in the low level client, transport is instantiated like this: - - -[source, csharp] ----- -var lowLevelTransport = new Transport(new ConnectionConfiguration()); ----- -and in the high level client, like this: - -[source, csharp] ----- -var highlevelTransport = new Transport(new ConnectionSettings()); - -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var inMemoryTransport = new Transport(new ConnectionSettings(connectionPool, new InMemoryConnection())); ----- - -The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the default `ITransport` implementation is responsible for introducing -many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. -If you feel this need, please let us know as we'd love to learn why you've go down this route! - - -[source, csharp] ----- -var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); - -response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Transports + +The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. +It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote +the internals of the client, by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. + +Transport is generically typed to a type that implements IConnectionConfigurationValues +This is the minimum ITransport needs to report back for the client to function. + +e.g in the low level client, transport is instantiated like this: + +[source,csharp] +---- +var lowLevelTransport = new Transport(new ConnectionConfiguration()); +---- + +and in the high level client, like this: + +[source,csharp] +---- +var highlevelTransport = new Transport(new ConnectionSettings()); + +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var inMemoryTransport = new Transport(new ConnectionSettings(connectionPool, new InMemoryConnection())); +---- + +The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the default `ITransport` implementation is responsible for introducing +many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. +If you feel this need, please let us know as we'd love to learn why you've go down this route! + +[source,csharp] +---- +var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); + +response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); +---- + diff --git a/docs/asciidoc/unexpected_exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc similarity index 51% rename from docs/asciidoc/unexpected_exceptions.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index 71921521717..25611735389 100644 --- a/docs/asciidoc/unexpected_exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -1,114 +1,117 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Unexpected exceptions -When a client call throws an exception that the IConnction can not handle, this exception will bubble -out the client as an UnexpectedElasticsearchClientException, regardless whether the client is configured to throw or not. -An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and -will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { AuditEvent.HealthyResponse, 9200 }, - } - ); -audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); - e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); - } - ); -e.FailureReason.Should().Be(PipelineFailure.Unexpected); -e.InnerException.Should().NotBeNull(); -e.InnerException.Message.Should().Be("boom!"); ----- - -Sometimes an unexpected exception happens further down in the pipeline, this is why we -wrap them inside an UnexpectedElasticsearchClientException so that information about where -in the pipeline the unexpected exception is not lost, here a call to 9200 fails using a webexception. -It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we -can still see the audit trail for the whole coordinated request. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) -#if DOTNETCORE - .ClientCalls(r => r.OnPort(9200).FailAlways(new System.Net.Http.HttpRequestException("recover"))) -#else - .ClientCalls(r => r.OnPort(9200).FailAlways(new WebException("recover"))) -#endif - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.BadResponse, 9200 }, - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); - e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); - } - ); -e.FailureReason.Should().Be(PipelineFailure.Unexpected); -e.InnerException.Should().NotBeNull(); -e.InnerException.Message.Should().Be("boom!"); ----- - -An unexpected hard exception on ping and sniff is something we *do* try to revover from and failover. -Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. -However the client call on 9201 throws a hard exception we can not recover from - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(r => r.OnPort(9200).FailAlways(new Exception("ping exception"))) - .Ping(r => r.OnPort(9201).SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .AllDefaults() - ); - -audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.PingFailure, 9200 }, - { AuditEvent.PingSuccess, 9201 }, - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); -e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); -e.SeenExceptions.Should().NotBeEmpty(); - var pipelineException = e.SeenExceptions.First(); - pipelineException.FailureReason.Should().Be(PipelineFailure.PingFailure); - pipelineException.InnerException.Message.Should().Be("ping exception"); -var pingException = e.AuditTrail.First(a => a.Event == AuditEvent.PingFailure).Exception; - pingException.Should().NotBeNull(); - pingException.Message.Should().Be("ping exception"); - - } -); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Unexpected exceptions + +When a client call throws an exception that the IConnction can not handle, this exception will bubble +out the client as an UnexpectedElasticsearchClientException, regardless whether the client is configured to throw or not. +An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and +will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall { + { AuditEvent.HealthyResponse, 9200 }, + } +); +audit = await audit.TraceUnexpectedException( + new ClientCall { + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); + } +); +e.FailureReason.Should().Be(PipelineFailure.Unexpected); +e.InnerException.Should().NotBeNull(); +e.InnerException.Message.Should().Be("boom!"); +---- + +Sometimes an unexpected exception happens further down in the pipeline, this is why we +wrap them inside an UnexpectedElasticsearchClientException so that information about where +in the pipeline the unexpected exception is not lost, here a call to 9200 fails using a webexception. +It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we +can still see the audit trail for the whole coordinated request. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) +#if DOTNETCORE + .ClientCalls(r => r.OnPort(9200).FailAlways(new System.Net.Http.HttpRequestException("recover"))) +#else + .ClientCalls(r => r.OnPort(9200).FailAlways(new WebException("recover"))) +#endif + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceUnexpectedException( + new ClientCall { + { AuditEvent.BadResponse, 9200 }, + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); + } +); +e.FailureReason.Should().Be(PipelineFailure.Unexpected); +e.InnerException.Should().NotBeNull(); +e.InnerException.Message.Should().Be("boom!"); +---- + +An unexpected hard exception on ping and sniff is something we *do* try to revover from and failover. +Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. +However the client call on 9201 throws a hard exception we can not recover from + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.OnPort(9200).FailAlways(new Exception("ping exception"))) + .Ping(r => r.OnPort(9201).SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .AllDefaults() +); + +audit = await audit.TraceUnexpectedException( + new ClientCall { + { AuditEvent.PingFailure, 9200 }, + { AuditEvent.PingSuccess, 9201 }, + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); +e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); +e.SeenExceptions.Should().NotBeEmpty(); + var pipelineException = e.SeenExceptions.First(); + pipelineException.FailureReason.Should().Be(PipelineFailure.PingFailure); + pipelineException.InnerException.Message.Should().Be("ping exception"); +var pingException = e.AuditTrail.First(a => a.Event == AuditEvent.PingFailure).Exception; + pingException.Should().NotBeNull(); + pingException.Message.Should().Be("ping exception"); + + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc new file mode 100644 index 00000000000..fc6a834aaf0 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -0,0 +1,51 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Unrecoverable exceptions + +Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. +By default the client won't throw on any ElasticsearchClientException but return an invalid response. +You can configure the client to throw using ThrowExceptions() on ConnectionSettings. The following test +both a client that throws and one that returns an invalid response with an `.OriginalException` exposed + +[source,csharp] +---- +var recoverablExceptions = new[] +{ + new PipelineException(PipelineFailure.BadResponse), + new PipelineException(PipelineFailure.PingFailure), +}; +recoverablExceptions.Should().OnlyContain(e => e.Recoverable); +var unrecoverableExceptions = new[] +{ + new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), + new PipelineException(PipelineFailure.SniffFailure), + new PipelineException(PipelineFailure.Unexpected), + new PipelineException(PipelineFailure.BadAuthentication), + new PipelineException(PipelineFailure.MaxRetriesReached), + new PipelineException(PipelineFailure.MaxTimeoutReached) +}; +unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.SucceedAlways()) + .ClientCalls(r => r.FailAlways(401)) + .StaticConnectionPool() + .AllDefaults() +); +audit = await audit.TraceElasticsearchException( + new ClientCall { + { AuditEvent.PingSuccess, 9200 }, + { AuditEvent.BadResponse, 9200 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + } +); +e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc new file mode 100644 index 00000000000..27a368fa892 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -0,0 +1,88 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Fail over + +When using connection pooling and the pool has sufficient nodes a request will be retried if +the call to a node throws an exception or returns a 502 or 503 + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } +); +---- + +=== 502 Bad Gateway + +Will be treated as an error that requires retrying + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(502)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } +); +---- + +=== 503 Service Unavailable + +Will be treated as an error that requires retrying + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(503)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } +); +---- + +If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(418)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc new file mode 100644 index 00000000000..e5e7c5b60b5 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -0,0 +1,148 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== MaxRetries + +By default retry as many times as we have nodes. However retries still respect the request timeout. +Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can +but give up after 20 seconds + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 } + } +); +---- + +When you have a 100 node cluster you might want to ensure a fixed number of retries. +Remember that the actual number of requests is initial attempt + set number of retries + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(3)) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { MaxRetriesReached } + } +); +---- + +In our previous test we simulated very fast failures, in the real world a call might take upwards of a second +Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. +In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxTimeoutReached } + } +); +---- + +If you set smaller request time outs you might not want it to also affect the retry timeout, therefor you can configure these separately too. +Here we simulate calls taking 3 seconds, a request time out of 2 and an overall retry timeout of 10 seconds. +We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 +wins over the configured request timeout + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { MaxTimeoutReached } + } +); +---- + +If your retry policy expands beyond available nodes we won't retry the same node twice + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(2) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxRetriesReached } + } +); +---- + +This makes setting any retry setting on a single node connection pool a NOOP, this is by design! +Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and +not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .SingleNodeConnection() + .Settings(s => s.DisablePing().MaximumRetries(10)) +); +audit = await audit.TraceCall( + new ClientCall { + { BadResponse, 9200 } + } +); +---- + diff --git a/docs/asciidoc/first_usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc similarity index 66% rename from docs/asciidoc/first_usage.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index 960244331a1..50a067de8ad 100644 --- a/docs/asciidoc/first_usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -1,110 +1,118 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Pinging - First Usage - -Pinging is enabled by default for the Static & Sniffing connection pool. -This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. -This allows us to fail and fallover to a healthy node faster - - -A cluster with 2 nodes where the second node fails on ping - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(2) - .Ping(p => p.Succeeds(Always)) - .Ping(p => p.OnPort(9201).FailAlways()) - .StaticConnectionPool() - .AllDefaults() -); ----- -The first call goes to 9200 which succeeds - -The 2nd call does a ping on 9201 because its used for the first time. -It fails so we wrap over to node 9200 which we've already pinged - -Finally we assert that the connectionpool has one node that is marked as dead - -[source, csharp] ----- -await audit.TraceCalls( -new ClientCall { - { PingSuccess, 9200}, - { HealthyResponse, 9200}, - { pool => - { - pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); - } } - }, -new ClientCall { - { PingFailure, 9201}, - { HealthyResponse, 9200}, -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - } -); ----- -A cluster with 4 nodes where the second and third pings fail - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .Ping(p => p.SucceedAlways()) - .Ping(p => p.OnPort(9201).FailAlways()) - .Ping(p => p.OnPort(9202).FailAlways()) - .StaticConnectionPool() - .AllDefaults() -); ----- -The first call goes to 9200 which succeeds - -The 2nd call does a ping on 9201 because its used for the first time. -It fails and so we ping 9202 which also fails. We then ping 9203 becuase -we haven't used it before and it succeeds - -Finally we assert that the connectionpool has two nodes that are marked as dead - -[source, csharp] ----- -await audit.TraceCalls( -new ClientCall { - { PingSuccess, 9200}, - { HealthyResponse, 9200}, - { pool => - { - pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); - } } - }, -new ClientCall { - { PingFailure, 9201}, - { PingFailure, 9202}, - { PingSuccess, 9203}, - { HealthyResponse, 9203}, -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - } -); ----- -A healthy cluster of 4 (min master nodes of 3 of course!) - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .Ping(p => p.SucceedAlways()) - .StaticConnectionPool() - .AllDefaults() -); - -await audit.TraceCalls( - new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }, - new ClientCall { { PingSuccess, 9201}, { HealthyResponse, 9201} }, - new ClientCall { { PingSuccess, 9202}, { HealthyResponse, 9202} }, - new ClientCall { { PingSuccess, 9203}, { HealthyResponse, 9203} }, - new ClientCall { { HealthyResponse, 9200} }, - new ClientCall { { HealthyResponse, 9201} }, - new ClientCall { { HealthyResponse, 9202} }, - new ClientCall { { HealthyResponse, 9203} }, - new ClientCall { { HealthyResponse, 9200} } - ); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Pinging - First Usage + +Pinging is enabled by default for the Static & Sniffing connection pool. +This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. +This allows us to fail and fallover to a healthy node faster + +A cluster with 2 nodes where the second node fails on ping + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(2) + .Ping(p => p.Succeeds(Always)) + .Ping(p => p.OnPort(9201).FailAlways()) + .StaticConnectionPool() + .AllDefaults() +); +---- + +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails so we wrap over to node 9200 which we've already pinged + +Finally we assert that the connectionpool has one node that is marked as dead + +[source,csharp] +---- +await audit.TraceCalls( +new ClientCall { + { PingSuccess, 9200}, + { HealthyResponse, 9200}, + { pool => + { + pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); + } } + }, +new ClientCall { + { PingFailure, 9201}, + { HealthyResponse, 9200}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + } +); +---- + +A cluster with 4 nodes where the second and third pings fail + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .Ping(p => p.SucceedAlways()) + .Ping(p => p.OnPort(9201).FailAlways()) + .Ping(p => p.OnPort(9202).FailAlways()) + .StaticConnectionPool() + .AllDefaults() +); +---- + +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails and so we ping 9202 which also fails. We then ping 9203 becuase +we haven't used it before and it succeeds + +Finally we assert that the connectionpool has two nodes that are marked as dead + +[source,csharp] +---- +await audit.TraceCalls( +new ClientCall { + { PingSuccess, 9200}, + { HealthyResponse, 9200}, + { pool => + { + pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); + } } + }, +new ClientCall { + { PingFailure, 9201}, + { PingFailure, 9202}, + { PingSuccess, 9203}, + { HealthyResponse, 9203}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + } +); +---- + + A healthy cluster of 4 (min master nodes of 3 of course!) + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .Ping(p => p.SucceedAlways()) + .StaticConnectionPool() + .AllDefaults() +); + +await audit.TraceCalls( + new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }, + new ClientCall { { PingSuccess, 9201}, { HealthyResponse, 9201} }, + new ClientCall { { PingSuccess, 9202}, { HealthyResponse, 9202} }, + new ClientCall { { PingSuccess, 9203}, { HealthyResponse, 9203} }, + new ClientCall { { HealthyResponse, 9200} }, + new ClientCall { { HealthyResponse, 9201} }, + new ClientCall { { HealthyResponse, 9202} }, + new ClientCall { { HealthyResponse, 9203} }, + new ClientCall { { HealthyResponse, 9200} } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc new file mode 100644 index 00000000000..cee8a500461 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -0,0 +1,54 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Pinging - Revival + +When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping +before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(3) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9202).Fails(Once)) + .Ping(p => p.SucceedAlways()) + .StaticConnectionPool() + .AllDefaults() +); +audit = await audit.TraceCalls( + new ClientCall { { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, + new ClientCall { { PingSuccess, 9201 }, { HealthyResponse, 9201 } }, + new ClientCall { + { PingSuccess, 9202}, + { BadResponse, 9202}, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.First(n=>!n.IsAlive).DeadUntil.Should().BeAfter(DateTime.UtcNow) } + } +); +audit = await audit.TraceCalls( + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } } +); +audit.ChangeTime(d => d.AddMinutes(20)); +audit = await audit.TraceCalls( + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { + { Resurrection, 9202 }, + { PingSuccess, 9202 }, + { HealthyResponse, 9202 } + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc new file mode 100644 index 00000000000..40646d0abdc --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -0,0 +1,78 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Disabling sniffing and pinging on a request basis + +Even if you are using a sniffing connection pool thats set up to sniff on start/failure +and pinging enabled, you can opt out of this behaviour on a per request basis + +In our first test we set up a cluster that pings and sniffs on startup +but we disable the sniffing on our first request so we only see the ping and the response + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) +); +---- + +We disable sniffing so eventhoug its our first call we do not want to sniff on startup + +Instead the sniff on startup is deffered to the second call into the cluster that +does not disable sniffing on a per request basis + +And after that no sniff on startup will happen again + +[source,csharp] +---- +audit = await audit.TraceCalls( +new ClientCall(r=>r.DisableSniffing()) { + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, +new ClientCall() + { + { SniffOnStartup }, + { SniffSuccess, 9200 }, + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, +new ClientCall() + { + { PingSuccess, 9201 }, + { HealthyResponse, 9201 } + } + ); + +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) +); +audit = await audit.TraceCall( + new ClientCall(r=>r.DisablePing()) { + { SniffOnStartup }, + { SniffSuccess, 9200 }, + { HealthyResponse, 9200 } + } + ); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) +); +audit = await audit.TraceCall( + new ClientCall(r=>r.DisableSniffing().DisablePing()) { + { HealthyResponse, 9200 } + } + ); +---- + diff --git a/docs/asciidoc/request_timeouts_overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc similarity index 79% rename from docs/asciidoc/request_timeouts_overrides.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index a4284d4860a..5facc37443c 100644 --- a/docs/asciidoc/request_timeouts_overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -1,95 +1,94 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Request Timeouts - -While you can specify Request time out globally you can override this per request too - - -we set up a 10 node cluster with a global time out of 20 seconds. -Each call on a node takes 10 seconds. So we can only try this call on 2 nodes -before the max request time out kills the client call. - - -[source, csharp] ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Request Timeouts + +While you can specify Request time out globally you can override this per request too + +we set up a 10 node cluster with a global time out of 20 seconds. +Each call on a node takes 10 seconds. So we can only try this call on 2 nodes +before the max request time out kills the client call. + +[source,csharp] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) .ClientCalls(r => r.OnPort(9209).SucceedAlways()) .StaticConnectionPool() .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) -); ----- - -On the second request we specify a request timeout override to 60 seconds -We should now see more nodes being tried. - - -[source, csharp] ----- +); +---- + +On the second request we specify a request timeout override to 60 seconds +We should now see more nodes being tried. + +[source,csharp] +---- audit = await audit.TraceCalls( new ClientCall { { BadResponse, 9200 }, - { BadResponse, 9201 }, + { BadResponse, 9201 }, { MaxTimeoutReached } - }, -new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) - { - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { BadResponse, 9205 }, - { BadResponse, 9206 }, - { BadResponse, 9207 }, - { BadResponse, 9208 }, - { HealthyResponse, 9209 }, - } -); ----- -== Connect Timeouts -Connect timeouts can be overridden, webrequest/httpclient can not distinguish connect and retry timeouts however -we use this separate configuration value for ping requests. - - -we set up a 10 node cluster with a global time out of 20 seconds. -Each call on a node takes 10 seconds. So we can only try this call on 2 nodes -before the max request time out kills the client call. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) - .ClientCalls(r => r.SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) -); ----- - -The first call uses the configured global settings, request times out after 10 seconds and ping -calls always take 20, so we should see a single ping failure - - - -On the second request we set a request ping timeout override of 2seconds -We should now see more nodes being tried before the request timeout is hit. - - -[source, csharp] ----- -audit = await audit.TraceCalls( -new ClientCall { - { PingFailure, 9200 }, - { MaxTimeoutReached } - }, -new ClientCall(r => r.PingTimeout(TimeSpan.FromSeconds(2))) - { - { PingFailure, 9202 }, - { PingFailure, 9203 }, - { PingFailure, 9204 }, - { PingFailure, 9205 }, - { PingFailure, 9206 }, - { MaxTimeoutReached } - } -); ----- + }, +new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) + { + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 }, + } +); +---- + +== Connect Timeouts + +Connect timeouts can be overridden, webrequest/httpclient can not distinguish connect and retry timeouts however +we use this separate configuration value for ping requests. + +we set up a 10 node cluster with a global time out of 20 seconds. +Each call on a node takes 10 seconds. So we can only try this call on 2 nodes +before the max request time out kills the client call. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) + .ClientCalls(r => r.SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) +); +---- + +The first call uses the configured global settings, request times out after 10 seconds and ping +calls always take 20, so we should see a single ping failure + +On the second request we set a request ping timeout override of 2seconds +We should now see more nodes being tried before the request timeout is hit. + +[source,csharp] +---- +audit = await audit.TraceCalls( +new ClientCall { + { PingFailure, 9200 }, + { MaxTimeoutReached } + }, +new ClientCall(r => r.PingTimeout(TimeSpan.FromSeconds(2))) + { + { PingFailure, 9202 }, + { PingFailure, 9203 }, + { PingFailure, 9204 }, + { PingFailure, 9205 }, + { PingFailure, 9206 }, + { MaxTimeoutReached } + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc new file mode 100644 index 00000000000..f78b9ff4d56 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -0,0 +1,26 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Allowed status codes + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways(400)) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(0)) +); +audit = await audit.TraceCalls( + new ClientCall() { + { BadResponse, 9200 } + }, + new ClientCall(r => r.AllowedStatusCodes(400)) { + { HealthyResponse, 9201 } + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc new file mode 100644 index 00000000000..2edb99c9108 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -0,0 +1,27 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Forcing nodes + +Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` +request configuration. This will ignore the pool and not retry. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9208).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { + { BadResponse, 9208 } + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc new file mode 100644 index 00000000000..d6c4f750abb --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -0,0 +1,73 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Maximum Retries + +By default retry as many times as we have nodes. However retries still respect the request timeout. +Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can +but give up after 20 seconds + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) +); +audit = await audit.TraceCall( + new ClientCall(r => r.MaxRetries(2)) { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { MaxRetriesReached } + } +); +---- + +When you have a 100 node cluster you might want to ensure a fixed number of retries. +Remember that the actual number of requests is initial attempt + set number of retries + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(5)) +); +audit = await audit.TraceCall( + new ClientCall(r => r.MaxRetries(2)) { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { MaxRetriesReached } + } +); +---- + +This makes setting any retry setting on a single node connection pool a NOOP, this is by design! +Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and +not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .SingleNodeConnection() + .Settings(s => s.DisablePing().MaximumRetries(10)) +); +audit = await audit.TraceCall( + new ClientCall(r => r.MaxRetries(10)) { + { BadResponse, 9200 } + } +); +---- + diff --git a/docs/asciidoc/round_robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc similarity index 60% rename from docs/asciidoc/round_robin.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index da10d7e09ed..90545f2690c 100644 --- a/docs/asciidoc/round_robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -1,73 +1,76 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -Round Robin -Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. - - -== GetNext -GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance -over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without -suffering from noisy neighboors advancing a global cursor. - - -[source, csharp] ----- -var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); -var staticPool = new StaticConnectionPool(uris, randomize: false); -var sniffingPool = new SniffingConnectionPool(uris, randomize: false); -this.AssertCreateView(staticPool); -this.AssertCreateView(sniffingPool); ----- - -Here we have setup a static connection pool seeded with 10 nodes. We force randomizationOnStartup to false -so that we can test the nodes being returned are int the order we expect them to. -So what order we expect? Imagine the following: - -Thread A calls GetNext first without a local cursor and takes the current from the internal global cursor which is 0. -Thread B calls GetNext() second without a local cursor and therefor starts at 1. -After this each thread should walk the nodes in successive order using their local cursor -e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. - - -[source, csharp] ----- -var startingPositions = Enumerable.Range(0, NumberOfNodes) - .Select(i => pool.CreateView().First()) - .Select(n => n.Uri.Port) - .ToList(); - -var expectedOrder = Enumerable.Range(9200, NumberOfNodes); -startingPositions.Should().ContainInOrder(expectedOrder); ----- - -What the above code just proved is that each call to GetNext(null) gets assigned the next available node. - -Lets up the ante: -- call get next over `NumberOfNodes * 2` threads -- on each thread call getnext `NumberOfNodes * 10` times using a local cursor. -We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 -comes 9200 again - - -[source, csharp] ----- -var threadedStartPositions = new ConcurrentBag(); - -var threads = Enumerable.Range(0, 20) - .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) - .ToList(); -t.Start(); -t.Join(); ----- - -Each thread reported the first node it started off lets make sure we see each node twice as the first node -because we started `NumberOfNodes * 2` threads - - -[source, csharp] ----- -var grouped = threadedStartPositions.GroupBy(p => p).ToList(); - -grouped.Count().Should().Be(NumberOfNodes); -grouped.Select(p => p.Count()).Should().OnlyContain(p => p == 2); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +Round Robin +Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. + +== GetNext + +GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance +over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without +suffering from noisy neighboors advancing a global cursor. + +[source,csharp] +---- +var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); +var staticPool = new StaticConnectionPool(uris, randomize: false); +var sniffingPool = new SniffingConnectionPool(uris, randomize: false); +this.AssertCreateView(staticPool); +this.AssertCreateView(sniffingPool); +---- + +Here we have setup a static connection pool seeded with 10 nodes. We force randomizationOnStartup to false +so that we can test the nodes being returned are int the order we expect them to. +So what order we expect? Imagine the following: + +Thread A calls GetNext first without a local cursor and takes the current from the internal global cursor which is 0. +Thread B calls GetNext() second without a local cursor and therefor starts at 1. +After this each thread should walk the nodes in successive order using their local cursor +e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. + +[source,csharp] +---- +var startingPositions = Enumerable.Range(0, NumberOfNodes) + .Select(i => pool.CreateView().First()) + .Select(n => n.Uri.Port) + .ToList(); + +var expectedOrder = Enumerable.Range(9200, NumberOfNodes); +startingPositions.Should().ContainInOrder(expectedOrder); +---- + +What the above code just proved is that each call to GetNext(null) gets assigned the next available node. + +Lets up the ante: + +* call get next over `NumberOfNodes * 2` threads + +* on each thread call getnext `NumberOfNodes * 10` times using a local cursor. +We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 +comes 9200 again + +[source,csharp] +---- +var threadedStartPositions = new ConcurrentBag(); + +var threads = Enumerable.Range(0, 20) + .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) + .ToList(); +t.Start(); +t.Join(); +---- + +Each thread reported the first node it started off lets make sure we see each node twice as the first node +because we started `NumberOfNodes * 2` threads + +[source,csharp] +---- +var grouped = threadedStartPositions.GroupBy(p => p).ToList(); + +grouped.Count().Should().Be(NumberOfNodes); +grouped.Select(p => p.Count()).Should().OnlyContain(p => p == 2); +---- + diff --git a/docs/asciidoc/skip_dead_nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc similarity index 87% rename from docs/asciidoc/skip_dead_nodes.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 0cbe619ea0e..96f2b678fe6 100644 --- a/docs/asciidoc/skip_dead_nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -1,178 +1,187 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Round Robin - Skipping Dead Nodes - -When selecting nodes the connection pool will try and skip all the nodes that are marked dead. - - -=== GetNext -GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance -over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without -suffering from noisy neighboors advancing a global cursor. - - -[source, csharp] ----- -var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -var pool = new StaticConnectionPool(seeds, randomize: false); -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9200); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); -var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -seeds.First().MarkDead(DateTime.Now.AddDays(1)); -var pool = new StaticConnectionPool(seeds, randomize: false); -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); ----- -After we marked the first node alive again, we expect it to be hit again - -[source, csharp] ----- -seeds.First().MarkAlive(); - -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9200); -var dateTimeProvider = new TestableDateTimeProvider(); -var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -seeds.First().MarkDead(dateTimeProvider.Now().AddDays(1)); -var pool = new StaticConnectionPool(seeds, randomize: false, dateTimeProvider: dateTimeProvider); -var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9201); -node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9202); ----- -If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected - -[source, csharp] ----- -dateTimeProvider.ChangeTime(d => d.AddDays(2)); - -var n = pool.CreateView().First(); -n.Uri.Port.Should().Be(9201); -n = pool.CreateView().First(); -n.Uri.Port.Should().Be(9202); -n = pool.CreateView().First(); -n.Uri.Port.Should().Be(9200); -n.IsResurrected.Should().BeTrue(); ----- -A cluster with 2 nodes where the second node fails on ping - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .ClientCalls(p => p.Succeeds(Always)) - .ClientCalls(p => p.OnPort(9201).FailAlways()) - .ClientCalls(p => p.OnPort(9203).FailAlways()) - .StaticConnectionPool() - .Settings(p=>p.DisablePing()) -); ----- -The first call goes to 9200 which succeeds - -The 2nd call does a ping on 9201 because its used for the first time. -It fails so we wrap over to node 9202 - -Finally we assert that the connectionpool has one node that is marked as dead - -The next call goes to 9203 which fails so we should wrap over - -[source, csharp] ----- -await audit.TraceCalls( -new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0) } - }, -new ClientCall { - { BadResponse, 9201}, - { HealthyResponse, 9202}, -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - }, -new ClientCall { - { BadResponse, 9203}, - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - } -); ----- -A cluster with 2 nodes where the second node fails on ping - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .ClientCalls(p => p.Fails(Always)) - .StaticConnectionPool() - .Settings(p=>p.DisablePing()) -); ----- -All the calls fail - -After all our registered nodes are marked dead we want to sample a single dead node -each time to quickly see if the cluster is back up. We do not want to retry all 4 -nodes - - -[source, csharp] ----- -await audit.TraceCalls( -new ClientCall { - { BadResponse, 9200}, - { BadResponse, 9201}, - { BadResponse, 9202}, - { BadResponse, 9203}, - { MaxRetriesReached }, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, -new ClientCall { - { AllNodesDead }, - { Resurrection, 9201}, - { BadResponse, 9201}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9202}, - { BadResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9203}, - { BadResponse, 9203}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9200}, - { BadResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - } -); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Round Robin - Skipping Dead Nodes + +When selecting nodes the connection pool will try and skip all the nodes that are marked dead. + +=== GetNext + +GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance +over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without +suffering from noisy neighboors advancing a global cursor. + +[source,csharp] +---- +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +var pool = new StaticConnectionPool(seeds, randomize: false); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +seeds.First().MarkDead(DateTime.Now.AddDays(1)); +var pool = new StaticConnectionPool(seeds, randomize: false); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +---- + +After we marked the first node alive again, we expect it to be hit again + +[source,csharp] +---- +seeds.First().MarkAlive(); + +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +var dateTimeProvider = new TestableDateTimeProvider(); +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +seeds.First().MarkDead(dateTimeProvider.Now().AddDays(1)); +var pool = new StaticConnectionPool(seeds, randomize: false, dateTimeProvider: dateTimeProvider); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9201); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9202); +---- + +If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected + +[source,csharp] +---- +dateTimeProvider.ChangeTime(d => d.AddDays(2)); + +var n = pool.CreateView().First(); +n.Uri.Port.Should().Be(9201); +n = pool.CreateView().First(); +n.Uri.Port.Should().Be(9202); +n = pool.CreateView().First(); +n.Uri.Port.Should().Be(9200); +n.IsResurrected.Should().BeTrue(); +---- + +A cluster with 2 nodes where the second node fails on ping + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .ClientCalls(p => p.Succeeds(Always)) + .ClientCalls(p => p.OnPort(9201).FailAlways()) + .ClientCalls(p => p.OnPort(9203).FailAlways()) + .StaticConnectionPool() + .Settings(p=>p.DisablePing()) +); +---- + +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails so we wrap over to node 9202 + +Finally we assert that the connectionpool has one node that is marked as dead + +The next call goes to 9203 which fails so we should wrap over + +[source,csharp] +---- +await audit.TraceCalls( +new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0) } + }, +new ClientCall { + { BadResponse, 9201}, + { HealthyResponse, 9202}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + }, +new ClientCall { + { BadResponse, 9203}, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + } +); +---- + +A cluster with 2 nodes where the second node fails on ping + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .ClientCalls(p => p.Fails(Always)) + .StaticConnectionPool() + .Settings(p=>p.DisablePing()) +); +---- + +All the calls fail + +After all our registered nodes are marked dead we want to sample a single dead node +each time to quickly see if the cluster is back up. We do not want to retry all 4 +nodes + +[source,csharp] +---- +await audit.TraceCalls( +new ClientCall { + { BadResponse, 9200}, + { BadResponse, 9201}, + { BadResponse, 9202}, + { BadResponse, 9203}, + { MaxRetriesReached }, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, +new ClientCall { + { AllNodesDead }, + { Resurrection, 9201}, + { BadResponse, 9201}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9202}, + { BadResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9203}, + { BadResponse, 9203}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9200}, + { BadResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + } +); +---- + diff --git a/docs/asciidoc/volatile_updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc similarity index 77% rename from docs/asciidoc/volatile_updates.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index c4e8592ac87..d153d19e86f 100644 --- a/docs/asciidoc/volatile_updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -1,10 +1,10 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:github: https://github.com/elastic/elasticsearch-net +:imagesdir: ../../../images/ - - -[source, csharp] +[source,csharp] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); var sniffingPool = new SniffingConnectionPool(uris, randomize: false); @@ -16,9 +16,7 @@ Action callStatic = () => this.AssertCreateView(staticPool); callStatic.ShouldNotThrow(); ---- - - -[source, csharp] +[source,csharp] ---- var threads = Enumerable.Range(0, 50) .Select(i => CreateReadAndUpdateThread(pool)) @@ -27,3 +25,4 @@ var threads = Enumerable.Range(0, 50) t.Start(); t.Join(); ---- + diff --git a/docs/asciidoc/on_connection_failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc similarity index 84% rename from docs/asciidoc/on_connection_failure.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index 49376513a51..6374cd9e5ba 100644 --- a/docs/asciidoc/on_connection_failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -1,155 +1,153 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Sniffing on connection failure - -Sniffing on connection is enabled by default when using a connection pool that allows reseeding. -The only IConnectionPool we ship that allows this is the SniffingConnectionPool. - -This can be very handy to force a refresh of the pools known healthy node by inspecting elasticsearch itself. -A sniff tries to get the nodes by asking each currently known node until one response. - - - -Here we seed our connection with 5 known nodes 9200-9204 of which we think -9202, 9203, 9204 are master eligible nodes. Our virtualized cluster will throw once when doing -a search on 9201. This should a sniff to be kicked off. - - - -When the call fails on 9201 the sniff succeeds and returns a new cluster of healty nodes -this cluster only has 3 nodes and the known masters are 9200 and 9202 but a search on 9201 -still fails once - - - -After this second failure on 9201 another sniff will be returned a cluster that no -longer fails but looks completely different (9210-9212) we should be able to handle this - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(5) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).Fails(Once)) -.Sniff(p => p.SucceedAlways(Framework.Cluster - .Nodes(3) - .MasterEligible(9200, 9202) - .ClientCalls(r => r.OnPort(9201).Fails(Once)) -.Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(3, 9210) - .MasterEligible(9210, 9212) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s.DisablePing().SniffOnStartup(false)) -); ----- - - -We assert we do a sniff on our first known master node 9202 - -Our pool should now have three nodes - -We assert we do a sniff on the first master node in our updated cluster - -[source, csharp] ----- -audit = await audit.TraceCalls( -new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(5) } - }, - new ClientCall { - { BadResponse, 9201}, -{ SniffOnFail }, - { SniffSuccess, 9202}, - { HealthyResponse, 9200}, -{ pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { - { BadResponse, 9201}, -{ SniffOnFail }, - { SniffSuccess, 9200}, - { HealthyResponse, 9210}, - { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } } -); ----- -Here we set up our cluster exactly the same as the previous setup -Only we enable pinging (default is true) and make the ping fail - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(5) - .MasterEligible(9202, 9203, 9204) - .Ping(r => r.OnPort(9201).Fails(Once)) - .Sniff(p => p.SucceedAlways(Framework.Cluster - .Nodes(3) - .MasterEligible(9200, 9202) - .Ping(r => r.OnPort(9201).Fails(Once)) - .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(3, 9210) - .MasterEligible(9210, 9211) - .Ping(r => r.SucceedAlways()) - .Sniff(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup(false)) -); ----- -We assert we do a sniff on our first known master node 9202 - -Our pool should now have three nodes - -We assert we do a sniff on the first master node in our updated cluster - -9210 was already pinged after the sniff returned the new nodes - -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { - { PingSuccess, 9200 }, - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(5) } - }, - new ClientCall { - { PingFailure, 9201}, -{ SniffOnFail }, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200}, -{ pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { - { PingFailure, 9201}, -{ SniffOnFail }, - { SniffSuccess, 9200}, - { PingSuccess, 9210}, - { HealthyResponse, 9210}, - { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { { PingSuccess, 9211 }, { HealthyResponse, 9211 } }, - new ClientCall { { PingSuccess, 9212 }, { HealthyResponse, 9212 } }, -new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } } -); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Sniffing on connection failure + +Sniffing on connection is enabled by default when using a connection pool that allows reseeding. +The only IConnectionPool we ship that allows this is the SniffingConnectionPool. + +This can be very handy to force a refresh of the pools known healthy node by inspecting elasticsearch itself. +A sniff tries to get the nodes by asking each currently known node until one response. + +Here we seed our connection with 5 known nodes 9200-9204 of which we think +9202, 9203, 9204 are master eligible nodes. Our virtualized cluster will throw once when doing +a search on 9201. This should a sniff to be kicked off. + +When the call fails on 9201 the sniff succeeds and returns a new cluster of healty nodes +this cluster only has 3 nodes and the known masters are 9200 and 9202 but a search on 9201 +still fails once + +After this second failure on 9201 another sniff will be returned a cluster that no +longer fails but looks completely different (9210-9212) we should be able to handle this + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(5) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).Fails(Once)) +.Sniff(p => p.SucceedAlways(Framework.Cluster + .Nodes(3) + .MasterEligible(9200, 9202) + .ClientCalls(r => r.OnPort(9201).Fails(Once)) +.Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(3, 9210) + .MasterEligible(9210, 9212) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s.DisablePing().SniffOnStartup(false)) +); +---- + +We assert we do a sniff on our first known master node 9202 + +Our pool should now have three nodes + +We assert we do a sniff on the first master node in our updated cluster + +[source,csharp] +---- +audit = await audit.TraceCalls( +new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(5) } + }, + new ClientCall { + { BadResponse, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9202}, + { HealthyResponse, 9200}, +{ pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { + { BadResponse, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9200}, + { HealthyResponse, 9210}, + { pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } } +); +---- + +Here we set up our cluster exactly the same as the previous setup +Only we enable pinging (default is true) and make the ping fail + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(5) + .MasterEligible(9202, 9203, 9204) + .Ping(r => r.OnPort(9201).Fails(Once)) + .Sniff(p => p.SucceedAlways(Framework.Cluster + .Nodes(3) + .MasterEligible(9200, 9202) + .Ping(r => r.OnPort(9201).Fails(Once)) + .Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(3, 9210) + .MasterEligible(9210, 9211) + .Ping(r => r.SucceedAlways()) + .Sniff(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup(false)) +); +---- + +We assert we do a sniff on our first known master node 9202 + +Our pool should now have three nodes + +We assert we do a sniff on the first master node in our updated cluster + +9210 was already pinged after the sniff returned the new nodes + +[source,csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { + { PingSuccess, 9200 }, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(5) } + }, + new ClientCall { + { PingFailure, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200}, +{ pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { + { PingFailure, 9201}, +{ SniffOnFail }, + { SniffSuccess, 9200}, + { PingSuccess, 9210}, + { HealthyResponse, 9210}, + { pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { { PingSuccess, 9211 }, { HealthyResponse, 9211 } }, + new ClientCall { { PingSuccess, 9212 }, { HealthyResponse, 9212 } }, +new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } } +); +---- + diff --git a/docs/asciidoc/on_stale_cluster_state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc similarity index 60% rename from docs/asciidoc/on_stale_cluster_state.asciidoc rename to docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index d3d40aa21f4..25816f351d0 100644 --- a/docs/asciidoc/on_stale_cluster_state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -1,92 +1,99 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Sniffing periodically - -Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. -In addition to sniffing on startup and sniffing on failures, sniffing periodically can benefit scenerio's where -clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes -but without sniffing periodically it will never find the nodes that have been added to help out with load - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(100) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(ss => ss.SucceedAlways(Framework.Cluster - .Nodes(10) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s - .DisablePing() - .SniffOnConnectionFault(false) - .SniffOnStartup(false) - .SniffLifeSpan(TimeSpan.FromMinutes(30)) - ) - ); ----- -healty cluster all nodes return healthy responses - -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9202 } }, - new ClientCall { { HealthyResponse, 9203 } }, - new ClientCall { { HealthyResponse, 9204 } }, - new ClientCall { { HealthyResponse, 9205 } }, - new ClientCall { { HealthyResponse, 9206 } }, - new ClientCall { { HealthyResponse, 9207 } }, - new ClientCall { { HealthyResponse, 9208 } }, - new ClientCall { { HealthyResponse, 9209 } }, - new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(10) } - } -); ----- -Now let's forward the clock 31 minutes, our sniff lifespan should now go state -and the first call should do a sniff which discovered we scaled up to a 100 nodes! - - -[source, csharp] ----- -audit.ChangeTime(d => d.AddMinutes(31)); ----- -a sniff is done first and it prefers the first node master node - -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { -{ SniffOnStaleCluster }, - { SniffSuccess, 9202 }, - { HealthyResponse, 9201 }, - { pool => pool.Nodes.Count.Should().Be(100) } - } -); - -audit.ChangeTime(d => d.AddMinutes(31)); ----- -a sniff is done first and it prefers the first node master node - -[source, csharp] ----- -audit = await audit.TraceCalls( - new ClientCall { -{ SniffOnStaleCluster }, - { SniffSuccess, 9202 }, - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(10) } - } -); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Sniffing periodically + +Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. +In addition to sniffing on startup and sniffing on failures, sniffing periodically can benefit scenerio's where +clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes +but without sniffing periodically it will never find the nodes that have been added to help out with load + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(100) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(ss => ss.SucceedAlways(Framework.Cluster + .Nodes(10) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s + .DisablePing() + .SniffOnConnectionFault(false) + .SniffOnStartup(false) + .SniffLifeSpan(TimeSpan.FromMinutes(30)) + ) +); +---- + +healty cluster all nodes return healthy responses + +[source,csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9202 } }, + new ClientCall { { HealthyResponse, 9203 } }, + new ClientCall { { HealthyResponse, 9204 } }, + new ClientCall { { HealthyResponse, 9205 } }, + new ClientCall { { HealthyResponse, 9206 } }, + new ClientCall { { HealthyResponse, 9207 } }, + new ClientCall { { HealthyResponse, 9208 } }, + new ClientCall { { HealthyResponse, 9209 } }, + new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(10) } + } +); +---- + +Now let's forward the clock 31 minutes, our sniff lifespan should now go state +and the first call should do a sniff which discovered we scaled up to a 100 nodes! + +[source,csharp] +---- +audit.ChangeTime(d => d.AddMinutes(31)); +---- + +a sniff is done first and it prefers the first node master node + +[source,csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { +{ SniffOnStaleCluster }, + { SniffSuccess, 9202 }, + { HealthyResponse, 9201 }, + { pool => pool.Nodes.Count.Should().Be(100) } + } +); + +audit.ChangeTime(d => d.AddMinutes(31)); +---- + +a sniff is done first and it prefers the first node master node + +[source,csharp] +---- +audit = await audit.TraceCalls( + new ClientCall { +{ SniffOnStaleCluster }, + { SniffSuccess, 9202 }, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(10) } + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc new file mode 100644 index 00000000000..0e3970e736e --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -0,0 +1,125 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Sniffing on startup + +Connection pools that return true for `SupportsReseeding` by default sniff on startup. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCall(new ClientCall + { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} +}); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCalls( + new ClientCall + { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} + }, + new ClientCall + { + { PingSuccess, 9201}, + { HealthyResponse, 9201} + } +); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always, Framework.Cluster.Nodes(8, startFrom: 9204))) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess, 9204}, + { HealthyResponse, 9204} +}); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9209).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffFailure, 9202}, + { SniffFailure, 9203}, + { SniffFailure, 9204}, + { SniffFailure, 9205}, + { SniffFailure, 9206}, + { SniffFailure, 9207}, + { SniffFailure, 9208}, + { SniffSuccess, 9209}, + { PingSuccess, 9200}, + { HealthyResponse, 9200} +}); +var audit = new Auditor(() => Framework.Cluster + .Nodes(new[] { + new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, + new Node(new Uri("http://localhost:9201")) { MasterEligible = false }, + new Node(new Uri("http://localhost:9202")) { MasterEligible = true }, + }) + .Sniff(s => s.Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200} +}); +var audit = new Auditor(() => Framework.Cluster + .Nodes(new[] { + new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, + new Node(new Uri("http://localhost:9201")) { MasterEligible = true }, + new Node(new Uri("http://localhost:9202")) { MasterEligible = false }, + }) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCall(new ClientCall { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200} +}); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc new file mode 100644 index 00000000000..a0a28493398 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -0,0 +1,128 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Sniffing role detection + + * + * When we sniff the custer state we detect the role of the node whether its master eligible and holds data + We use this information when selecting a node to perform an API call on. + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202) + .Succeeds(Always, Framework.Cluster.Nodes(8).MasterEligible(9200, 9201, 9202)) + ) + .SniffingConnectionPool() + .AllDefaults() +) +{ + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); + }, + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); + } +}; +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(10); +pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(8); +pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); +await audit.TraceStartup(); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202) + .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202)) + ) + .SniffingConnectionPool() + .AllDefaults() +) +{ + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); + }, + + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); + } +}; +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(10); +pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(8); +pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); +await audit.TraceStartup(); +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.SucceedAlways() + .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202).SniffShouldReturnFqdn()) + ) + .SniffingConnectionPool() + .AllDefaults() +) +{ + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); + pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); + }, + + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); + pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); + } +}; +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(10); +pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); +pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(8); +pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); +pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); +await audit.TraceStartup(); +var node = SniffAndReturnNode(); +node.MasterEligible.Should().BeTrue(); +node.HoldsData.Should().BeFalse(); +node = await SniffAndReturnNodeAsync(); +node.MasterEligible.Should().BeTrue(); +node.HoldsData.Should().BeFalse(); +var pipeline = CreatePipeline(); +pipeline.Sniff(); +var pipeline = CreatePipeline(); +await pipeline.SniffAsync(); +this._settings = + this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; +var pipeline = new RequestPipeline(this._settings, DateTimeProvider.Default, new MemoryStreamFactory(), + new SearchRequestParameters()); +var nodes = this._settings.ConnectionPool.Nodes; +nodes.Should().NotBeEmpty().And.HaveCount(1); +var node = nodes.First(); +---- + diff --git a/docs/asciidoc/covariant_search_results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc similarity index 74% rename from docs/asciidoc/covariant_search_results.asciidoc rename to docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index efb9f19e931..ac96d217f32 100644 --- a/docs/asciidoc/covariant_search_results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -1,233 +1,208 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Covariant Search Results - -NEST directly supports returning covariant result sets. -Meaning a result can be typed to an interface or baseclass -but the actual instance type of the result can be that of the subclass directly - -Let look at an example, imagine we want to search over multiple types that all implement -`ISearchResult` - - - - -We have three implementations of `ISearchResult` namely `A`, `B` and `C` - - - -The most straightforward way to search over multiple types is to -type the response to the parent interface or base class -and pass the actual types we want to search over using `.Types()` - - -[source, csharp] ----- -var result = this._client.Search(s => s - .Type(Types.Type(typeof(A), typeof(B), typeof(C))) - .Size(100) -); ----- - -Nest will translate this to a search over /index/a,b,c/_search. -hits that have `"_type" : "a"` will be serialized to `A` and so forth - - - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- - -A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to - - -[source, csharp] ----- -var result = this._client.Search(s => s - .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) - .Size(100) -); ----- - -here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` -and a typed `h` which represents the encapsulating hit. - - - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- -Scroll also supports CovariantSearchResponses - - - -Scroll() is a continuation of a previous Search() so Types() are lost. -You can hint the type types again using CovariantTypes() - - -[source, csharp] ----- -var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s - .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) -); ----- - -Nest will translate this to a search over /index/a,b,c/_search. -hits that have `"_type" : "a"` will be serialized to `A` and so forth - - - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- - -The more low level concrete type selector can also be specified on scroll - - -[source, csharp] ----- -var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s - .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) -); ----- - -here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` -and a typed `h` which represents the encapsulating hit. - - - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - - -[source, csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - - -[source, csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - - -[source, csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + += Covariant Search Results + +NEST directly supports returning covariant result sets. +Meaning a result can be typed to an interface or baseclass +but the actual instance type of the result can be that of the subclass directly + +Let look at an example, imagine we want to search over multiple types that all implement +`ISearchResult` + +We have three implementations of `ISearchResult` namely `A`, `B` and `C` + +The most straightforward way to search over multiple types is to +type the response to the parent interface or base class +and pass the actual types we want to search over using `.Types()` + +[source,csharp] +---- +var result = this._client.Search(s => s + .Type(Types.Type(typeof(A), typeof(B), typeof(C))) + .Size(100) +); +---- + +Nest will translate this to a search over /index/a,b,c/_search. +hits that have `"_type" : "a will be serialized to `A` and so forth + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to + +[source,csharp] +---- +var result = this._client.Search(s => s + .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) + .Size(100) +); +---- + +here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` +and a typed `h` which represents the encapsulating hit. + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +Scroll also supports CovariantSearchResponses + +Scroll() is a continuation of a previous Search() so Types() are lost. +You can hint the type types again using CovariantTypes() + +[source,csharp] +---- +var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s + .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) +); +---- + +Nest will translate this to a search over /index/a,b,c/_search. +hits that have `"_type" : "a will be serialized to `A` and so forth + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +The more low level concrete type selector can also be specified on scroll + +[source,csharp] +---- +var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s + .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) +); +---- + +here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` +and a typed `h` which represents the encapsulating hit. + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + diff --git a/docs/asciidoc/document_paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc similarity index 79% rename from docs/asciidoc/document_paths.asciidoc rename to docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc index f619676519e..df4686cb32d 100644 --- a/docs/asciidoc/document_paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc @@ -1,100 +1,111 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -= DocumentPaths - -Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes -and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path -to your document more succintly - - -== Creating new instances - -here we create a new document path based on Project with the id 1 - -[source, csharp] ----- -IDocumentPath path = new DocumentPath(1); - -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); ----- -You can still override the inferred index and type name - -[source, csharp] ----- -path = new DocumentPath(1).Type("project1"); - -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(1).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- -there is also a static way to describe such paths - -[source, csharp] ----- -path = DocumentPath.Id(1); - -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); ----- -== Creating from a document type instance -if you have an instance of your document you can use it as well generate document paths - - -[source, csharp] ----- -var project = new Project { Name = "hello-world" }; ----- -here we create a new document path based on the instance of `Project`, project - -[source, csharp] ----- -IDocumentPath path = new DocumentPath(project); - -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect("hello-world").WhenSerializing(path.Id); ----- -You can still override the inferred index and type name - -[source, csharp] ----- -path = new DocumentPath(project).Type("project1"); - -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(project).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- -there is also a static way to describe such paths - -[source, csharp] ----- -path = DocumentPath.Id(project); - -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect("hello-world").WhenSerializing(path.Id); -DocumentPath p = project; -var project = new Project { Name = "hello-world" }; ----- -Here we can see and example how DocumentPath helps your describe your requests more tersely - -[source, csharp] ----- -var request = new IndexRequest(2) { Document = project }; - -request = new IndexRequest(project) { }; ----- -when comparing with the full blown constructor and passing document manually -`DocumentPath`'s benefits become apparent. - - -[source, csharp] ----- -request = new IndexRequest(IndexName.From(), TypeName.From(), 2) -{ - Document = project -}; ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + += DocumentPaths + +Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes +and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path +to your document more succintly + +== Creating new instances + +here we create a new document path based on Project with the id 1 + +[source,csharp] +---- +IDocumentPath path = new DocumentPath(1); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect(1).WhenSerializing(path.Id); +---- + +You can still override the inferred index and type name + +[source,csharp] +---- +path = new DocumentPath(1).Type("project1"); + +Expect("project1").WhenSerializing(path.Type); +path = new DocumentPath(1).Index("project1"); +Expect("project1").WhenSerializing(path.Index); +---- + +there is also a static way to describe such paths + +[source,csharp] +---- +path = DocumentPath.Id(1); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect(1).WhenSerializing(path.Id); +---- + +== Creating from a document type instance + +if you have an instance of your document you can use it as well generate document paths + +[source,csharp] +---- +var project = new Project { Name = "hello-world" }; +---- + +here we create a new document path based on the instance of `Project`, project + +[source,csharp] +---- +IDocumentPath path = new DocumentPath(project); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect("hello-world").WhenSerializing(path.Id); +---- + +You can still override the inferred index and type name + +[source,csharp] +---- +path = new DocumentPath(project).Type("project1"); + +Expect("project1").WhenSerializing(path.Type); +path = new DocumentPath(project).Index("project1"); +Expect("project1").WhenSerializing(path.Index); +---- + +there is also a static way to describe such paths + +[source,csharp] +---- +path = DocumentPath.Id(project); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect("hello-world").WhenSerializing(path.Id); +DocumentPath p = project; +var project = new Project { Name = "hello-world" }; +---- + +Here we can see and example how DocumentPath helps your describe your requests more tersely + +[source,csharp] +---- +var request = new IndexRequest(2) { Document = project }; + +request = new IndexRequest(project) { }; +---- + +when comparing with the full blown constructor and passing document manually +`DocumentPath`'s benefits become apparent. + +[source,csharp] +---- +request = new IndexRequest(IndexName.From(), TypeName.From(), 2) +{ + Document = project +}; +---- + diff --git a/docs/asciidoc/field_inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc similarity index 80% rename from docs/asciidoc/field_inference.asciidoc rename to docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc index d03c68464ab..67e2daa2833 100644 --- a/docs/asciidoc/field_inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc @@ -1,406 +1,423 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -= Strongly typed field access - -Several places in the elasticsearch API expect the path to a field from your original source document as a string. -NEST allows you to use C# expressions to strongly type these field path strings. - -These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: - - -Using the constructor directly is possible but rather involved - -[source, csharp] ----- -var fieldString = new Field { Name = "name" }; ----- -especially when using C# expressions since these can not be simply new'ed - -[source, csharp] ----- -Expression> expression = p => p.Name; - -var fieldExpression = Field.Create(expression); -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- -Therefore you can also implicitly convert strings and expressions to `Field`s - -[source, csharp] ----- -Field fieldString = "name"; ----- -but for expressions this is still rather involved - -[source, csharp] ----- -Expression> expression = p => p.Name; - -Field fieldExpression = expression; -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- -to ease creating `Field`s from expressions there is a static Property class you can use - -[source, csharp] ----- -Field fieldString = "name"; ----- -but for expressions this is still rather involved - -[source, csharp] ----- -var fieldExpression = Infer.Field(p => p.Name); ----- -this can be even shortened even further using static imports in c# 6 i.e. -`using static Nest.Static;` - - -[source, csharp] ----- -fieldExpression = Field(p => p.Name); ----- -Now this is much much terser then our first example using the constructor! - -[source, csharp] ----- -Expect("name") - .WhenSerializing(fieldString) - .WhenSerializing(fieldExpression); ----- -By default, NEST will camel-case all field names to be more _javascript-y_ - -using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior - -[source, csharp] ----- -var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); - -setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); ----- -However string are *always* passed along verbatim - -[source, csharp] ----- -setup.Expect("NaMe").WhenSerializing("NaMe"); ----- -if you want the same behavior for expressions simply do nothing in the default inferrer - -[source, csharp] ----- -setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); - -setup.Expect("Name").WhenSerializing(Field(p => p.Name)); ----- -== Complex field name expressions - -You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName - -[source, csharp] ----- -Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ----- -When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections - -[source, csharp] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ----- -Similarly, LINQ's `.First()` method also works -NOTE: remember these are expressions and not actual code that will be executed - -[source, csharp] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); - -Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); -Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); ----- -An indexer on a dictionary is assumed to describe a property name - -[source, csharp] ----- -Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); - -Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); ----- -A cool feature here is that we'll evaluate variables passed to an indexer - -[source, csharp] ----- -var variable = "var"; - -Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); -Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ----- -:multifieldlink: https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html -If you are using elasticearch's {multifieldlink}[multi_fields], which you really should as they allow -you to analyze a string in a number of different ways, these _"virtual"_ sub fields -do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that -should be mapped. - - -[source, csharp] ----- -Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); - -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); -Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); -Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); -Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); ----- - -You can even chain `.Suffix()` calls to any depth! - - -[source, csharp] ----- -Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ----- -Variables passed to suffix will be evaluated as well - -[source, csharp] ----- -var suffix = "unanalyzed"; - -Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); -Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); ----- - -Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix -to a list of fields. - - -Here we have a list of expressions - -[source, csharp] ----- -var expressions = new List>> -{ - p => p.Name, - p => p.Description, - p => p.CuratedTags.First().Name, - p => p.LeadDeveloper.FirstName -}; ----- -and we want to append the suffix "raw" to each - -[source, csharp] ----- -var fieldExpressions = - expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); - -Expect("name.raw").WhenSerializing(fieldExpressions[0]); -Expect("description.raw").WhenSerializing(fieldExpressions[1]); -Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); -Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); ----- -== Annotations - -When using NEST's property attributes you can specify a new name for the properties - - -[source, csharp] ----- -public class BuiltIn -{ - [String(Name = "naam")] - public string Name { get; set; } -} - -Expect("naam").WhenSerializing(Field(p => p.Name)); ----- - -Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. -Here we ask the default `JsonNetSerializer` to resolve a property name and it takes -the `JsonPropertyAttribute` into account - - -[source, csharp] ----- -public class SerializerSpecific -{ - [JsonProperty("nameInJson")] - public string Name { get; set; } -} - -Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ----- - -If both a NEST property attribute and a serializer specific attribute are present on a property, -NEST takes precedence - - -[source, csharp] ----- -public class Both -{ - [String(Name = "naam")] - [JsonProperty("nameInJson")] - public string Name { get; set; } -} - -Expect("naam").WhenSerializing(Field(p => p.Name)); -Expect(new - { - naam = "Martijn Laarman" - }).WhenSerializing(new Both { Name = "Martijn Laarman" }); ----- - -Resolution of field names is cached per connection settings instance. To demonstrate, -take the following simple POCOs - - -[source, csharp] ----- -class A { public C C { get; set; } } - -class B { public C C { get; set; } } - -class C { public string Name { get; set; } } - -var connectionSettings = TestClient.CreateSettings(forceInMemory: true); -var client = new ElasticClient(connectionSettings); -var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); -var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); ----- - -Here we have to similary shaped expressions on coming from A and on from B -that will resolve to the same field name, as expected - - -[source, csharp] ----- -fieldNameOnA.Should().Be("c.name"); - -fieldNameOnB.Should().Be("c.name"); ----- - -now we create a new connectionsettings with a remap for C on class A to `d` -now when we resolve the field path for A will be different - - -[source, csharp] ----- -var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s - .InferMappingFor(m => m - .Rename(p => p.C, "d") - ) -); - -var newClient = new ElasticClient(newConnectionSettings); -fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); -fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); -fieldNameOnA.Should().Be("d.name"); -fieldNameOnB.Should().Be("c.name"); ----- -however we didn't break inferrence on the first client instance using its separate connectionsettings - -[source, csharp] ----- -fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); - -fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); -fieldNameOnA.Should().Be("c.name"); -fieldNameOnB.Should().Be("c.name"); ----- - -To wrap up, the precedence in which field names are inferred is: - -. A hard rename of the property on connection settings using `.Rename()` -. A NEST property mapping -. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. -. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases - -The following example class will demonstrate this precedence - - -[source, csharp] ----- -class Precedence -{ - // Even though this property has a NEST property mapping and a JsonProperty attribute, - // We are going to provide a hard rename for it on ConnectionSettings later that should win. - [String(Name = "renamedIgnoresNest")] - [JsonProperty("renamedIgnoresJsonProperty")] - public string RenamedOnConnectionSettings { get; set; } - - // This property has both a NEST attribute and a JsonProperty, NEST should win. - [String(Name = "nestAtt")] - [JsonProperty("jsonProp")] - public string NestAttribute { get; set; } - - // We should take the json property into account by itself - [JsonProperty("jsonProp")] - public string JsonProperty { get; set; } - - // This property we are going to special case in our custom serializer to resolve to ask - [JsonProperty("dontaskme")] - public string AskSerializer { get; set; } - - // We are going to register a DefaultFieldNameInferrer on ConnectionSettings - // that will uppercase all properties. - public string DefaultFieldNameInferrer { get; set; } -} ----- - -Here we create a custom serializer that renames any property named `AskSerializer` to `ask` - - -[source, csharp] ----- -class CustomSerializer : JsonNetSerializer -{ - public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } - - public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) - { - return memberInfo.Name == nameof(Precedence.AskSerializer) - ? new PropertyMapping { Name = "ask" } - : base.CreatePropertyMapping(memberInfo); - } -} ----- -here we provide an explicit rename of a property on connectionsettings using `.Rename()` -and all properties that are not mapped verbatim should be uppercased - - -[source, csharp] ----- -var usingSettings = WithConnectionSettings(s => s - - .InferMappingFor(m => m - .Rename(p => p.RenamedOnConnectionSettings, "renamed") - ) - .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) -).WithSerializer(s => new CustomSerializer(s)); - -usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); -usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); -usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); -usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); -usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); ----- -The same naming rules also apply when indexing a document - -[source, csharp] ----- -usingSettings.Expect(new [] -{ - "ask", - "DEFAULTFIELDNAMEINFERRER", - "jsonProp", - "nestAtt", - "renamed" -}).AsPropertiesOf(new Precedence -{ - RenamedOnConnectionSettings = "renamed on connection settings", - NestAttribute = "using a nest attribute", - JsonProperty = "the default serializer resolves json property attributes", - AskSerializer = "serializer fiddled with this one", - DefaultFieldNameInferrer = "shouting much?" -}); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + += Strongly typed field access + +Several places in the elasticsearch API expect the path to a field from your original source document as a string. +NEST allows you to use C expressions to strongly type these field path strings. + +These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: + +Using the constructor directly is possible but rather involved + +[source,csharp] +---- +var fieldString = new Field { Name = "name" }; +---- + +especially when using C expressions since these can not be simply new'ed + +[source,csharp] +---- +Expression> expression = p => p.Name; + +var fieldExpression = Field.Create(expression); +Expect("name") + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); +---- + +Therefore you can also implicitly convert strings and expressions to `Field`s + +[source,csharp] +---- +Field fieldString = "name"; +---- + +but for expressions this is still rather involved + +[source,csharp] +---- +Expression> expression = p => p.Name; + +Field fieldExpression = expression; +Expect("name") + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); +---- + +to ease creating `Field`s from expressions there is a static Property class you can use + +[source,csharp] +---- +Field fieldString = "name"; +---- + +but for expressions this is still rather involved + +[source,csharp] +---- +var fieldExpression = Infer.Field(p => p.Name); +---- + +this can be even shortened even further using static imports in c 6 i.e. + `using static Nest.Static;` + +[source,csharp] +---- +fieldExpression = Field(p => p.Name); +---- + +Now this is much much terser then our first example using the constructor! + +[source,csharp] +---- +Expect("name") + .WhenSerializing(fieldString) + .WhenSerializing(fieldExpression); +---- + +By default, NEST will camel-case all field names to be more _javascript-y_ + +using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior + +[source,csharp] +---- +var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); + +setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); +---- + +However string are *always* passed along verbatim + +[source,csharp] +---- +setup.Expect("NaMe").WhenSerializing("NaMe"); +---- + +if you want the same behavior for expressions simply do nothing in the default inferrer + +[source,csharp] +---- +setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); + +setup.Expect("Name").WhenSerializing(Field(p => p.Name)); +---- + +== Complex field name expressions + +You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName + +[source,csharp] +---- +Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); +---- + +When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections + +[source,csharp] +---- +Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); +---- + +NOTE: Similarly, LINQ's `.First()` method also works +remember these are expressions and not actual code that will be executed + +[source,csharp] +---- +Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); + +Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); +Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); +---- + +An indexer on a dictionary is assumed to describe a property name + +[source,csharp] +---- +Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); + +Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); +---- + +A cool feature here is that we'll evaluate variables passed to an indexer + +[source,csharp] +---- +var variable = "var"; + +Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); +Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); +---- + +:multifieldlink: https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html + +If you are using elasticearch's {multifieldlink}[multi_fields], which you really should as they allow +you to analyze a string in a number of different ways, these _"virtual" sub fields +do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that +should be mapped. + +[source,csharp] +---- +Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); + +Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); +Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); +Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); +Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); +Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); +---- + +You can even chain `.Suffix()` calls to any depth! + +[source,csharp] +---- +Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); +---- + +Variables passed to suffix will be evaluated as well + +[source,csharp] +---- +var suffix = "unanalyzed"; + +Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); +Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); +---- + +Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix +to a list of fields. + +Here we have a list of expressions + +[source,csharp] +---- +var expressions = new List>> +{ + p => p.Name, + p => p.Description, + p => p.CuratedTags.First().Name, + p => p.LeadDeveloper.FirstName +}; +---- + +and we want to append the suffix "raw" to each + +[source,csharp] +---- +var fieldExpressions = + expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); + +Expect("name.raw").WhenSerializing(fieldExpressions[0]); +Expect("description.raw").WhenSerializing(fieldExpressions[1]); +Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); +Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); +---- + +== Annotations + +When using NEST's property attributes you can specify a new name for the properties + +[source,csharp] +---- +public class BuiltIn +{ + [String(Name = "naam")] + public string Name { get; set; } +} + +Expect("naam").WhenSerializing(Field(p => p.Name)); +---- + +Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. +Here we ask the default `JsonNetSerializer` to resolve a property name and it takes +the `JsonPropertyAttribute` into account + +[source,csharp] +---- +public class SerializerSpecific +{ + [JsonProperty("nameInJson")] + public string Name { get; set; } +} + +Expect("nameInJson").WhenSerializing(Field(p => p.Name)); +---- + +If both a NEST property attribute and a serializer specific attribute are present on a property, +NEST takes precedence + +[source,csharp] +---- +public class Both +{ + [String(Name = "naam")] + [JsonProperty("nameInJson")] + public string Name { get; set; } +} + +Expect("naam").WhenSerializing(Field(p => p.Name)); +Expect(new +{ + naam = "Martijn Laarman" +}).WhenSerializing(new Both { Name = "Martijn Laarman" }); +---- + +Resolution of field names is cached per connection settings instance. To demonstrate, +take the following simple POCOs + +[source,csharp] +---- +class A { public C C { get; set; } } + +class B { public C C { get; set; } } + +class C { public string Name { get; set; } } + +var connectionSettings = TestClient.CreateSettings(forceInMemory: true); +var client = new ElasticClient(connectionSettings); +var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); +var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); +---- + +Here we have to similary shaped expressions on coming from A and on from B +that will resolve to the same field name, as expected + +[source,csharp] +---- +fieldNameOnA.Should().Be("c.name"); + +fieldNameOnB.Should().Be("c.name"); +---- + +now we create a new connectionsettings with a remap for C on class A to `d` +now when we resolve the field path for A will be different + +[source,csharp] +---- +var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s + .InferMappingFor(m => m + .Rename(p => p.C, "d") + ) +); + +var newClient = new ElasticClient(newConnectionSettings); +fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); +fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); +fieldNameOnA.Should().Be("d.name"); +fieldNameOnB.Should().Be("c.name"); +---- + +however we didn't break inferrence on the first client instance using its separate connectionsettings + +[source,csharp] +---- +fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); + +fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); +fieldNameOnA.Should().Be("c.name"); +fieldNameOnB.Should().Be("c.name"); +---- + +To wrap up, the precedence in which field names are inferred is: + +. A hard rename of the property on connection settings using `.Rename()` + +. A NEST property mapping + +. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. + +. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases + +The following example class will demonstrate this precedence + +[source,csharp] +---- +class Precedence +{ + // Even though this property has a NEST property mapping and a JsonProperty attribute, + // We are going to provide a hard rename for it on ConnectionSettings later that should win. + [String(Name = "renamedIgnoresNest")] + [JsonProperty("renamedIgnoresJsonProperty")] + public string RenamedOnConnectionSettings { get; set; } + + // This property has both a NEST attribute and a JsonProperty, NEST should win. + [String(Name = "nestAtt")] + [JsonProperty("jsonProp")] + public string NestAttribute { get; set; } + + // We should take the json property into account by itself + [JsonProperty("jsonProp")] + public string JsonProperty { get; set; } + + // This property we are going to special case in our custom serializer to resolve to ask + [JsonProperty("dontaskme")] + public string AskSerializer { get; set; } + + // We are going to register a DefaultFieldNameInferrer on ConnectionSettings + // that will uppercase all properties. + public string DefaultFieldNameInferrer { get; set; } +} +---- + +Here we create a custom serializer that renames any property named `AskSerializer` to `ask` + +[source,csharp] +---- +class CustomSerializer : JsonNetSerializer +{ + public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } + + public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) + { + return memberInfo.Name == nameof(Precedence.AskSerializer) + ? new PropertyMapping { Name = "ask" } + : base.CreatePropertyMapping(memberInfo); + } +} +---- + +here we provide an explicit rename of a property on connectionsettings using `.Rename()` +and all properties that are not mapped verbatim should be uppercased + +[source,csharp] +---- +var usingSettings = WithConnectionSettings(s => s + + .InferMappingFor(m => m + .Rename(p => p.RenamedOnConnectionSettings, "renamed") + ) + .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) +).WithSerializer(s => new CustomSerializer(s)); + +usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); +usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); +usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); +usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); +usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); +---- + +The same naming rules also apply when indexing a document + +[source,csharp] +---- +usingSettings.Expect(new [] +{ + "ask", + "DEFAULTFIELDNAMEINFERRER", + "jsonProp", + "nestAtt", + "renamed" +}).AsPropertiesOf(new Precedence +{ + RenamedOnConnectionSettings = "renamed on connection settings", + NestAttribute = "using a nest attribute", + JsonProperty = "the default serializer resolves json property attributes", + AskSerializer = "serializer fiddled with this one", + DefaultFieldNameInferrer = "shouting much?" +}); +---- + diff --git a/docs/asciidoc/ids_inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc similarity index 51% rename from docs/asciidoc/ids_inference.asciidoc rename to docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc index ca93a7b8ac9..ba13264f705 100644 --- a/docs/asciidoc/ids_inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc @@ -1,100 +1,133 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -= Ids - -Several places in the elasticsearch API expect an Id object to be passed. -This is a special box type that you can implicitly convert to and from many value types. - - -Methods that take an Id can be passed longs, ints, strings & Guids and they will be implicitly converted to Ids - -[source, csharp] ----- -Id idFromInt = 1; -Id idFromLong = 2L; -Id idFromString = "hello-world"; -Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); -Expect(1).WhenSerializing(idFromInt); -Expect(2).WhenSerializing(idFromLong); -Expect("hello-world").WhenSerializing(idFromString); -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); ----- -Sometimes a method takes an object and we need an Id from that object to build up a path. -There is no implicit conversion from any object to Id but we can call `Id.From`. - -Imagine your codebase has the following type that we want to index into elasticsearch - - -[source, csharp] ----- -class MyDTO -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } -} ----- -By default NEST will try to find a property called `Id` on the class using reflection -and create a cached fast func delegate based on the properties getter - -[source, csharp] ----- -var dto = new MyDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; - -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); ----- -Using the connection settings you can specify a different property NEST should look for ids. -Here we instruct NEST to infer the Id for MyDTO based on its Name property - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.Name) - ) -).Expect("x").WhenInferringIdOn(dto); ----- -Even though we have a cache at play the cache is per connection settings, so we can create a different config - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- -Another way is to mark the type with an `ElasticsearchType` attribute, using a string `IdProperty` - -[source, csharp] ----- -[ElasticsearchType(IdProperty = nameof(Name))] -class MyOtherDTO -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } -} ----- -Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the ConnectionSettings - -[source, csharp] ----- -var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; - -Expect("x").WhenInferringIdOn(dto); ----- -This attribute *is* cached statically/globally, however connectionsettings with a config for the type will -still win over this static configuration. - -Even though we have a cache at play the cache its per connection settings, so we can create a different config - - -[source, csharp] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Id Inference + +=== Implicit Conversions + +Several places in the Elasticsearch API expect an `Id` object to be passed. +This is a special box type that you can implicitly convert to from the following types + +* `Int32` + +* `Int64` + +* `String` + +* `Guid` + +Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` + +[source,csharp] +---- +Id idFromInt = 1; +Id idFromLong = 2L; +Id idFromString = "hello-world"; +Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); +Expect(1).WhenSerializing(idFromInt); +Expect(2).WhenSerializing(idFromLong); +Expect("hello-world").WhenSerializing(idFromString); +Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); +---- + +=== Inferring from a Type + +Sometimes a method takes an object and we need an Id from that object to build up a path. +There is no implicit conversion from any object to Id but we can call `Id.From`. + +Imagine your codebase has the following type that we want to index into Elasticsearch + +[source,csharp] +---- +class MyDTO +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } +} +---- + +By default NEST will try to find a property called `Id` on the class using reflection +and create a cached fast func delegate based on the properties getter + +[source,csharp] +---- +var dto = new MyDTO +{ + Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), + Name = "x", + OtherName = "y" +}; + +Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); +---- + +Using the connection settings you can specify a different property that NEST should use to infer the document Id. +Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property + +[source,csharp] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.Name) + ) +).Expect("x").WhenInferringIdOn(dto); +---- + +IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. + + Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance + with different inference rules + +[source,csharp] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) +).Expect("y").WhenInferringIdOn(dto); +---- + +=== Using the `ElasticsearchType` attribute + +Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` +to the name of the property that should be used for the document id + +[source,csharp] +---- +[ElasticsearchType(IdProperty = nameof(Name))] +class MyOtherDTO +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } +} +---- + +Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` + +[source,csharp] +---- +var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; + +Expect("x").WhenInferringIdOn(dto); +---- + +=== Using Mapping inference on `ConnectionSettings` + +This attribute *is* cached statically/globally, however an inference rule on the `ConnectionSettings` for the type will +still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance +that will infer the document id from the property `OtherName`: + +[source,csharp] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) +).Expect("y").WhenInferringIdOn(dto); +---- + diff --git a/docs/asciidoc/indices_paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc similarity index 56% rename from docs/asciidoc/indices_paths.asciidoc rename to docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc index 9e084e4b450..f422f6914ac 100644 --- a/docs/asciidoc/indices_paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc @@ -1,47 +1,50 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Indices paths - -Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices -In nest this is encoded using `Indices` - - -Several types implicitly convert to `Indices` - -[source, csharp] ----- -Nest.Indices singleIndexFromString = "name"; -Nest.Indices multipleIndicesFromString = "name1, name2"; -Nest.Indices allFromString = "_all"; -Nest.Indices allWithOthersFromString = "_all, name2"; -singleIndexFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(1).And.Contain("name") - ); -multipleIndicesFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(2).And.Contain("name2") - ); -allFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() - ); -allWithOthersFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() - ); ----- -to ease creating Field's from expressions there is a static Property class you can use - - - -[source, csharp] ----- -var all = Nest.Indices.All; - -var many = Nest.Indices.Index("name1", "name2"); -var manyTyped = Nest.Indices.Index().And(); -var singleTyped = Nest.Indices.Index(); -var singleString = Nest.Indices.Index("name1"); -var invalidSingleString = Nest.Indices.Index("name1, name2"); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + += Indices paths + +Some API's in elasticsearch take one or many index name or a special "all" marker to send the request to all the indices +In nest this is encoded using `Indices` + +Several types implicitly convert to `Indices` + +[source,csharp] +---- +Nest.Indices singleIndexFromString = "name"; +Nest.Indices multipleIndicesFromString = "name1, name2"; +Nest.Indices allFromString = "_all"; +Nest.Indices allWithOthersFromString = "_all, name2"; +singleIndexFromString.Match( + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(1).And.Contain("name") +); +multipleIndicesFromString.Match( + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(2).And.Contain("name2") +); +allFromString.Match( + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() +); +allWithOthersFromString.Match( + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() +); +---- + +to ease creating Field's from expressions there is a static Property class you can use + +[source,csharp] +---- +var all = Nest.Indices.All; + +var many = Nest.Indices.Index("name1", "name2"); +var manyTyped = Nest.Indices.Index().And(); +var singleTyped = Nest.Indices.Index(); +var singleString = Nest.Indices.Index("name1"); +var invalidSingleString = Nest.Indices.Index("name1, name2"); +---- + diff --git a/docs/asciidoc/property_inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc similarity index 67% rename from docs/asciidoc/property_inference.asciidoc rename to docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc index 4fdb46cf639..89f3a3519e3 100644 --- a/docs/asciidoc/property_inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc @@ -1,29 +1,31 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - - -Property names resolve to the last token. An example using the `.Suffix()` extension - - -[source, csharp] ----- -Expression> expression = p => p.Name.Suffix("raw"); -Expect("raw").WhenSerializing(expression); ----- - -And an example using the `.ApplySuffix()` extension on lambda expressions - - -[source, csharp] ----- -Expression> expression = p => p.Name; -expression.AppendSuffix("raw"); -Expect("raw").WhenSerializing(expression); ----- -Property names cannot contain a `.` in order to prevent the potential for collision with a field that -may have https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html[`multi_fields`] - - -[source, csharp] ----- -Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +Property names resolve to the last token. An example using the `.Suffix()` extension + +[source,csharp] +---- +Expression> expression = p => p.Name.Suffix("raw"); +Expect("raw").WhenSerializing(expression); +---- + +And an example using the `.ApplySuffix()` extension on lambda expressions + +[source,csharp] +---- +Expression> expression = p => p.Name; +expression.AppendSuffix("raw"); +Expect("raw").WhenSerializing(expression); +---- + +Property names cannot contain a `.` in order to prevent the potential for collision with a field that +may have https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html[`multi_fields`] + +[source,csharp] +---- +Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc new file mode 100644 index 00000000000..7bbbc05fa74 --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -0,0 +1,954 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Auto mapping properties + + * + * When creating a mapping (either when creating an index or via the put mapping API), + * NEST offers a feature called AutoMap(), which will automagically infer the correct + * Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if + * you're using attributes to map your properties, then calling AutoMap() is required + * in order for your attributes to be applied. We'll look at examples of both. + * + * + + * For these examples, we'll define two POCOS, `Company`, which has a name + * and a collection of Employees, and `Employee` which has various properties of + different types, and itself has a collection of `Employee` types. + +[source,csharp] +---- +public class Company +{ + public string Name { get; set; } + public List Employees { get; set; } +} + +public class Employee +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public int Salary { get; set; } + public DateTime Birthday { get; set; } + public bool IsManager { get; set; } + public List Employees { get; set; } + public TimeSpan Hours { get; set;} +} +---- + +=== Manual mapping + + * To create a mapping for our Company type, we can use the fluent API + * and map each property explicitly + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .Properties(ps => ps + .String(s => s + .Name(c => c.Name) + ) + .Object(o => o + .Name(c => c.Employees) + .Properties(eps => eps + .String(s => s + .Name(e => e.FirstName) + ) + .String(s => s + .Name(e => e.LastName) + ) + .Number(n => n + .Name(e => e.Salary) + .Type(NumberType.Integer) + ) + ) + ) + ) + ) + ); +---- + + * This is all fine and dandy and useful for some use cases however in most cases + * this can become verbose and wieldy. The majority of the time you simply just want to map *all* + the properties of a POCO in a single go. + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + name = new + { + type = "string" + }, + employees = new + { + type = "object", + properties = new + { + firstName = new + { + type = "string" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + } + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +=== Simple Automapping + + * This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, + * explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap()) + .Map(m => m.AutoMap()) + ); +---- + + * Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. + * In this example, + * - Birthday was mapped as a date, + * - Hours was mapped as a long (ticks) + * - IsManager was mapped as a boolean, + * - Salary as an integer + * - Employees as an object + * and the remaining string properties as strings. + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + employees = new + { + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + type = "object" + }, + name = new + { + type = "string" + } + } + }, + employee = new + { + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +== Automapping with overrides + + * In most cases, you'll want to map more than just the vanilla datatypes and also provide + * various options on your properties (analyzer, docvalues, etc...). In that case, it's + * possible to use AutoMap() in conjuction with explicitly mapped properties. + + * Here we are using AutoMap() to automatically map our company type, but then we're + * overriding our employee property and making it a `nested` type, since by default, + AutoMap() will infer objects as `object`. + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .AutoMap() + .Properties(ps => ps + .Nested(n => n + .Name(c => c.Employees) + .Properties(eps => eps + // snip + ) + ) + ) + ) + ); + +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + name = new + { + type = "string" + }, + employees = new + { + type = "nested", + properties = new {} + } + } + } + } +}; +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +== Automap with attributes + + * It is also possible to define your mappings using attributes on your POCOS. When you + * use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. + Here we define the same two types but this time using attributes. + +[source,csharp] +---- +[ElasticsearchType(Name = "company")] +public class CompanyWithAttributes +{ + [String(Analyzer = "keyword", NullValue = "null", Similarity = SimilarityOption.BM25)] + public string Name { get; set; } + + [String] + public TimeSpan? HeadOfficeHours { get; set; } + + [Object(Path = "employees", Store = false)] + public List Employees { get; set; } +} + +[ElasticsearchType(Name = "employee")] +public class EmployeeWithAttributes +{ + [String] + public string FirstName { get; set; } + + [String] + public string LastName { get; set; } + + [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)] + public int Salary { get; set; } + + [Date(Format = "MMddyyyy", NumericResolution = NumericResolutionUnit.Seconds)] + public DateTime Birthday { get; set; } + + [Boolean(NullValue = false, Store = true)] + public bool IsManager { get; set; } + + [Nested(Path = "employees")] + [JsonProperty("empl")] + public List Employees { get; set; } +} +---- + + Then map the types by calling `.AutoMap()` + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap()) + .Map(m => m.AutoMap()) + ); +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + employees = new + { + path = "employees", + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + store = false, + type = "object" + }, + name = new + { + analyzer = "keyword", + null_value = "null", + similarity = "BM25", + type = "string" + }, + headOfficeHours = new + { + type = "string" + } + } + }, + employee = new + { + properties = new + { + birthday = new + { + format = "MMddyyyy", + numeric_resolution = "seconds", + type = "date" + }, + empl = new + { + path = "employees", + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + type = "nested" + }, + firstName = new + { + type = "string" + }, + isManager = new + { + null_value = false, + store = true, + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + coerce = true, + doc_values = false, + ignore_malformed = true, + type = "double" + } + } + } + } +}; +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + + * Just as we were able to override the inferred properties in our earlier example, explicit (manual) + * mappings also take precedence over attributes. Therefore we can also override any mappings applied + via any attributes defined on the POCO + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .AutoMap() + .Properties(ps => ps + .Nested(n => n + .Name(c => c.Employees) + ) + ) + ) + .Map(m => m + .AutoMap() + .TtlField(ttl => ttl + .Enable() + .Default("10m") + ) + .Properties(ps => ps + .String(s => s + .Name(e => e.FirstName) + .Fields(fs => fs + .String(ss => ss + .Name("firstNameRaw") + .Index(FieldIndexOption.NotAnalyzed) + ) + .TokenCount(t => t + .Name("length") + .Analyzer("standard") + ) + ) + ) + .Number(n => n + .Name(e => e.Salary) + .Type(NumberType.Double) + .IgnoreMalformed(false) + ) + .Date(d => d + .Name(e => e.Birthday) + .Format("MM-dd-yy") + ) + ) + ) + ); +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + employees = new + { + type = "nested" + }, + name = new + { + analyzer = "keyword", + null_value = "null", + similarity = "BM25", + type = "string" + }, + headOfficeHours = new + { + type = "string" + } + } + }, + employee = new + { + _ttl = new + { + enabled = true, + @default = "10m" + }, + properties = new + { + birthday = new + { + format = "MM-dd-yy", + type = "date" + }, + empl = new + { + path = "employees", + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + type = "nested" + }, + firstName = new + { + fields = new + { + firstNameRaw = new + { + index = "not_analyzed", + type = "string" + }, + length = new + { + type = "token_count", + analyzer = "standard" + } + }, + type = "string" + }, + isManager = new + { + null_value = false, + store = true, + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + ignore_malformed = false, + type = "double" + } + } + } + } +}; +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +== Ignoring Properties + + * Properties on a POCO can be ignored in a few ways: + * + * - Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO + * + * - Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings + * + * - Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` + * + * This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the + * property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` + +[source,csharp] +---- +[ElasticsearchType(Name = "company")] +public class CompanyWithAttributesAndPropertiesToIgnore +{ + public string Name { get; set; } + + [String(Ignore = true)] + public string PropertyToIgnore { get; set; } + + public string AnotherPropertyToIgnore { get; set; } + + [JsonIgnore] + public string JsonIgnoredProperty { get; set; } +} +---- + +All of the properties except `Name` have been ignored in the mapping + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .AutoMap() + ) + ); + +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + name = new + { + type = "string" + } + } + } + } +}; +var settings = WithConnectionSettings(s => s + .InferMappingFor(i => i + .Ignore(p => p.AnotherPropertyToIgnore) + ) +); +settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +== Mapping Recursion + + * If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive + * in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only + * traverse a single depth when it encounters recursive instances like this. Hence, in the + * previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. + * This is done as a safe-guard to prevent stack overflows and all the fun that comes with + * infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is + * often an edge case to have deeply nested mappings like this. However, you may still have + * the need to do this, so you can control the recursion depth of `.AutoMap()`. + * + * Let's introduce a very simple class, `A`, which itself has a property + Child of type `A`. + +[source,csharp] +---- +public class A +{ + public A Child { get; set; } +} +---- + +By default, `.AutoMap()` only goes as far as depth 1 + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap()) + ); +---- + +Thus we do not map properties on the second occurrence of our Child property + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + a = new + { + properties = new + { + child = new + { + properties = new { }, + type = "object" + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +Now lets specify a maxRecursion of 3 + +[source,csharp] +---- +var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(3)) + ); +---- + +`.AutoMap()` has now mapped three levels of our Child property + +[source,csharp] +---- +var expectedWithMaxRecursion = new +{ + mappings = new + { + a = new + { + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new { } + } + } + } + } + } + } + } + } + } + } +}; + +Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); +---- + +== Applying conventions through the Visitor pattern + + * It is also possible to apply a transformation on all or specific properties. + * + * AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, + * does nothing and acts as a blank canvas for you to implement your own visiting methods. + * + * For instance, lets create a custom visitor that disables doc values for numeric and boolean types. + (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) + +[source,csharp] +---- +public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor +{ + // Override the Visit method on INumberProperty and set DocValues = false + public override void Visit(INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + type.DocValues = false; + } + + // Similarily, override the Visit method on IBooleanProperty and set DocValues = false + public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + type.DocValues = false; + } +} +---- + +Now we can pass an instance of our custom visitor to `.AutoMap()` + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) + ); +---- + +and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) + * it will apply the transformation defined in each Visit() respectively, which in this example + * disables {ref_current}/doc-values.html[doc values]. + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + employee = new + { + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + isManager = new + { + doc_values = false, + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + doc_values = false, + type = "integer" + } + } + } + } +}; +---- + +You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit + * directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types + * to an Elasticsearch string (`IStringProperty`). + +[source,csharp] +---- +public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor +{ + public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); +} + +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(new EverythingIsAStringPropertyVisitor())) + ); +var expected = new +{ + mappings = new + { + employee = new + { + properties = new + { + birthday = new + { + type = "string" + }, + employees = new + { + type = "string" + }, + firstName = new + { + type = "string" + }, + isManager = new + { + type = "string" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "string" + } + } + } + } +}; +---- + diff --git a/docs/asciidoc/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc similarity index 74% rename from docs/asciidoc/connecting.asciidoc rename to docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 67251c1c4ca..2ba414a38da 100644 --- a/docs/asciidoc/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -1,324 +1,294 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Connecting -Connecting to *Elasticsearch* with `Elasticsearch.Net` is quite easy but has a few toggles and options worth knowing. - -# Choosing the right connection strategy -If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` - - -[source, csharp] ----- -var client = new ElasticLowLevelClient(); -var tokenizers = new TokenizersDescriptor(); ----- - -If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then -you will need to pass in some instance of `IConnectionConfigurationValues`. - -The easiest way to do this is: - - -[source, csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); -var config = new ConnectionConfiguration(node); -var client = new ElasticLowLevelClient(config); ----- - -This however is still a non-failover connection. Meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. - -To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. - - -[source, csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); -var connectionPool = new SniffingConnectionPool(new[] { node }); -var config = new ConnectionConfiguration(connectionPool); -var client = new ElasticLowLevelClient(config); ----- - -Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. -Be sure to read more about [Connection Pooling and Cluster Failover here](/elasticsearch-net/cluster-failover.html) - -## Options - -Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: - - -[source, csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); -var connectionPool = new SniffingConnectionPool(new[] { node }); -var config = new ConnectionConfiguration(connectionPool) - .DisableDirectStreaming() - .BasicAuthentication("user", "pass") - .RequestTimeout(TimeSpan.FromSeconds(5)); ----- - -The following is a list of available connection configuration options: - - -[source, csharp] ----- -var client = new ElasticLowLevelClient(); ----- -Disable automatic proxy detection. Defaults to true. - - -Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured -to allow this. See the [http module settings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html) for more info). - - - -By default responses are deserialized off stream to the object you tell it to. -For debugging purposes it can be very useful to keep a copy of the raw response on the result object. - - -[source, csharp] ----- -var config = new ConnectionConfiguration() - - .DisableAutomaticProxyDetection() -.EnableHttpCompression() -.DisableDirectStreaming() - -var result = client.Search>(new { size = 12 }); -var raw = result.ResponseBodyInBytes; ----- -This will only have a value if the client configuration has ExposeRawResponse set - - -Please note that this only make sense if you need a mapped response and the raw response at the same time. -If you need a `string` or `byte[]` response simply call: - - -[source, csharp] ----- -var stringResult = client.Search(new { }); ----- - -Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. - - -Sets proxy information on the connection. - - -Sets the global maximum time a connection may take. -Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts -(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx). - - - -As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw -exceptions. - -There are three category of exceptions thay may be thrown: - -1) ElasticsearchClientException: These are known exceptions, either an exception that occurred in the request pipeline -(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could -not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property -on the response will contain the the actual error that was returned. The inner exception will always contain the -root causing exception. - -2) UnexpectedElasticsearchClientException: These are unknown exceptions, for instance a response from Elasticsearch not -properly deserialized. These are usually bugs and should be reported. This excpetion also inherits from ElasticsearchClientException -so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. - -3) Development time exceptions: These are CLR exceptions like ArgumentException, NullArgumentException etc... that are thrown -when an API in the client is misused. These should not be handled as you want to know about them during development. - - - - -Forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well - - -Sets the HTTP basic authentication credentials to specify with all requests. - -[source, csharp] ----- -config = config - //endhide - .GlobalQueryStringParameters(new NameValueCollection()) -.Proxy(new Uri("http://myproxy"), "username", "pass") -.RequestTimeout(TimeSpan.FromSeconds(4)) -.ThrowExceptions() -.PrettyJson() -.BasicAuthentication("username", "password") ----- - -**Note:** This can alternatively be specified on the node URI directly: - - -[source, csharp] ----- -var uri = new Uri("http://username:password@localhost:9200"); - -var settings = new ConnectionConfiguration(uri); ----- - -...but may become tedious when using connection pooling with multiple nodes. - - - -You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. -If you have complex logging needs this is a good place to add that in. - - -[source, csharp] ----- -var counter = 0; -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) - .OnRequestCompleted(r => counter++); -var client = new ElasticClient(settings); -client.RootNodeInfo(); -counter.Should().Be(1); -client.RootNodeInfoAsync(); -counter.Should().Be(2); ----- - -An example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like -to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` -to `true` - - -[source, csharp] ----- -var list = new List(); -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) - .DisableDirectStreaming() - .OnRequestCompleted(response => - { - // log out the request - if (response.RequestBodyInBytes != null) - { - list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); - } - else - { - list.Add($"{response.HttpMethod} {response.Uri}"); - } - - // log out the response - if (response.ResponseBodyInBytes != null) - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); - } - else - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); - } - }); -list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); -list.Add($"{response.HttpMethod} {response.Uri}"); -list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); -list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); -var client = new ElasticClient(settings); -var syncResponse = client.Search(s => s - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) - ); -list.Count.Should().Be(2); -var asyncResponse = await client.SearchAsync(s => s - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) - ); -list.Count.Should().Be(4); -list.ShouldAllBeEquivalentTo(new [] - { - "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", - "Status: 200\n------------------------------\n", - "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", - "Status: 200\n------------------------------\n" - }); ----- - -## Configuring SSL -SSL must be configured outside of the client using .NET's -[ServicePointManager](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx) -class and setting the [ServerCertificateValidationCallback](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx) -property. - -The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: - - -[source, csharp] ----- -ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; ----- - -However, this will accept all requests from the AppDomain to untrusted SSL sites, -therefore we recommend doing some minimal introspection on the passed in certificate. - - - -## Overriding default Json.NET behavior - -Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful - -Create a subclass of the `JsonNetSerializer` - - - - -Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` - - - -You can inject contract resolved converters by implementing the ContractConverters property -This can be much faster then registering them on JsonSerializerSettings.Converters - - -[source, csharp] ----- -public class MyJsonNetSerializer : JsonNetSerializer -{ - public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } -public int CallToModify { get; set; } = 0; - protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; -public int CallToContractConverter { get; set; } = 0; - protected override IList> ContractConverters => new List>() - { - { t => { - CallToContractConverter++; - return null; - } } - }; - -} ----- - -You can then register a factory on ConnectionSettings to create an instance of your subclass instead. -This is called once per instance of ConnectionSettings. - - -[source, csharp] ----- -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); -var client = new ElasticClient(settings); -client.RootNodeInfo(); -client.RootNodeInfo(); -var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; -serializer.CallToModify.Should().BeGreaterThan(0); -serializer.SerializeToString(new Project { }); -serializer.CallToContractConverter.Should().BeGreaterThan(0); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + += Choosing the right connection strategy + +[source,csharp] +---- +var client = new ElasticLowLevelClient(); +var tokenizers = new TokenizersDescriptor(); +---- + +If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then +you will need to pass in some instance of `IConnectionConfigurationValues`. + +The easiest way to do this is: + +[source,csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); +var config = new ConnectionConfiguration(node); +var client = new ElasticLowLevelClient(config); +---- + +This however is still a non-failover connection. Meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. + +To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. + +[source,csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); +var connectionPool = new SniffingConnectionPool(new[] { node }); +var config = new ConnectionConfiguration(connectionPool); +var client = new ElasticLowLevelClient(config); +---- + +Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. +Be sure to read more about [Connection Pooling and Cluster Failover here](/elasticsearch-net/cluster-failover.html) + +== Options + + Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: + +[source,csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); +var connectionPool = new SniffingConnectionPool(new[] { node }); +var config = new ConnectionConfiguration(connectionPool) + .DisableDirectStreaming() + .BasicAuthentication("user", "pass") + .RequestTimeout(TimeSpan.FromSeconds(5)); +---- + +The following is a list of available connection configuration options: + +[source,csharp] +---- +var client = new ElasticLowLevelClient(); +---- + +Disable automatic proxy detection. Defaults to true. + +Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured +to allow this. See the [http module settings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html) for more info). + +By default responses are deserialized off stream to the object you tell it to. +For debugging purposes it can be very useful to keep a copy of the raw response on the result object. + +[source,csharp] +---- +var config = new ConnectionConfiguration() + + .DisableAutomaticProxyDetection() +.EnableHttpCompression() +.DisableDirectStreaming() + +var result = client.Search>(new { size = 12 }); +var raw = result.ResponseBodyInBytes; +---- + +This will only have a value if the client configuration has ExposeRawResponse set + +Please note that this only make sense if you need a mapped response and the raw response at the same time. +If you need a `string` or `byte[]` response simply call: + +[source,csharp] +---- +var stringResult = client.Search(new { }); +---- + +Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. + +Sets proxy information on the connection. + +Sets the global maximum time a connection may take. +Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts +(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx). + +As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw +exceptions. + +There are three category of exceptions thay may be thrown: + +1) ElasticsearchClientException: These are known exceptions, either an exception that occurred in the request pipeline +(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could +not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property +on the response will contain the the actual error that was returned. The inner exception will always contain the +root causing exception. + +2) UnexpectedElasticsearchClientException: These are unknown exceptions, for instance a response from Elasticsearch not +properly deserialized. These are usually bugs and should be reported. This excpetion also inherits from ElasticsearchClientException +so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. + +3) Development time exceptions: These are CLR exceptions like ArgumentException, NullArgumentException etc... that are thrown +when an API in the client is misused. These should not be handled as you want to know about them during development. + +Forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well + +Sets the HTTP basic authentication credentials to specify with all requests. + +[source,csharp] +---- +config = config + //endhide + .GlobalQueryStringParameters(new NameValueCollection()) +.Proxy(new Uri("http://myproxy"), "username", "pass") +.RequestTimeout(TimeSpan.FromSeconds(4)) +.ThrowExceptions() +.PrettyJson() +.BasicAuthentication("username", "password") +---- + +**Note:** This can alternatively be specified on the node URI directly: + +[source,csharp] +---- +var uri = new Uri("http://username:password@localhost:9200"); + +var settings = new ConnectionConfiguration(uri); +---- + + ...but may become tedious when using connection pooling with multiple nodes. + +You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. +If you have complex logging needs this is a good place to add that in. + +[source,csharp] +---- +var counter = 0; +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + .OnRequestCompleted(r => counter++); +var client = new ElasticClient(settings); +client.RootNodeInfo(); +counter.Should().Be(1); +client.RootNodeInfoAsync(); +counter.Should().Be(2); +---- + +An example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like +to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` +to `true` + +[source,csharp] +---- +var list = new List(); +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + .DisableDirectStreaming() + .OnRequestCompleted(response => + { + // log out the request + if (response.RequestBodyInBytes != null) + { + list.Add( + $"{response.HttpMethod} {response.Uri} \n" + + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); + } + else + { + list.Add($"{response.HttpMethod} {response.Uri}"); + } + + // log out the response + if (response.ResponseBodyInBytes != null) + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + + $"{new string('-', 30)}\n"); + } + else + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{new string('-', 30)}\n"); + } + }); +list.Add( + $"{response.HttpMethod} {response.Uri} \n" + + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); +list.Add($"{response.HttpMethod} {response.Uri}"); +list.Add($"Status: {response.HttpStatusCode}\n" + + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + + $"{new string('-', 30)}\n"); +list.Add($"Status: {response.HttpStatusCode}\n" + + $"{new string('-', 30)}\n"); +var client = new ElasticClient(settings); +var syncResponse = client.Search(s => s + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) + ); +list.Count.Should().Be(2); +var asyncResponse = await client.SearchAsync(s => s + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) + ); +list.Count.Should().Be(4); +list.ShouldAllBeEquivalentTo(new [] + { + "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", + "Status: 200\n------------------------------\n", + "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", + "Status: 200\n------------------------------\n" + }); +---- + +== Configuring SSL + +SSL must be configured outside of the client using .NET's +[ServicePointManager](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx) +class and setting the [ServerCertificateValidationCallback](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx) +property. + +The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: + +[source,csharp] +---- +ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; +---- + +However, this will accept all requests from the AppDomain to untrusted SSL sites, +therefore we recommend doing some minimal introspection on the passed in certificate. + +== Overriding default Json.NET behavior + +Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful + +Create a subclass of the `JsonNetSerializer` + +Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` + +You can inject contract resolved converters by implementing the ContractConverters property +This can be much faster then registering them on JsonSerializerSettings.Converters + +[source,csharp] +---- +public class MyJsonNetSerializer : JsonNetSerializer +{ + public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } +public int CallToModify { get; set; } = 0; + protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; +public int CallToContractConverter { get; set; } = 0; + protected override IList> ContractConverters => new List>() + { + { t => { + CallToContractConverter++; + return null; + } } + }; + +} +---- + +You can then register a factory on ConnectionSettings to create an instance of your subclass instead. +This is called once per instance of ConnectionSettings. + +[source,csharp] +---- +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); +var client = new ElasticClient(settings); +client.RootNodeInfo(); +client.RootNodeInfo(); +var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; +serializer.CallToModify.Should().BeGreaterThan(0); +serializer.SerializeToString(new Project { }); +serializer.CallToContractConverter.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc similarity index 78% rename from docs/asciidoc/lifetimes.asciidoc rename to docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 313a3668ae4..c8a555233b7 100644 --- a/docs/asciidoc/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -1,82 +1,83 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - - -## Lifetimes - -If you are using an IOC container its always useful to know the best practices around the lifetime of your objects - -In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe -so sharing this instance over threads is ok. - -Zooming in however the actual moving part that benefits the most from being static for most of the duration of your -application is ConnectionSettings. Caches are per ConnectionSettings. - -In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different -connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. - -Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types - - -[source, csharp] ----- -class AConnectionSettings : ConnectionSettings -{ - public AConnectionSettings(IConnectionPool pool, IConnection connection) - : base(pool, connection) - { } - public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() - { - this.IsDisposed = true; - base.DisposeManagedResources(); - } -} - -class AConnectionPool : SingleNodeConnectionPool -{ - public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } - - public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() - { - this.IsDisposed = true; - base.DisposeManagedResources(); - } -} - -class AConnection : InMemoryConnection -{ - public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() - { - this.IsDisposed = true; - base.DisposeManagedResources(); - } -} ----- - -`ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` - - -[source, csharp] ----- -var connection = new AConnection(); -var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); -var settings = new AConnectionSettings(connectionPool, connection); -settings.IsDisposed.Should().BeFalse(); -connectionPool.IsDisposed.Should().BeFalse(); -connection.IsDisposed.Should().BeFalse(); ----- - -Disposing the ConnectionSettings will dispose the `IConnectionPool` and `IConnection` it has a hold of - - -[source, csharp] ----- -var connection = new AConnection(); -var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); -var settings = new AConnectionSettings(connectionPool, connection); -settings.IsDisposed.Should().BeTrue(); -connectionPool.IsDisposed.Should().BeTrue(); -connection.IsDisposed.Should().BeTrue(); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +== Lifetimes + +If you are using an IOC container its always useful to know the best practices around the lifetime of your objects + +In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe +so sharing this instance over threads is ok. + +Zooming in however the actual moving part that benefits the most from being static for most of the duration of your +application is ConnectionSettings. Caches are per ConnectionSettings. + +In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different +connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. + +Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types + +[source,csharp] +---- +class AConnectionSettings : ConnectionSettings +{ + public AConnectionSettings(IConnectionPool pool, IConnection connection) + : base(pool, connection) + { } + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } +} + +class AConnectionPool : SingleNodeConnectionPool +{ + public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } + + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } +} + +class AConnection : InMemoryConnection +{ + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } +} +---- + +`ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` + +[source,csharp] +---- +var connection = new AConnection(); +var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); +var settings = new AConnectionSettings(connectionPool, connection); +settings.IsDisposed.Should().BeFalse(); +connectionPool.IsDisposed.Should().BeFalse(); +connection.IsDisposed.Should().BeFalse(); +---- + +Disposing the ConnectionSettings will dispose the `IConnectionPool` and `IConnection` it has a hold of + +[source,csharp] +---- +var connection = new AConnection(); +var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); +var settings = new AConnectionSettings(connectionPool, connection); +settings.IsDisposed.Should().BeTrue(); +connectionPool.IsDisposed.Should().BeTrue(); +connection.IsDisposed.Should().BeTrue(); +---- + diff --git a/docs/asciidoc/post_data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc similarity index 83% rename from docs/asciidoc/post_data.asciidoc rename to docs/asciidoc/client-concepts/low-level/post-data.asciidoc index bd2322b36cd..07512df22ad 100644 --- a/docs/asciidoc/post_data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -1,106 +1,116 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Post data -The low level allows you to post a string, byte[] array directly. On top of this if you pass a list of strings or objects -they will be serialized in Elasticsearch's special bulk/multi format. - - -Even though the argument for postData on the low level client takes a PostData -You can rely on C# implicit conversion to abstract the notion of PostData completely. -You can implicitly convert from the following types. - -[source, csharp] ----- -var fromString = ImplicitlyConvertsFrom(@string); - -var fromByteArray = ImplicitlyConvertsFrom(bytes); -var fromListOfString = ImplicitlyConvertsFrom(listOfStrings); -var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); -var fromObject = ImplicitlyConvertsFrom(@object); ----- -postData Bytes will always be set if it originated from a byte - -[source, csharp] ----- -fromByteArray.WrittenBytes.Should().BeSameAs(bytes); - -fromString.Type.Should().Be(PostType.LiteralString); -fromByteArray.Type.Should().Be(PostType.ByteArray); -fromListOfString.Type.Should().Be(PostType.EnumerableOfString); -fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); -fromObject.Type.Should().Be(PostType.Serializable); -fromString = ImplicitlyConvertsFrom(fromString); -fromByteArray = ImplicitlyConvertsFrom(fromByteArray); -fromListOfString = ImplicitlyConvertsFrom(fromListOfString); -fromListOfObject = ImplicitlyConvertsFrom(fromListOfObject); -fromObject = ImplicitlyConvertsFrom(fromObject); -fromString.Type.Should().Be(PostType.LiteralString); -fromByteArray.Type.Should().Be(PostType.ByteArray); -fromListOfString.Type.Should().Be(PostType.EnumerableOfString); -fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); -fromObject.Type.Should().Be(PostType.Serializable); -await this.AssertOn(new ConnectionSettings()); -await this.AssertOn(new ConnectionConfiguration()); ----- -Although each implicitly types behaves slightly differently - -[source, csharp] ----- -await Post(()=>@string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); - -await Post(()=>bytes, writes: bytes, storesBytes: true, settings: settings); ----- -When passing a list of strings we assume its a list of valid serialized json that we -join with newlinefeeds making sure there is a trailing linefeed - -[source, csharp] ----- -await Post(()=>listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); ----- - -When passing a list of object we assume its a list of objects we need to serialize -individually to json and join with newlinefeeds aking sure there is a trailing linefeed - - -[source, csharp] ----- -await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); ----- -In all other cases postdata is serialized as is. - -[source, csharp] ----- -await Post(()=>@object, writes: objectJson, storesBytes: false, settings: settings); ----- -If you want to maintain a copy of the request that went out use the following settings - -[source, csharp] ----- -settings = new ConnectionSettings().DisableDirectStreaming(); ----- -by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream -so we can get a hold of the serialized bytes - -[source, csharp] ----- -await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); ----- -this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` - -[source, csharp] ----- -await Post(()=>@object, writes: objectJson, storesBytes: true, settings: settings); - -PostAssert(postData(), writes, storesBytes, settings); -await PostAssertAsync(postData(), writes, storesBytes, settings); -postData.Write(ms, settings); -var sentBytes = ms.ToArray(); -sentBytes.Should().Equal(writes); -postData.WrittenBytes.Should().NotBeNull(); -postData.WrittenBytes.Should().BeNull(); -await postData.WriteAsync(ms, settings); -var sentBytes = ms.ToArray(); -sentBytes.Should().Equal(writes); -postData.WrittenBytes.Should().NotBeNull(); -postData.WrittenBytes.Should().BeNull(); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + += Post data + +they will be serialized in Elasticsearch's special bulk/multi format. + +Even though the argument for postData on the low level client takes a PostData +You can rely on C implicit conversion to abstract the notion of PostData completely. +You can implicitly convert from the following types. + +[source,csharp] +---- +var fromString = ImplicitlyConvertsFrom(@string); + +var fromByteArray = ImplicitlyConvertsFrom(bytes); +var fromListOfString = ImplicitlyConvertsFrom(listOfStrings); +var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); +var fromObject = ImplicitlyConvertsFrom(@object); +---- + +postData Bytes will always be set if it originated from a byte + +[source,csharp] +---- +fromByteArray.WrittenBytes.Should().BeSameAs(bytes); + +fromString.Type.Should().Be(PostType.LiteralString); +fromByteArray.Type.Should().Be(PostType.ByteArray); +fromListOfString.Type.Should().Be(PostType.EnumerableOfString); +fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); +fromObject.Type.Should().Be(PostType.Serializable); +fromString = ImplicitlyConvertsFrom(fromString); +fromByteArray = ImplicitlyConvertsFrom(fromByteArray); +fromListOfString = ImplicitlyConvertsFrom(fromListOfString); +fromListOfObject = ImplicitlyConvertsFrom(fromListOfObject); +fromObject = ImplicitlyConvertsFrom(fromObject); +fromString.Type.Should().Be(PostType.LiteralString); +fromByteArray.Type.Should().Be(PostType.ByteArray); +fromListOfString.Type.Should().Be(PostType.EnumerableOfString); +fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); +fromObject.Type.Should().Be(PostType.Serializable); +await this.AssertOn(new ConnectionSettings()); +await this.AssertOn(new ConnectionConfiguration()); +---- + +Although each implicitly types behaves slightly differently + +[source,csharp] +---- +await Post(()=>@string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); + +await Post(()=>bytes, writes: bytes, storesBytes: true, settings: settings); +---- + +When passing a list of strings we assume its a list of valid serialized json that we +join with newlinefeeds making sure there is a trailing linefeed + +[source,csharp] +---- +await Post(()=>listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); +---- + +When passing a list of object we assume its a list of objects we need to serialize +individually to json and join with newlinefeeds aking sure there is a trailing linefeed + +[source,csharp] +---- +await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); +---- + +In all other cases postdata is serialized as is. + +[source,csharp] +---- +await Post(()=>@object, writes: objectJson, storesBytes: false, settings: settings); +---- + +If you want to maintain a copy of the request that went out use the following settings + +[source,csharp] +---- +settings = new ConnectionSettings().DisableDirectStreaming(); +---- + +by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream +so we can get a hold of the serialized bytes + +[source,csharp] +---- +await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); +---- + +this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` + +[source,csharp] +---- +await Post(()=>@object, writes: objectJson, storesBytes: true, settings: settings); + +PostAssert(postData(), writes, storesBytes, settings); +await PostAssertAsync(postData(), writes, storesBytes, settings); +postData.Write(ms, settings); +var sentBytes = ms.ToArray(); +sentBytes.Should().Equal(writes); +postData.WrittenBytes.Should().NotBeNull(); +postData.WrittenBytes.Should().BeNull(); +await postData.WriteAsync(ms, settings); +var sentBytes = ms.ToArray(); +sentBytes.Should().Equal(writes); +postData.WrittenBytes.Should().NotBeNull(); +postData.WrittenBytes.Should().BeNull(); +---- + diff --git a/docs/asciidoc/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc similarity index 55% rename from docs/asciidoc/descriptors.asciidoc rename to docs/asciidoc/code-standards/descriptors.asciidoc index dcc4e0624f0..9bbe9ec0ac1 100644 --- a/docs/asciidoc/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -1,54 +1,56 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - - -Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface - - -[source, csharp] ----- -var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; -var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() - where t.IsClass() - && t.Name.Contains("Descriptor") - && !notDescriptors.Contains(t.Name) - && !t.GetInterfaces().Any(i => i == typeof(IDescriptor)) - select t.FullName; -descriptors.Should().BeEmpty(); ----- - -Methods taking a func should have that func return an interface - - -[source, csharp] ----- -var descriptors = - from t in typeof(DescriptorBase<,>).Assembly().Types() - where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) - select t; -var selectorMethods = - from d in descriptors - from m in d.GetMethods() - let parameters = m.GetParameters() - from p in parameters - let type = p.ParameterType - let isGeneric = type.IsGeneric() - where isGeneric - let isFunc = type.GetGenericTypeDefinition() == typeof(Func<,>) - where isFunc - let firstFuncArg = type.GetGenericArguments().First() - let secondFuncArg = type.GetGenericArguments().Last() - let isQueryFunc = firstFuncArg.IsGeneric() && - firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) && - typeof(QueryContainer).IsAssignableFrom(secondFuncArg) - where !isQueryFunc - let isFluentDictionaryFunc = - firstFuncArg.IsGeneric() && - firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) && - secondFuncArg.IsGeneric() && - secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) - where !isFluentDictionaryFunc - let lastArgIsNotInterface = !secondFuncArg.IsInterface() - where lastArgIsNotInterface - select $"{m.Name} on {m.DeclaringType.Name}"; -selectorMethods.Should().BeEmpty(); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../images/ + +Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface + +[source,csharp] +---- +var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; +var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() + where t.IsClass() + && t.Name.Contains("Descriptor") + && !notDescriptors.Contains(t.Name) + && !t.GetInterfaces().Any(i => i == typeof(IDescriptor)) + select t.FullName; +descriptors.Should().BeEmpty(); +---- + +Methods taking a func should have that func return an interface + +[source,csharp] +---- +var descriptors = + from t in typeof(DescriptorBase<,>).Assembly().Types() + where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) + select t; +var selectorMethods = + from d in descriptors + from m in d.GetMethods() + let parameters = m.GetParameters() + from p in parameters + let type = p.ParameterType + let isGeneric = type.IsGeneric() + where isGeneric + let isFunc = type.GetGenericTypeDefinition() == typeof(Func<,>) + where isFunc + let firstFuncArg = type.GetGenericArguments().First() + let secondFuncArg = type.GetGenericArguments().Last() + let isQueryFunc = firstFuncArg.IsGeneric() && + firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) && + typeof(QueryContainer).IsAssignableFrom(secondFuncArg) + where !isQueryFunc + let isFluentDictionaryFunc = + firstFuncArg.IsGeneric() && + firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) && + secondFuncArg.IsGeneric() && + secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) + where !isFluentDictionaryFunc + let lastArgIsNotInterface = !secondFuncArg.IsInterface() + where lastArgIsNotInterface + select $"{m.Name} on {m.DeclaringType.Name}"; +selectorMethods.Should().BeEmpty(); +---- + diff --git a/docs/asciidoc/elastic_client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc similarity index 80% rename from docs/asciidoc/elastic_client.asciidoc rename to docs/asciidoc/code-standards/elastic-client.asciidoc index 5207fbd972f..dde8600a29d 100644 --- a/docs/asciidoc/elastic_client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -1,26 +1,30 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ -[source, csharp] +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../images/ + +[source,csharp] ---- var fluentParametersNotNamedSelector = - from m in typeof (IElasticClient).GetMethods() - from p in m.GetParameters() - where p.ParameterType.BaseType() == typeof (MulticastDelegate) - where !p.Name.Equals("selector") - select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'selector' but has a name of '{p.Name}'"; + from m in typeof (IElasticClient).GetMethods() + from p in m.GetParameters() + where p.ParameterType.BaseType() == typeof (MulticastDelegate) + where !p.Name.Equals("selector") + select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'selector' but has a name of '{p.Name}'"; fluentParametersNotNamedSelector.Should().BeEmpty(); var requestParametersNotNamedRequest = - from m in typeof(IElasticClient).GetMethods() - from p in m.GetParameters() - where typeof(IRequest).IsAssignableFrom(p.ParameterType) - where !p.Name.Equals("request") - select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'request' but has a name of '{p.Name}'"; + from m in typeof(IElasticClient).GetMethods() + from p in m.GetParameters() + where typeof(IRequest).IsAssignableFrom(p.ParameterType) + where !p.Name.Equals("request") + select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'request' but has a name of '{p.Name}'"; requestParametersNotNamedRequest.Should().BeEmpty(); var requestParameters = - (from m in typeof(IElasticClient).GetMethods() - from p in m.GetParameters() - where typeof(IRequest).IsAssignableFrom(p.ParameterType) - select p).ToList(); + (from m in typeof(IElasticClient).GetMethods() + from p in m.GetParameters() + where typeof(IRequest).IsAssignableFrom(p.ParameterType) + select p).ToList(); requestParameter.HasDefaultValue.Should().BeFalse(); var concreteMethodParametersDoNotMatchInterface = new List(); var interfaceMap = typeof(ElasticClient).GetInterfaceMap(typeof(IElasticClient)); @@ -94,3 +98,4 @@ private class MethodWithRequestParameter } } ---- + diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc new file mode 100644 index 00000000000..9c6e9843182 --- /dev/null +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -0,0 +1,130 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../images/ + += Naming Conventions + +NEST uses the following naming conventions (with _some_ exceptions). + +== Class Names + +Abstract class names should end with a `Base` suffix + +[source,csharp] +---- +var exceptions = new[] +{ + typeof(DateMath) +}; +var abstractClasses = typeof(IRequest).Assembly().GetTypes() + .Where(t => t.IsClass() && t.IsAbstract() && !t.IsSealed() && !exceptions.Contains(t)) + .Where(t => !t.Name.Split('`')[0].EndsWith("Base")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +abstractClasses.Should().BeEmpty(); +---- + +Class names that end with `Base` suffix are abstract + +[source,csharp] +---- +var exceptions = new[] { typeof(DateMath) }; +var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() + .Where(t => t.IsClass() && !exceptions.Contains(t)) + .Where(t => t.Name.Split('`')[0].EndsWith("Base")) + .Where(t => !t.IsAbstractClass()) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +baseClassesNotAbstract.Should().BeEmpty(); +---- + +== Requests and Responses + +Request class names should end with `Request` + +[source,csharp] +---- +var types = typeof(IRequest).Assembly().GetTypes(); +var requests = types + .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) + .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) + .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +requests.Should().BeEmpty(); +---- + +Response class names should end with `Response` + +[source,csharp] +---- +var types = typeof(IRequest).Assembly().GetTypes(); +var responses = types + .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) + .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); +responses.Should().BeEmpty(); +---- + +Request and Response class names should be one to one in *most* cases. +e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => `ValidateResponse` +There are a few exceptions to this rule, most notably the `Cat` prefixed requests and +`Exists` requests. + +[source,csharp] +---- +var exceptions = new[] +{ + typeof(CatAliasesRequest), + typeof(CatAllocationRequest), + typeof(CatCountRequest), + typeof(CatFielddataRequest), + typeof(CatHealthRequest), + typeof(CatHelpRequest), + typeof(CatIndicesRequest), + typeof(CatMasterRequest), + typeof(CatNodesRequest), + typeof(CatPendingTasksRequest), + typeof(CatPluginsRequest), + typeof(CatRecoveryRequest), + typeof(CatSegmentsRequest), + typeof(CatShardsRequest), + typeof(CatThreadPoolRequest), + typeof(DocumentExistsRequest), + typeof(DocumentExistsRequest<>), + typeof(AliasExistsRequest), + typeof(IndexExistsRequest), + typeof(TypeExistsRequest), + typeof(IndexTemplateExistsRequest), + typeof(SearchExistsRequest), + typeof(SearchExistsRequest<>), + typeof(SearchTemplateRequest), + typeof(SearchTemplateRequest<>), + typeof(ScrollRequest), + typeof(SourceRequest), + typeof(SourceRequest<>), + typeof(ValidateQueryRequest<>), + typeof(GetAliasRequest), + typeof(CatNodeattrsRequest), + typeof(IndicesShardStoresRequest), + typeof(RenderSearchTemplateRequest) +}; +var types = typeof(IRequest).Assembly().GetTypes(); +var requests = new HashSet(types + .Where(t => + t.IsClass() && + !t.IsAbstract() && + typeof(IRequest).IsAssignableFrom(t) && + !typeof(IDescriptor).IsAssignableFrom(t) + && !exceptions.Contains(t)) + .Select(t => t.Name.Split('`')[0].Replace("Request", "")) +); +var responses = types + .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) + .Select(t => t.Name.Split('`')[0].Replace("Response", "")); +requests.Except(responses).Should().BeEmpty(); +---- + diff --git a/docs/asciidoc/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc similarity index 54% rename from docs/asciidoc/queries.asciidoc rename to docs/asciidoc/code-standards/queries.asciidoc index fb845b9b1ca..f5926e9f830 100644 --- a/docs/asciidoc/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -1,33 +1,38 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ -[source, csharp] +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../images/ + +[source,csharp] ---- var properties = from p in QueryProperties - let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) - where a.Count() != 1 - select p; + let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) + where a.Count() != 1 + select p; properties.Should().BeEmpty(); var staticProperties = from p in typeof(Query<>).GetMethods() - let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name - select name; + let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name + select name; var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name); staticProperties.Distinct().Should().Contain(placeHolders.Distinct()); var fluentMethods = from p in typeof(QueryContainerDescriptor<>).GetMethods() - let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name - select name; + let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name + select name; var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name); fluentMethods.Distinct().Should().Contain(placeHolders.Distinct()); var skipQueryImplementations = new[] { typeof(IFieldNameQuery), typeof(IFuzzyQuery<,>), typeof(IConditionlessQuery) }; var queries = typeof(IQuery).Assembly().ExportedTypes - .Where(t => t.IsInterface() && typeof(IQuery).IsAssignableFrom(t)) - .Where(t => !skipQueryImplementations.Contains(t)) - .ToList(); + .Where(t => t.IsInterface() && typeof(IQuery).IsAssignableFrom(t)) + .Where(t => !skipQueryImplementations.Contains(t)) + .ToList(); queries.Should().NotBeEmpty(); var visitMethods = typeof(IQueryVisitor).GetMethods().Where(m => m.Name == "Visit"); visitMethods.Should().NotBeEmpty(); var missingTypes = from q in queries - let visitMethod = visitMethods.FirstOrDefault(m => m.GetParameters().First().ParameterType == q) - where visitMethod == null - select q; + let visitMethod = visitMethods.FirstOrDefault(m => m.GetParameters().First().ParameterType == q) + where visitMethod == null + select q; missingTypes.Should().BeEmpty(); ---- + diff --git a/docs/asciidoc/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc similarity index 79% rename from docs/asciidoc/properties.asciidoc rename to docs/asciidoc/code-standards/serialization/properties.asciidoc index 8766c544364..ecf0d8aed97 100644 --- a/docs/asciidoc/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -1,18 +1,21 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - - -Our Json.NET contract resolver picks up attributes set on the interface - - -[source, csharp] ----- -var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(pool, new InMemoryConnection()); -var c = new ElasticClient(settings); -var serialized = c.Serializer.SerializeToString(new Nest.Analysis { CharFilters = new CharFilters() }); -serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); -serialized.Should().Contain("char_filter"); -serialized = c.Serializer.SerializeToString(new AnalysisDescriptor().CharFilters(cf=>cf)); -serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); -serialized.Should().Contain("char_filter"); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +Our Json.NET contract resolver picks up attributes set on the interface + +[source,csharp] +---- +var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); +var settings = new ConnectionSettings(pool, new InMemoryConnection()); +var c = new ElasticClient(settings); +var serialized = c.Serializer.SerializeToString(new Nest.Analysis { CharFilters = new CharFilters() }); +serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); +serialized.Should().Contain("char_filter"); +serialized = c.Serializer.SerializeToString(new AnalysisDescriptor().CharFilters(cf=>cf)); +serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); +serialized.Should().Contain("char_filter"); +---- + diff --git a/docs/asciidoc/date_math_expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc similarity index 55% rename from docs/asciidoc/date_math_expressions.asciidoc rename to docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index b8e9f87bde7..bfb9304e59f 100644 --- a/docs/asciidoc/date_math_expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -1,91 +1,122 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Date Expressions -The date type supports using date math expression when using it in a query/filter -Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified - -The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with ||. -It can then follow by a math expression, supporting +, - and / (rounding). -The units supported are y (year), M (month), w (week), d (day), h (hour), m (minute), and s (second). -as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. - -Be sure to read the elasticsearch documentation {ref}/mapping-date-format.html#date-math[on this subject here] - - - -You can create simple expressions using any of the static methods on `DateMath` - -[source, csharp] ----- -Expect("now").WhenSerializing(Nest.DateMath.Now); - -Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05, 05))); ----- -strings implicitly convert to date maths - -[source, csharp] ----- -Expect("now").WhenSerializing("now"); ----- -but are lenient to bad math expressions - -[source, csharp] ----- -var nonsense = "now||*asdaqwe"; ----- -the resulting date math will assume the whole string is the anchor - -[source, csharp] ----- -Expect(nonsense).WhenSerializing(nonsense) -.Result(dateMath => ((IDateMath)dateMath) - .Anchor.Match( - d => d.Should().NotBe(default(DateTime)), - s => s.Should().Be(nonsense) - ) - ); ----- -date's also implicitly convert to simple date math expressions - -[source, csharp] ----- -var date = new DateTime(2015, 05, 05); ----- -the anchor will be an actual DateTime, even after a serialization - deserialization round trip - -[source, csharp] ----- -Expect("2015-05-05T00:00:00").WhenSerializing(date) -.Result(dateMath => ((IDateMath)dateMath) - . Anchor.Match( - d => d.Should().Be(date), - s => s.Should().BeNull() - ) - ); ----- -Ranges can be chained on to simple expressions - -[source, csharp] ----- -Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); ----- -plural means that you can chain multiple - -[source, csharp] ----- -Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); ----- -a rounding value can also be chained at the end afterwhich no more ranges can be appended - -[source, csharp] ----- -Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); ----- -When anchoring date's we need to append `||` as clear separator between anchor and ranges - -plural means that you can chain multiple - -[source, csharp] ----- -Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +== Date Math Expressions + +The date type supports using date math expression when using it in a query/filter +Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified + +The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with `||`. +It can then follow by a math expression, supporting `+`, `-` and `/` (rounding). +The units supported are + +* `y` (year) + +* `M` (month) + +* `w` (week) + +* `d` (day) + +* `h` (hour) + +* `m` (minute) + +* `s` (second) + +as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. + +Be sure to read the elasticsearch documentation {ref_current}/mapping-date-format.htmldate-math[on this subject here] + +=== Simple Expressions + +You can create simple expressions using any of the static methods on `DateMath` + +[source,csharp] +---- +Expect("now").WhenSerializing(Nest.DateMath.Now); + +Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05, 05))); +---- + +strings implicitly convert to `DateMath` + +[source,csharp] +---- +Expect("now").WhenSerializing("now"); +---- + +but are lenient to bad math expressions + +[source,csharp] +---- +var nonsense = "now||*asdaqwe"; +---- + +the resulting date math will assume the whole string is the anchor + +[source,csharp] +---- +Expect(nonsense).WhenSerializing(nonsense) +.Result(dateMath => ((IDateMath)dateMath) + .Anchor.Match( + d => d.Should().NotBe(default(DateTime)), + s => s.Should().Be(nonsense) + ) + ); +---- + +`DateTime` also implicitly convert to simple date math expressions + +[source,csharp] +---- +var date = new DateTime(2015, 05, 05); +---- + +the anchor will be an actual `DateTime`, even after a serialization/deserialization round trip + +[source,csharp] +---- +Expect("2015-05-05T00:00:00").WhenSerializing(date) +.Result(dateMath => ((IDateMath)dateMath) + . Anchor.Match( + d => d.Should().Be(date), + s => s.Should().BeNull() + ) + ); +---- + +=== Complex Expressions + +Ranges can be chained on to simple expressions + +[source,csharp] +---- +Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); +---- + +Including multiple operations + +[source,csharp] +---- +Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); +---- + +A rounding value can be chained to the end of the expression, after which no more ranges can be appended + +[source,csharp] +---- +Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); +---- + +When anchoring dates, a `||` needs to be appended as clear separator between the anchor and ranges. +Again, multiple ranges can be chained + +[source,csharp] +---- +Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); +---- + diff --git a/docs/asciidoc/time_units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc similarity index 71% rename from docs/asciidoc/time_units.asciidoc rename to docs/asciidoc/common-options/time-unit/time-units.asciidoc index fe1d7422eb7..80caeaaaa44 100644 --- a/docs/asciidoc/time_units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -1,119 +1,125 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Time units -Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified -as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. - -## Using Time units in NEST -NEST uses `Time` to strongly type this and there are several ways to construct one. - -### Constructor -The most straight forward way to construct a `Time` is through its constructor - - -[source, csharp] ----- -var unitString = new Time("2d"); -var unitComposed = new Time(2, Nest.TimeUnit.Day); -var unitTimeSpan = new Time(TimeSpan.FromDays(2)); -var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); ----- - -When serializing Time constructed from a string, milliseconds, composition of factor and -interval, or a `TimeSpan` the expression will be serialized as time unit string - - -[source, csharp] ----- -Expect("2d") - .WhenSerializing(unitString) - .WhenSerializing(unitComposed) - .WhenSerializing(unitTimeSpan) - .WhenSerializing(unitMilliseconds); ----- - -Milliseconds are always calculated even when not using the constructor that takes a long - - -[source, csharp] ----- -unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); - -unitComposed.Milliseconds.Should().Be(1000*60*60*24*2); -unitTimeSpan.Milliseconds.Should().Be(1000*60*60*24*2); -unitString.Milliseconds.Should().Be(1000*60*60*24*2); ----- - -### Implicit conversion -Alternatively `string`, `TimeSpan` and `double` can be implicitly assigned to `Time` properties and variables - - -[source, csharp] ----- -Time oneAndHalfYear = "1.5y"; -Time twoWeeks = TimeSpan.FromDays(14); -Time twoDays = 1000*60*60*24*2; -Expect("1.5y").WhenSerializing(oneAndHalfYear); -Expect("2w").WhenSerializing(twoWeeks); -Expect("2d").WhenSerializing(twoDays); -Time oneAndHalfYear = "1.5y"; -Time twoWeeks = TimeSpan.FromDays(14); -Time twoDays = 1000*60*60*24*2; ----- - -Milliseconds are calculated even when values are not passed as long - - -[source, csharp] ----- -oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); - -twoWeeks.Milliseconds.Should().BeGreaterThan(1); ----- - -This allows you to do comparisons on the expressions - - -[source, csharp] ----- -oneAndHalfYear.Should().BeGreaterThan(twoWeeks); - -(oneAndHalfYear > twoWeeks).Should().BeTrue(); -(oneAndHalfYear >= twoWeeks).Should().BeTrue(); -(twoDays >= new Time("2d")).Should().BeTrue(); -twoDays.Should().BeLessThan(twoWeeks); -(twoDays < twoWeeks).Should().BeTrue(); -(twoDays <= twoWeeks).Should().BeTrue(); -(twoDays <= new Time("2d")).Should().BeTrue(); ----- - -And assert equality - - -[source, csharp] ----- -twoDays.Should().Be(new Time("2d")); - -(twoDays == new Time("2d")).Should().BeTrue(); -(twoDays != new Time("2.1d")).Should().BeTrue(); -(new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue(); ----- - -Time units are specified as a union of either a `DateInterval` or `Time` -both of which implicitly convert to the `Union` of these two. - - -[source, csharp] ----- -Expect("month").WhenSerializing>(DateInterval.Month); - -Expect("day").WhenSerializing>(DateInterval.Day); -Expect("hour").WhenSerializing>(DateInterval.Hour); -Expect("minute").WhenSerializing>(DateInterval.Minute); -Expect("quarter").WhenSerializing>(DateInterval.Quarter); -Expect("second").WhenSerializing>(DateInterval.Second); -Expect("week").WhenSerializing>(DateInterval.Week); -Expect("year").WhenSerializing>(DateInterval.Year); -Expect("2d").WhenSerializing>((Time)"2d"); -Expect("1.16w").WhenSerializing>((Time)TimeSpan.FromDays(8.1)); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +== Time units + +Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified +as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. + +=== Using Time units in NEST + +NEST uses `Time` to strongly type this and there are several ways to construct one. + +==== Constructor + +The most straight forward way to construct a `Time` is through its constructor + +[source,csharp] +---- +var unitString = new Time("2d"); +var unitComposed = new Time(2, Nest.TimeUnit.Day); +var unitTimeSpan = new Time(TimeSpan.FromDays(2)); +var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); +---- + +When serializing Time constructed from + +* a string + +* milliseconds (as a double) + +* composition of factor and interval + +* a `TimeSpan` + +the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` + +[source,csharp] +---- +Expect("2d") + .WhenSerializing(unitString) + .WhenSerializing(unitComposed) + .WhenSerializing(unitTimeSpan) + .WhenSerializing(unitMilliseconds); +---- + +The `Milliseconds` property on `Time` is calculated even when not using the constructor that takes a double + +[source,csharp] +---- +unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); + +unitComposed.Milliseconds.Should().Be(1000*60*60*24*2); +unitTimeSpan.Milliseconds.Should().Be(1000*60*60*24*2); +unitString.Milliseconds.Should().Be(1000*60*60*24*2); +---- + +==== Implicit conversion + +Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` + +[source,csharp] +---- +Time oneAndHalfYear = "1.5y"; +Time twoWeeks = TimeSpan.FromDays(14); +Time twoDays = 1000*60*60*24*2; +Expect("1.5y").WhenSerializing(oneAndHalfYear); +Expect("2w").WhenSerializing(twoWeeks); +Expect("2d").WhenSerializing(twoDays); +Time oneAndHalfYear = "1.5y"; +Time twoWeeks = TimeSpan.FromDays(14); +Time twoDays = 1000*60*60*24*2; +---- + +Again, the `Milliseconds` property is calculated on `Time`, +allowing you to do comparisons + +[source,csharp] +---- +oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); + +twoWeeks.Milliseconds.Should().BeGreaterThan(1); +oneAndHalfYear.Should().BeGreaterThan(twoWeeks); +(oneAndHalfYear > twoWeeks).Should().BeTrue(); +(oneAndHalfYear >= twoWeeks).Should().BeTrue(); +(twoDays >= new Time("2d")).Should().BeTrue(); +twoDays.Should().BeLessThan(twoWeeks); +(twoDays < twoWeeks).Should().BeTrue(); +(twoDays <= twoWeeks).Should().BeTrue(); +(twoDays <= new Time("2d")).Should().BeTrue(); +---- + +And assert equality + +[source,csharp] +---- +twoDays.Should().Be(new Time("2d")); + +(twoDays == new Time("2d")).Should().BeTrue(); +(twoDays != new Time("2.1d")).Should().BeTrue(); +(new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue(); +---- + +=== Time units + +Time units are specified as a union of either a `DateInterval` or `Time`, +both of which implicitly convert to the `Union` of these two. + +[source,csharp] +---- +Expect("month").WhenSerializing>(DateInterval.Month); + +Expect("day").WhenSerializing>(DateInterval.Day); +Expect("hour").WhenSerializing>(DateInterval.Hour); +Expect("minute").WhenSerializing>(DateInterval.Minute); +Expect("quarter").WhenSerializing>(DateInterval.Quarter); +Expect("second").WhenSerializing>(DateInterval.Second); +Expect("week").WhenSerializing>(DateInterval.Week); +Expect("year").WhenSerializing>(DateInterval.Year); +Expect("2d").WhenSerializing>((Time)"2d"); +Expect("1.16w").WhenSerializing>((Time)TimeSpan.FromDays(8.1)); +---- + diff --git a/docs/asciidoc/disable_sniff_ping_per_request.asciidoc b/docs/asciidoc/disable_sniff_ping_per_request.asciidoc deleted file mode 100644 index a0df0b0e0b7..00000000000 --- a/docs/asciidoc/disable_sniff_ping_per_request.asciidoc +++ /dev/null @@ -1,79 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Disabling sniffing and pinging on a request basis - -Even if you are using a sniffing connection pool thats set up to sniff on start/failure -and pinging enabled, you can opt out of this behaviour on a per request basis - -In our first test we set up a cluster that pings and sniffs on startup -but we disable the sniffing on our first request so we only see the ping and the response - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); ----- - -We disable sniffing so eventhoug its our first call we do not want to sniff on startup - - - -Instead the sniff on startup is deffered to the second call into the cluster that -does not disable sniffing on a per request basis - - - -And after that no sniff on startup will happen again - - -[source, csharp] ----- -audit = await audit.TraceCalls( -new ClientCall(r=>r.DisableSniffing()) { - { PingSuccess, 9200 }, - { HealthyResponse, 9200 } - }, -new ClientCall() - { - { SniffOnStartup }, - { SniffSuccess, 9200 }, - { PingSuccess, 9200 }, - { HealthyResponse, 9200 } - }, -new ClientCall() - { - { PingSuccess, 9201 }, - { HealthyResponse, 9201 } - } - ); - -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); -audit = await audit.TraceCall( - new ClientCall(r=>r.DisablePing()) { - { SniffOnStartup }, - { SniffSuccess, 9200 }, - { HealthyResponse, 9200 } - } - ); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); -audit = await audit.TraceCall( - new ClientCall(r=>r.DisableSniffing().DisablePing()) { - { HealthyResponse, 9200 } - } - ); ----- diff --git a/docs/asciidoc/falling_over.asciidoc b/docs/asciidoc/falling_over.asciidoc deleted file mode 100644 index fe4606f88df..00000000000 --- a/docs/asciidoc/falling_over.asciidoc +++ /dev/null @@ -1,84 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Fail over -When using connection pooling and the pool has sufficient nodes a request will be retried if -the call to a node throws an exception or returns a 502 or 503 - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } - ); ----- -=== 502 Bad Gateway - -Will be treated as an error that requires retrying - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(502)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } - ); ----- -=== 503 Service Unavailable - -Will be treated as an error that requires retrying - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(503)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } - ); ----- - -If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(418)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - } - ); ----- diff --git a/src/Tests/QueryDsl/BoolDsl/hadouken_indentation.jpg b/docs/asciidoc/images/hadouken-indentation.jpg similarity index 100% rename from src/Tests/QueryDsl/BoolDsl/hadouken_indentation.jpg rename to docs/asciidoc/images/hadouken-indentation.jpg diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 41313633127..897e079d6ba 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -36,6 +36,7 @@ We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest === License +.... This software is licensed under the Apache 2 license, quoted below. Copyright (c) 2014 Elasticsearch @@ -51,5 +52,6 @@ This software is licensed under the Apache 2 license, quoted below. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +.... diff --git a/docs/asciidoc/naming_conventions.asciidoc b/docs/asciidoc/naming_conventions.asciidoc deleted file mode 100644 index 2614827f0ac..00000000000 --- a/docs/asciidoc/naming_conventions.asciidoc +++ /dev/null @@ -1,130 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Naming Conventions - -NEST uses the following naming conventions (with _some_ exceptions). - - -## Class Names - -Abstract class names should end with a `Base` suffix - - -[source, csharp] ----- -var exceptions = new[] - { - typeof(DateMath) - }; -var abstractClasses = typeof(IRequest).Assembly().GetTypes() - .Where(t => t.IsClass() && t.IsAbstract() && !t.IsSealed() && !exceptions.Contains(t)) - .Where(t => !t.Name.Split('`')[0].EndsWith("Base")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -abstractClasses.Should().BeEmpty(); ----- - -Class names that end with `Base` suffix are abstract - - -[source, csharp] ----- -var exceptions = new[] { typeof(DateMath) }; -var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() - .Where(t => t.IsClass() && !exceptions.Contains(t)) - .Where(t => t.Name.Split('`')[0].EndsWith("Base")) - .Where(t => !t.IsAbstractClass()) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -baseClassesNotAbstract.Should().BeEmpty(); ----- -## Requests and Responses - -Request class names should end with `Request` - - -[source, csharp] ----- -var types = typeof(IRequest).Assembly().GetTypes(); -var requests = types - .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) - .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) - .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -requests.Should().BeEmpty(); ----- - -Response class names should end with `Response` - - -[source, csharp] ----- -var types = typeof(IRequest).Assembly().GetTypes(); -var responses = types - .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) - .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); -responses.Should().BeEmpty(); ----- - -Request and Response class names should be one to one in *most* cases. -e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => `ValidateResponse` -There are a few exceptions to this rule, most notably the `Cat` prefixed requests and -`Exists` requests. - - -[source, csharp] ----- -var exceptions = new[] - { - typeof(CatAliasesRequest), - typeof(CatAllocationRequest), - typeof(CatCountRequest), - typeof(CatFielddataRequest), - typeof(CatHealthRequest), - typeof(CatHelpRequest), - typeof(CatIndicesRequest), - typeof(CatMasterRequest), - typeof(CatNodesRequest), - typeof(CatPendingTasksRequest), - typeof(CatPluginsRequest), - typeof(CatRecoveryRequest), - typeof(CatSegmentsRequest), - typeof(CatShardsRequest), - typeof(CatThreadPoolRequest), - typeof(DocumentExistsRequest), - typeof(DocumentExistsRequest<>), - typeof(AliasExistsRequest), - typeof(IndexExistsRequest), - typeof(TypeExistsRequest), - typeof(IndexTemplateExistsRequest), - typeof(SearchExistsRequest), - typeof(SearchExistsRequest<>), - typeof(SearchTemplateRequest), - typeof(SearchTemplateRequest<>), - typeof(ScrollRequest), - typeof(SourceRequest), - typeof(SourceRequest<>), - typeof(ValidateQueryRequest<>), - typeof(GetAliasRequest), - typeof(CatNodeattrsRequest), - typeof(IndicesShardStoresRequest), - typeof(RenderSearchTemplateRequest) - }; -var types = typeof(IRequest).Assembly().GetTypes(); -var requests = new HashSet(types - .Where(t => - t.IsClass() && - !t.IsAbstract() && - typeof(IRequest).IsAssignableFrom(t) && - !typeof(IDescriptor).IsAssignableFrom(t) - && !exceptions.Contains(t)) - .Select(t => t.Name.Split('`')[0].Replace("Request", "")) - ); -var responses = types - .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) - .Select(t => t.Name.Split('`')[0].Replace("Response", "")); -requests.Except(responses).Should().BeEmpty(); ----- diff --git a/docs/asciidoc/on_startup.asciidoc b/docs/asciidoc/on_startup.asciidoc deleted file mode 100644 index 7550fbd4e44..00000000000 --- a/docs/asciidoc/on_startup.asciidoc +++ /dev/null @@ -1,121 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Sniffing on startup - -Connection pools that return true for `SupportsReseeding` by default sniff on startup. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall - { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCalls( - new ClientCall - { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} - }, - new ClientCall - { - { PingSuccess, 9201}, - { HealthyResponse, 9201} - } - ); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always, Framework.Cluster.Nodes(8, startFrom: 9204))) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess, 9204}, - { HealthyResponse, 9204} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9209).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffFailure, 9202}, - { SniffFailure, 9203}, - { SniffFailure, 9204}, - { SniffFailure, 9205}, - { SniffFailure, 9206}, - { SniffFailure, 9207}, - { SniffFailure, 9208}, - { SniffSuccess, 9209}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(new[] { - new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, - new Node(new Uri("http://localhost:9201")) { MasterEligible = false }, - new Node(new Uri("http://localhost:9202")) { MasterEligible = true }, - }) - .Sniff(s => s.Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} - }); -var audit = new Auditor(() => Framework.Cluster - .Nodes(new[] { - new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, - new Node(new Uri("http://localhost:9201")) { MasterEligible = true }, - new Node(new Uri("http://localhost:9202")) { MasterEligible = false }, - }) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() - ); -await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} - }); ----- diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc new file mode 100644 index 00000000000..7414bd6a953 --- /dev/null +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -0,0 +1,165 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +== Bool Queries + +Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, +take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses + +[source,csharp] +---- +var searchResults = this.Client.Search(s => s + .Query(q => q + .Bool(b => b + .Should( + bs => bs.Term(p => p.Name, "x"), + bs => bs.Term(p => p.Name, "y") + ) + ) + ) +); +---- + +Now, imagine multiple nested bools this quickly becomes an exercise in _hadouken indenting_ + +[[indent]] +.hadouken indenting example +image::{imagesdir}/hadouken-indentation.jpg[dead indent] +=== Operator Overloading + +For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. +The previous example now becomes the following with the fluent API + +[source,csharp] +---- +var searchResults = this.Client.Search(s => s + .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) +); +---- + +or, using the object initializer syntax + +[source,csharp] +---- +searchResults = this.Client.Search(new SearchRequest +{ + Query = new TermQuery { Field = "name", Value= "x" } + || new TermQuery { Field = Field(p=>p.Name), Value = "y" } +}); +---- + +A naive implementation of operator overloading would rewrite + +`term && term && term` to + +.... +bool +|___must + |___term + |___bool + |___must + |___term + |___term +.... + +As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and +join them together to become a single bool query + +.... +bool +|___must + |___term + |___term + |___term +.... + +The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator + +And to mark a query as a `filter` using the `+` operator + +Both of these can be combined with `&&` to form a single bool query + +=== Combining/Merging bool queries + +When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query + +.... +bool +|___must +| |___term +| |___term +| |___term +| +|___must_not + |___term +.... + +[source,csharp] +---- +Assert( + q => q.Query() && q.Query() && q.Query() && !q.Query(), + Query && Query && Query && !Query, + c=> + { + c.Bool.Must.Should().HaveCount(3); + c.Bool.MustNot.Should().HaveCount(1); + }); +c.Bool.Must.Should().HaveCount(3); +c.Bool.MustNot.Should().HaveCount(1); +---- + +Even more involved `term && term && term && !term && +term && +term` still only results in a single `bool` query: + +.... +bool +|___must +| |___term +| |___term +| |___term +| +|___must_not +| |___term +| +|___filter + |___term + |___term +.... + +You can still mix and match actual bool queries with the bool DSL e.g +`bool(must=term, term, term) && !term` would still merge into a single `bool` query. + +TIP: You can add parentheses to force evaluation order + +Also note that using shoulds as boosting factors can be really powerful so if you need this +always remember that you can mix and match an actual bool query with the bool dsl. + +There is another subtle situation where NEST will not blindly merge 2 bool queries with only should clauses. Imagine the following: + +`bool(should=term1, term2, term3, term4, minimum_should_match=2) || term5 || term6` + +if NEST identified both sides of the OR operation as only containing `should` clauses and it would +join them together it would give a different meaning to the `minimum_should_match` parameter of the first boolean query. +Rewriting this to a single bool with 5 `should` clauses would break because only matching on `term5` or `term6` should still be a hit. + +=== Locked bool queries + +NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, +NEST will treat these as locked + +Here we demonstrate that two locked `bool` queries are not combined + +neither are two `bool` queries where either the left or the right query is locked + +[source,csharp] +---- +c.Bool.Should.Should().HaveCount(2); +var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); +nestedBool.Bool.Should.Should().HaveCount(1); +nestedBool.Bool.Name.Should().Be(firstName); +assert(fluent.InvokeQuery(new QueryContainerDescriptor())); +assert((QueryContainer)ois); +---- + diff --git a/docs/asciidoc/distance_units.asciidoc b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc similarity index 57% rename from docs/asciidoc/distance_units.asciidoc rename to docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc index e4c875fd76a..f607f320597 100644 --- a/docs/asciidoc/distance_units.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc @@ -1,120 +1,120 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -# Distance Units -Whenever distances need to be specified, e.g. for a geo distance query, the distance unit can be specified -as a double number representing distance in meters, as a new instance of a `Distance`, or as a string -of the form number and distance unit e.g. `"2.72km"` - -## Using Distance units in NEST -NEST uses `Distance` to strongly type distance units and there are several ways to construct one. - -### Constructor -The most straight forward way to construct a `Distance` is through its constructor - - -[source, csharp] ----- -var unitComposed = new Nest.Distance(25); -var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); ----- - -When serializing Distance constructed from a string, composition of distance value and unit - - -[source, csharp] ----- -Expect("25.0m") - .WhenSerializing(unitComposed) - .WhenSerializing(unitComposedWithUnits); ----- - -### Implicit conversion -Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. -If no `DistanceUnit` is specified, the default distance unit is meters - - -[source, csharp] ----- -Nest.Distance distanceString = "25"; -Nest.Distance distanceStringWithUnits = "25m"; -Expect(new Nest.Distance(25)) - .WhenSerializing(distanceString) - .WhenSerializing(distanceStringWithUnits); ----- - -### Supported units -A number of distance units are supported, from millimeters to nautical miles - - - -Miles - - -[source, csharp] ----- -Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); ----- - -Yards - - -[source, csharp] ----- -Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); ----- - -Feet - - -[source, csharp] ----- -Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); ----- - -Inches - - -[source, csharp] ----- -Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); ----- - -Kilometers - - -[source, csharp] ----- -Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); ----- - -Meters - - -[source, csharp] ----- -Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); ----- - -Centimeters - - -[source, csharp] ----- -Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); ----- - -Millimeters - - -[source, csharp] ----- -Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); ----- - -Nautical Miles - - -[source, csharp] ----- -Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); ----- +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +== Distance Units + +Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], +the distance unit can be specified as a double number representing distance in meters, as a new instance of +a `Distance`, or as a string of the form number and distance unit e.g. "`2.72km`" + +=== Using Distance units in NEST + +NEST uses `Distance` to strongly type distance units and there are several ways to construct one. + +==== Constructor + +The most straight forward way to construct a `Distance` is through its constructor + +[source,csharp] +---- +var unitComposed = new Nest.Distance(25); +var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); +---- + +`Distance` serializes to a string composed of a factor and distance unit + +[source,csharp] +---- +Expect("25.0m") + .WhenSerializing(unitComposed) + .WhenSerializing(unitComposedWithUnits); +---- + +==== Implicit conversion + +Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. +If no `DistanceUnit` is specified, the default distance unit is meters + +[source,csharp] +---- +Nest.Distance distanceString = "25"; +Nest.Distance distanceStringWithUnits = "25m"; +Expect(new Nest.Distance(25)) + .WhenSerializing(distanceString) + .WhenSerializing(distanceStringWithUnits); +---- + +==== Supported units + +A number of distance units are supported, from millimeters to nautical miles + +===== Metric + +`mm` (Millimeters) + +[source,csharp] +---- +Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); +---- + +`cm` (Centimeters) + +[source,csharp] +---- +Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); +---- + +`m` (Meters) + +[source,csharp] +---- +Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); +---- + +`km` (Kilometers) + +[source,csharp] +---- +Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); +---- + +===== Imperial + +`in` (Inches) + +[source,csharp] +---- +Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); +---- + +`ft` (Feet) + +[source,csharp] +---- +Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); +---- + +`yd` (Yards) + +[source,csharp] +---- +Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); +---- + +`mi` (Miles) + +[source,csharp] +---- +Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); +---- + +`nmi` or `NM` (Nautical Miles) + +[source,csharp] +---- +Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); +---- + diff --git a/docs/asciidoc/respects_allowed_status_code.asciidoc b/docs/asciidoc/respects_allowed_status_code.asciidoc deleted file mode 100644 index d2814867afa..00000000000 --- a/docs/asciidoc/respects_allowed_status_code.asciidoc +++ /dev/null @@ -1,22 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Allowed status codes - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(400)) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(0)) - ); -audit = await audit.TraceCalls( - new ClientCall() { - { BadResponse, 9200 } - }, - new ClientCall(r => r.AllowedStatusCodes(400)) { - { HealthyResponse, 9201 } - } - ); ----- diff --git a/docs/asciidoc/respects_force_node.asciidoc b/docs/asciidoc/respects_force_node.asciidoc deleted file mode 100644 index fd95567d129..00000000000 --- a/docs/asciidoc/respects_force_node.asciidoc +++ /dev/null @@ -1,22 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Forcing nodes -Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` -request configuration. This will ignore the pool and not retry. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9208).FailAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { - { BadResponse, 9208 } - } - ); ----- diff --git a/docs/asciidoc/respects_max_retry.asciidoc b/docs/asciidoc/respects_max_retry.asciidoc deleted file mode 100644 index ffcd07c6c7e..00000000000 --- a/docs/asciidoc/respects_max_retry.asciidoc +++ /dev/null @@ -1,148 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== MaxRetries -By default retry as many times as we have nodes. However retries still respect the request timeout. -Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can -but give up after 20 seconds - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { BadResponse, 9205 }, - { BadResponse, 9206 }, - { BadResponse, 9207 }, - { BadResponse, 9208 }, - { HealthyResponse, 9209 } - } - ); ----- - -When you have a 100 node cluster you might want to ensure a fixed number of retries. -Remember that the actual number of requests is initial attempt + set number of retries - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(3)) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { MaxRetriesReached } - } - ); ----- - -In our previous test we simulated very fast failures, in the real world a call might take upwards of a second -Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. -In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxTimeoutReached } - } - ); ----- - -If you set smaller request time outs you might not want it to also affect the retry timeout, therefor you can configure these separately too. -Here we simulate calls taking 3 seconds, a request time out of 2 and an overall retry timeout of 10 seconds. -We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 -wins over the configured request timeout - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).FailAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { MaxTimeoutReached } - } - ); ----- - -If your retry policy expands beyond available nodes we won't retry the same node twice - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(2) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxRetriesReached } - } - ); ----- - -This makes setting any retry setting on a single node connection pool a NOOP, this is by design! -Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and -not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .SingleNodeConnection() - .Settings(s => s.DisablePing().MaximumRetries(10)) - ); -audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 } - } - ); ----- diff --git a/docs/asciidoc/respects_max_retry_overrides.asciidoc b/docs/asciidoc/respects_max_retry_overrides.asciidoc deleted file mode 100644 index ada9e0ac7b2..00000000000 --- a/docs/asciidoc/respects_max_retry_overrides.asciidoc +++ /dev/null @@ -1,71 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Maximum Retries - -By default retry as many times as we have nodes. However retries still respect the request timeout. -Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can -but give up after 20 seconds - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(2)) { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { MaxRetriesReached } - } - ); ----- - -When you have a 100 node cluster you might want to ensure a fixed number of retries. -Remember that the actual number of requests is initial attempt + set number of retries - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(5)) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(2)) { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { MaxRetriesReached } - } - ); ----- - -This makes setting any retry setting on a single node connection pool a NOOP, this is by design! -Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and -not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .SingleNodeConnection() - .Settings(s => s.DisablePing().MaximumRetries(10)) - ); -audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(10)) { - { BadResponse, 9200 } - } - ); ----- diff --git a/docs/asciidoc/revival.asciidoc b/docs/asciidoc/revival.asciidoc deleted file mode 100644 index 6ba6c41ad98..00000000000 --- a/docs/asciidoc/revival.asciidoc +++ /dev/null @@ -1,50 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Pinging - Revival - -When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping -before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(3) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9202).Fails(Once)) - .Ping(p => p.SucceedAlways()) - .StaticConnectionPool() - .AllDefaults() - ); -audit = await audit.TraceCalls( - new ClientCall { { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, - new ClientCall { { PingSuccess, 9201 }, { HealthyResponse, 9201 } }, - new ClientCall { - { PingSuccess, 9202}, - { BadResponse, 9202}, - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.First(n=>!n.IsAlive).DeadUntil.Should().BeAfter(DateTime.UtcNow) } - } - ); -audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } } - ); -audit.ChangeTime(d => d.AddMinutes(20)); -audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { - { Resurrection, 9202 }, - { PingSuccess, 9202 }, - { HealthyResponse, 9202 } - } - ); ----- diff --git a/docs/asciidoc/role_detection.asciidoc b/docs/asciidoc/role_detection.asciidoc deleted file mode 100644 index e1e87529c21..00000000000 --- a/docs/asciidoc/role_detection.asciidoc +++ /dev/null @@ -1,123 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Sniffing role detection - -When we sniff the custer state we detect the role of the node whether its master eligible and holds data -We use this information when selecting a node to perform an API call on. - - -[source, csharp] ----- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202) - .Succeeds(Always, Framework.Cluster.Nodes(8).MasterEligible(9200, 9201, 9202)) - ) - .SniffingConnectionPool() - .AllDefaults() - ) - { - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); - }, - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); - } - }; -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(10); -pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(8); -pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); -await audit.TraceStartup(); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202) - .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202)) - ) - .SniffingConnectionPool() - .AllDefaults() - ) - { - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); - }, - - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); - } - }; -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(10); -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(8); -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); -await audit.TraceStartup(); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.SucceedAlways() - .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202).SniffShouldReturnFqdn()) - ) - .SniffingConnectionPool() - .AllDefaults() - ) - { - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); - pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); - }, - - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); - pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); - } - }; -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(10); -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); -pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(8); -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); -pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); -await audit.TraceStartup(); -var node = SniffAndReturnNode(); -node.MasterEligible.Should().BeTrue(); -node.HoldsData.Should().BeFalse(); -node = await SniffAndReturnNodeAsync(); -node.MasterEligible.Should().BeTrue(); -node.HoldsData.Should().BeFalse(); -var pipeline = CreatePipeline(); -pipeline.Sniff(); -var pipeline = CreatePipeline(); -await pipeline.SniffAsync(); -this._settings = - this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; -var pipeline = new RequestPipeline(this._settings, DateTimeProvider.Default, new MemoryStreamFactory(), - new SearchRequestParameters()); -var nodes = this._settings.ConnectionPool.Nodes; -nodes.Should().NotBeEmpty().And.HaveCount(1); -var node = nodes.First(); ----- diff --git a/docs/asciidoc/unrecoverable_exceptions.asciidoc b/docs/asciidoc/unrecoverable_exceptions.asciidoc deleted file mode 100644 index 802512fdd5e..00000000000 --- a/docs/asciidoc/unrecoverable_exceptions.asciidoc +++ /dev/null @@ -1,46 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - -== Unrecoverable exceptions -Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. -By default the client won't throw on any ElasticsearchClientException but return an invalid response. -You can configure the client to throw using ThrowExceptions() on ConnectionSettings. The following test -both a client that throws and one that returns an invalid response with an `.OriginalException` exposed - - -[source, csharp] ----- -var recoverablExceptions = new[] - { - new PipelineException(PipelineFailure.BadResponse), - new PipelineException(PipelineFailure.PingFailure), - }; -recoverablExceptions.Should().OnlyContain(e => e.Recoverable); -var unrecoverableExceptions = new[] - { - new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), - new PipelineException(PipelineFailure.SniffFailure), - new PipelineException(PipelineFailure.Unexpected), - new PipelineException(PipelineFailure.BadAuthentication), - new PipelineException(PipelineFailure.MaxRetriesReached), - new PipelineException(PipelineFailure.MaxTimeoutReached) - }; -unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(r => r.SucceedAlways()) - .ClientCalls(r => r.FailAlways(401)) - .StaticConnectionPool() - .AllDefaults() - ); -audit = await audit.TraceElasticsearchException( - new ClientCall { - { AuditEvent.PingSuccess, 9200 }, - { AuditEvent.BadResponse, 9200 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); - } - ); -e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); ----- diff --git a/docs/asciidoc/writing_aggregations.asciidoc b/docs/asciidoc/writing_aggregations.asciidoc deleted file mode 100644 index 6be9d4ac159..00000000000 --- a/docs/asciidoc/writing_aggregations.asciidoc +++ /dev/null @@ -1,124 +0,0 @@ -:ref_current: http://www.elastic.co/guide/elasticsearch/reference/current - - -Aggregations are arguably one of the most powerful features of Elasticsearch. -NEST allows you to write your aggregations using a strict fluent dsl, a verbatim object initializer -syntax that maps verbatim to the elasticsearch API & a more terse object initializer aggregation DSL. - -Three different ways, yikes thats a lot to take in! Lets go over them one by one and explain when you might -want to use which one. - - - -The fluent lambda syntax is the most terse way to write aggregations. -It benefits from types that are carried over to sub aggregations - - - -The object initializer syntax (OIS) is a one-to-one mapping with how aggregations -have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one -mapping, being dictionary based in C# means it can grow exponentially in complexity rather quickly. - - -[source, csharp] ----- -public class Usage : UsageTestBase, SearchRequest> -{ - protected override object ExpectJson => new - { - aggs = new - { - name_of_child_agg = new - { - children = new { type = "commits" }, - aggs = new { - average_per_child = new - { - avg = new { field = "confidenceFactor" } - }, - max_per_child = new - { - max = new { field = "confidenceFactor" } - } - } - } - } - }; -protected override Func, ISearchRequest> Fluent => s => s - .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => childAggs - .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - ) - ) - ); -protected override SearchRequest Initializer => - new SearchRequest - { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", "confidenceFactor") - && new MaxAggregation("max_per_child", "confidenceFactor") - } - }; -} ----- - -For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, -These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. -It also allows you to combine multiple aggregations using bitwise AND (`&&`) operator. - -Compare the following example with the previous vanilla OIS syntax - - -[source, csharp] ----- -public class AggregationDslUsage : Usage -{ -protected override SearchRequest Initializer => - new SearchRequest - { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) - && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) - } - }; -} ----- - -An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations -on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor -(`childAggs` below) in turn, returning the descriptor after each function application. - - - -[source, csharp] ----- -public class AdvancedAggregationDslUsage : Usage -{ -protected override Func, ISearchRequest> Fluent - { - get - { - var aggregations = new List, IAggregationContainer>> - { - a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), - a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - }; - - return s => s - .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => - aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) - ) - ) - ); - } - } -} ----- diff --git a/libs/AsciiDoc.dll b/libs/AsciiDoc.dll new file mode 100644 index 0000000000000000000000000000000000000000..1fc341935180ece7ba66799d7ec8146873563c2c GIT binary patch literal 68096 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Ξ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%0D4=;V>Vfk{E4OTfo~ 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 a.Name == "ref_current")) + { + document.Attributes.Add(new AttributeEntry("ref_current", "https://www.elastic.co/guide/en/elasticsearch/reference/current/")); + } + + if (!document.Attributes.Any(a => a.Name == "github")) + { + document.Attributes.Add(new AttributeEntry("github", "https://github.com/elastic/elasticsearch-net")); + } + + if (!document.Attributes.Any(a => a.Name == "imagesdir")) + { + var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; + var currentDirectory = _destination.Directory.FullName; + var count = 0; + + while (currentDirectory != targetDirectory) + { + currentDirectory = new DirectoryInfo(currentDirectory).Parent?.FullName; + ++count; + } + + document.Attributes.Add(new AttributeEntry( + "imagesdir", + $"{string.Join(string.Empty, Enumerable.Repeat("../", count))}{Program.ImagesDir}/")); + } + + base.Visit(document); + } + } +} +#endif diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs index f305486bf12..32f8d32a822 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs @@ -1,13 +1,24 @@ +using System; + namespace Nest.Litterateur.Documentation.Blocks { public class CodeBlock : IDocumentationBlock { public string Value { get; } public int LineNumber { get; } - public CodeBlock(string lineOfCode, int lineNumber) + + public string Language { get; set; } + + public CodeBlock(string lineOfCode, int lineNumber, string language) { + if (language == null) + { + throw new ArgumentNullException(nameof(language)); + } + Value = lineOfCode.Trim(); LineNumber = lineNumber; + Language = language; } } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index c413261ff99..cd7dd7d95eb 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -7,38 +8,31 @@ using Nest.Litterateur.Documentation.Blocks; using Nest.Litterateur.Walkers; +#if !DOTNETCORE +using AsciiDoc; +using Nest.Litterateur.AsciiDoc; +#endif + namespace Nest.Litterateur.Documentation.Files { public class CSharpDocumentationFile : DocumentationFile { - internal CSharpDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } + private readonly Dictionary _sections; + + internal CSharpDocumentationFile(FileInfo fileLocation, Dictionary sections) : base(fileLocation) + { + _sections = sections; + } private string RenderBlocksToDocumentation(IEnumerable blocks) { var builder = new StringBuilder(); - - RenderHeader(builder); - var lastBlockWasCodeBlock = false; - RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock); if (lastBlockWasCodeBlock) builder.AppendLine("----"); - - RenderFooter(builder); - return builder.ToString(); } - private void RenderHeader(StringBuilder builder) - { - builder.AppendLine(":ref_current: http://www.elastic.co/guide/elasticsearch/reference/current"); - builder.AppendLine(); - } - - private void RenderFooter(StringBuilder builder) - { - } - private void RenderBlocksToDocumentation(IEnumerable blocks, StringBuilder builder, ref bool lastBlockWasCodeBlock) { foreach (var block in blocks) @@ -55,9 +49,16 @@ private void RenderBlocksToDocumentation(IEnumerable blocks } else if (block is CodeBlock) { + var codeBlock = (CodeBlock)block; + if (!lastBlockWasCodeBlock) { - builder.AppendLine("[source, csharp]"); + builder.AppendLine($"[source, {codeBlock.Language}]"); + if (codeBlock.Language == "javascript") + { + builder.AppendLine(".Example json output"); + } + builder.AppendLine("----"); } else @@ -81,13 +82,15 @@ private List MergeAdjacentCodeBlocks(IEnumerable(); List collapseCodeBlocks = null; int lineNumber = 0; + string language = null; + foreach (var b in unmergedBlocks) { - //if current block is not a code block and we;ve been collapsing code blocks - //at this point close that buffre and add a new codeblock + //if current block is not a code block and we've been collapsing code blocks + //at this point close that buffer and add a new codeblock if (!(b is CodeBlock) && collapseCodeBlocks != null) { - blocks.Add(new CodeBlock(string.Join("\r\n", collapseCodeBlocks), lineNumber)); + blocks.Add(new CodeBlock(string.Join(Environment.NewLine, collapseCodeBlocks), lineNumber, language)); collapseCodeBlocks = null; } @@ -100,12 +103,21 @@ private List MergeAdjacentCodeBlocks(IEnumerable(); - collapseCodeBlocks.Add(b.Value); - lineNumber = b.LineNumber; + var codeBlock = (CodeBlock)b; + + if (language != null && codeBlock.Language != language) + { + blocks.Add(codeBlock); + continue; + } + + language = codeBlock.Language; + collapseCodeBlocks.Add(codeBlock.Value); + lineNumber = codeBlock.LineNumber; } //make sure we flush our code buffer if (collapseCodeBlocks != null) - blocks.Add(new CodeBlock(string.Join("\r\n", collapseCodeBlocks), lineNumber)); + blocks.Add(new CodeBlock(string.Join(Environment.NewLine, collapseCodeBlocks), lineNumber, language)); return blocks; } @@ -121,9 +133,29 @@ public override void SaveToDocumentationFolder() var mergedBlocks = MergeAdjacentCodeBlocks(blocks); var body = this.RenderBlocksToDocumentation(mergedBlocks); - var docFileName = this.CreateDocumentationLocation(); + +#if !DOTNETCORE + // tidy up + var document = Document.Parse(body); + + // get the section numbers + var sectionAttributeEntry = document.Attributes.SingleOrDefault(a => a.Name == "section-number"); + decimal sectionValue; + if (sectionAttributeEntry != null && decimal.TryParse(sectionAttributeEntry.Value, out sectionValue)) + { + _sections.Add(docFileName.Name, sectionValue); + } + + // add attributes and write to destination + using (var file = new StreamWriter(docFileName.FullName)) + { + document.Accept(new AddAttributeEntriesVisitor(docFileName)); + document.Accept(new AsciiDocVisitor(file)); + } +#else File.WriteAllText(docFileName.FullName, body); +#endif } } } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs index 1fdaba08261..5dfd76cdb9c 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Reflection.Emit; using System.Text.RegularExpressions; @@ -19,13 +20,13 @@ protected DocumentationFile(FileInfo fileLocation) public abstract void SaveToDocumentationFolder(); - public static DocumentationFile Load(FileInfo fileLocation) + public static DocumentationFile Load(FileInfo fileLocation, Dictionary sections) { var extension = fileLocation?.Extension; switch (extension) { case ".cs": - return new CSharpDocumentationFile(fileLocation); + return new CSharpDocumentationFile(fileLocation, sections); case ".gif": case ".jpg": case ".jpeg": @@ -43,11 +44,10 @@ protected virtual FileInfo CreateDocumentationLocation() var testFullPath = this.FileLocation.FullName; var testInDocumentationFolder = - Path.GetFileNameWithoutExtension(testFullPath).TrimDocExtension().PascalToUnderscore() + ".asciidoc"; + Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "").TrimDocExtension().PascalToHyphen() + ".asciidoc"; - var documentationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, testInDocumentationFolder)); + var documentationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputDirPath, testInDocumentationFolder)); var fileInfo = new FileInfo(documentationTargetPath); - if (fileInfo.Directory != null) Directory.CreateDirectory(fileInfo.Directory.FullName); diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs index a9ee3bfc9f1..1bf76cd336f 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs @@ -9,9 +9,9 @@ public ImageDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } protected override FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; - var testInDocumenationFolder = Path.GetFileName(testFullPath).PascalToUnderscore(); + var testInDocumenationFolder = Path.GetFileName(testFullPath).PascalToHyphen(); - var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, "images", testInDocumenationFolder)); + var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.ImagesDirPath, testInDocumenationFolder)); var fileInfo = new FileInfo(documenationTargetPath); if (fileInfo.Directory != null) Directory.CreateDirectory(fileInfo.Directory.FullName); diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs index a976cb3080f..5750c9f009a 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs @@ -17,9 +17,9 @@ public override void SaveToDocumentationFolder() protected override FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; - var testInDocumenationFolder = Path.GetFileName(testFullPath).PascalToUnderscore(); + var testInDocumenationFolder = Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "").PascalToHyphen() + this.Extension; - var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputFolder, testInDocumenationFolder)); + var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputDirPath, testInDocumenationFolder)); var fileInfo = new FileInfo(documenationTargetPath); if (fileInfo.Directory != null) Directory.CreateDirectory(fileInfo.Directory.FullName); diff --git a/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs b/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs index 5ea9733336e..9c82fffdb04 100644 --- a/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/EnumerableExtensions.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; namespace Nest.Litterateur { @@ -39,26 +37,4 @@ public static IEnumerable Intertwine(this IEnumerable one, IEnumerable< } } - - public static class StringExtensions - { - public static string PascalToUnderscore(this string input) - { - if (string.IsNullOrEmpty(input)) return string.Empty; - - return Regex.Replace( - Regex.Replace( - Regex.Replace(input, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-z\d])([A-Z])", "$1_$2") - , @"[-\s]", "_").ToLower(); - } - - public static string TrimDocExtension(this string input) - { - if (string.IsNullOrEmpty(input)) return string.Empty; - - return input.EndsWith(".doc", StringComparison.OrdinalIgnoreCase) - ? input.Substring(0, input.Length - 4) - : input; - } - } } diff --git a/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs b/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs deleted file mode 100644 index 11eaab86d96..00000000000 --- a/src/CodeGeneration/Nest.Litterateur/Linker/Linker.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Nest.Litterateur.Linker -{ - /// - /// Goes over the generated docs, does heuristical touchups and writes outs ascii docs links at the bottom of files - /// - public class Linker - { - public Linker() - { - - } - - public void GenerateIndex() - { - // TODO: harvest all the doc ids and write out an index file containing links for all - } - - public void GenerateHeaderIds() - { - - } - - public void GenerateAttributes() - { - - } - } -} diff --git a/src/CodeGeneration/Nest.Litterateur/LitUp.cs b/src/CodeGeneration/Nest.Litterateur/LitUp.cs index 66dfd2771cc..2519149bdfe 100644 --- a/src/CodeGeneration/Nest.Litterateur/LitUp.cs +++ b/src/CodeGeneration/Nest.Litterateur/LitUp.cs @@ -9,11 +9,14 @@ namespace Nest.Litterateur public static class LitUp { private static readonly string[] SkipFolders = { "Nest.Tests.Literate", "Debug", "Release" }; + + private static readonly Dictionary Sections = new Dictionary(); + public static IEnumerable InputFiles(string extension) => - from f in Directory.GetFiles(Program.InputFolder, $"*.{extension}", SearchOption.AllDirectories) + from f in Directory.GetFiles(Program.InputDirPath, $"*.{extension}", SearchOption.AllDirectories) let dir = new DirectoryInfo(f) where dir?.Parent != null && !SkipFolders.Contains(dir.Parent.Name) - select DocumentationFile.Load(new FileInfo(f)); + select DocumentationFile.Load(new FileInfo(f), Sections); public static IEnumerable> Input { diff --git a/src/CodeGeneration/Nest.Litterateur/Program.cs b/src/CodeGeneration/Nest.Litterateur/Program.cs index 8ecdf2ab64d..f396de0d52d 100644 --- a/src/CodeGeneration/Nest.Litterateur/Program.cs +++ b/src/CodeGeneration/Nest.Litterateur/Program.cs @@ -1,32 +1,31 @@ using System.IO; -using Nest.Litterateur.Documentation; namespace Nest.Litterateur { public static class Program { - private static string DefaultTestFolder; - private static string DefaultDocFolder; + public const string ImagesDir = "images"; static Program() { var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); if (currentDirectory.Name == "Nest.Litterateur" && currentDirectory.Parent.Name == "CodeGeneration") { - DefaultTestFolder = @"..\..\Tests"; - DefaultDocFolder = @"..\..\..\docs\asciidoc"; + InputDirPath = @"..\..\Tests"; + OutputDirPath = @"..\..\..\docs\asciidoc"; } else { - DefaultTestFolder = @"..\..\..\..\..\src\Tests"; - DefaultDocFolder = @"..\..\..\..\..\docs\asciidoc"; + InputDirPath = @"..\..\..\..\..\src\Tests"; + OutputDirPath = @"..\..\..\..\..\docs\asciidoc"; } } - public static string InputFolder => DefaultTestFolder; + public static string ImagesDirPath => Path.Combine(OutputDirPath, ImagesDir); - - public static string OutputFolder => DefaultDocFolder; + public static string InputDirPath { get; } + + public static string OutputDirPath { get; } static void Main(string[] args) => LitUp.Go(args); } diff --git a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs new file mode 100644 index 00000000000..1c208d4c19d --- /dev/null +++ b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs @@ -0,0 +1,63 @@ +using System; +using System.Text.RegularExpressions; + +namespace Nest.Litterateur +{ + public static class StringExtensions + { + public static string PascalToHyphen(this string input) + { + if (string.IsNullOrEmpty(input)) return string.Empty; + + return Regex.Replace( + Regex.Replace( + Regex.Replace(input, @"([A-Z]+)([A-Z][a-z])", "$1-$2"), @"([a-z\d])([A-Z])", "$1-$2") + , @"[-\s]", "-").ToLower(); + } + + public static string TrimDocExtension(this string input) + { + if (string.IsNullOrEmpty(input)) return string.Empty; + + return input.EndsWith(".doc", StringComparison.OrdinalIgnoreCase) + ? input.Substring(0, input.Length - 4) + : input; + } + + public static string RemoveLeadingAndTrailingMultiLineComments(this string input) + { + var match = Regex.Match(input, @"^(?[ \t]*\/\*)"); + + if (match.Success) + { + input = input.Substring(match.Groups["value"].Value.Length); + } + + match = Regex.Match(input, @"(?\*\/[ \t]*)$"); + + if (match.Success) + { + input = input.Substring(0, input.Length - match.Groups["value"].Value.Length); + } + + return input; + } + + public static string RemoveLeadingSpacesAndAsterisk(this string input) + { + var match = Regex.Match(input, @"^(?[ \t]*\*\s?).*"); + + if (match.Success) + { + input = input.Substring(match.Groups["value"].Value.Length); + } + + return input; + } + + public static string RemoveNumberOfLeadingTabsAfterNewline(this string input , int numberOfTabs) + { + return Regex.Replace(input, $"(?[\n|\r\n]+\t{{{numberOfTabs}}})", m => m.Value.Replace("\t", string.Empty)); + } + } +} \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs index ab1e6445d0d..0904152d512 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs @@ -4,26 +4,33 @@ using Nest.Litterateur.Documentation; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Formatting; #if !DOTNETCORE using Microsoft.CodeAnalysis.MSBuild; #endif using Microsoft.CodeAnalysis.Text; using Nest.Litterateur.Documentation.Blocks; +using Newtonsoft.Json; namespace Nest.Litterateur.Walkers { class CodeWithDocumentationWalker : CSharpSyntaxWalker { public List Blocks { get; } = new List(); + public List TextBlocks { get; } = new List(); private bool _firstVisit = true; private string _code; + public int ClassDepth { get; } + private readonly int? _lineNumberOverride; /// @@ -32,7 +39,7 @@ class CodeWithDocumentationWalker : CSharpSyntaxWalker /// /// the depth of the class /// line number used for sorting - public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null) : base(SyntaxWalkerDepth.StructuredTrivia) + public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null) : base(SyntaxWalkerDepth.StructuredTrivia) { ClassDepth = classDepth; _lineNumberOverride = lineNumber; @@ -45,19 +52,27 @@ public override void Visit(SyntaxNode node) _firstVisit = false; var repeatedTabs = 2 + ClassDepth; + var language = "csharp"; _code = node.WithoutLeadingTrivia().WithTrailingTrivia().ToFullString(); + _code = _code.RemoveNumberOfLeadingTabsAfterNewline(repeatedTabs); - // find x or more repeated tabs and trim x number of tabs from the start - _code = Regex.Replace(_code, $"\t{{{repeatedTabs},}}", match => match.Value.Substring(repeatedTabs)); +#if !DOTNETCORE + // if this is ExpectJson node, get the json for the anonymous type + if (node.Kind() == SyntaxKind.AnonymousObjectCreationExpression) + { + _code = GetJsonForAnonymousType(); + language = "javascript"; + } +#endif var nodeLine = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var line = _lineNumberOverride ?? nodeLine; - var codeBlocks = ParseCodeBlocks(_code, line); + var codeBlocks = ParseCodeBlocks(_code, line, language); base.Visit(node); var nodeHasLeadingTriva = node.HasLeadingTrivia && node.GetLeadingTrivia() - .Any(c=>c.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia); + .Any(c => c.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia); var blocks = codeBlocks.Intertwine(this.TextBlocks, swap: nodeHasLeadingTriva); this.Blocks.Add(new CombinedBlock(blocks, line)); return; @@ -77,11 +92,11 @@ public override void VisitBlock(BlockSyntax node) SyntaxNode formattedStatement = statement; _code = formattedStatement.WithoutLeadingTrivia().WithTrailingTrivia().ToFullString(); - _code = Regex.Replace(_code, $"\t{{{repeatedTabs},}}", match => match.Value.Substring(repeatedTabs)); + _code = _code.RemoveNumberOfLeadingTabsAfterNewline(repeatedTabs); var nodeLine = formattedStatement.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var line = _lineNumberOverride ?? nodeLine; - var codeBlocks = ParseCodeBlocks(_code, line); + var codeBlocks = ParseCodeBlocks(_code, line, "csharp"); this.Blocks.AddRange(codeBlocks); } @@ -98,12 +113,15 @@ public override void VisitTrivia(SyntaxTrivia trivia) return; } - var tokens = trivia.ToFullString().TrimStart('/', '*').TrimEnd('*', '/').Split('\n'); + var tokens = trivia.ToFullString() + .RemoveLeadingAndTrailingMultiLineComments() + .Split(new[] { Environment.NewLine }, StringSplitOptions.None); var builder = new StringBuilder(); foreach (var token in tokens) { - var decodedToken = System.Net.WebUtility.HtmlDecode(token.TrimStart().TrimStart('*').TrimStart()); + var currentToken = token.RemoveLeadingSpacesAndAsterisk(); + var decodedToken = System.Net.WebUtility.HtmlDecode(currentToken); builder.AppendLine(decodedToken); } @@ -115,13 +133,87 @@ public override void VisitTrivia(SyntaxTrivia trivia) this.Blocks.Add(new TextBlock(text, line)); } - private List ParseCodeBlocks(string code, int line) + private List ParseCodeBlocks(string code, int line, string language) { return Regex.Split(code, @"\/\*\*.*?\*\/", RegexOptions.Singleline) .Select(b => b.TrimStart('\r', '\n').TrimEnd('\r', '\n', '\t')) .Where(b => !string.IsNullOrEmpty(b) && b != ";") - .Select(b => new CodeBlock(b, line)) + .Select(b => new CodeBlock(b, line, language)) .ToList(); } + +#if !DOTNETCORE + private string GetJsonForAnonymousType() + { + var text = + $@" + using System; + using Newtonsoft.Json; + + namespace Temporary + {{ + public class Json + {{ + public string Write() + {{ + var o = " + + _code + $@"; + var json = JsonConvert.SerializeObject(o, Formatting.Indented); + return json; + }} + }} + }}"; + + var syntaxTree = CSharpSyntaxTree.ParseText(text); + string assemblyName = Path.GetRandomFileName(); + + var references = new MetadataReference[] + { + MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(JsonConvert).GetTypeInfo().Assembly.Location), + }; + + CSharpCompilation compilation = + CSharpCompilation.Create( + assemblyName, + new[] { syntaxTree }, + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + + using (var ms = new MemoryStream()) + { + var result = compilation.Emit(ms); + + if (!result.Success) + { + var failures = result.Diagnostics.Where(diagnostic => + diagnostic.IsWarningAsError || + diagnostic.Severity == DiagnosticSeverity.Error); + + var builder = new StringBuilder(); + foreach (var diagnostic in failures) + { + builder.AppendLine($"{diagnostic.Id}: {diagnostic.GetMessage()}"); + } + + throw new Exception(builder.ToString()); + } + + ms.Seek(0, SeekOrigin.Begin); + Assembly assembly = Assembly.Load(ms.ToArray()); + + Type type = assembly.GetType("Temporary.Json"); + object obj = Activator.CreateInstance(type); + var output = type.InvokeMember("Write", + BindingFlags.Default | BindingFlags.InvokeMethod, + null, + obj, + new object[] { }); + + return output.ToString(); + } + } +#endif } } diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index 3cfbf57998d..72fc9bb2382 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -55,7 +55,13 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { var propertyName = node.Identifier.Text; - if (propertyName == "Fluent") + if (propertyName == "ExpectJson") + { + this.InsideFluentOrInitializerExample = true; + base.VisitPropertyDeclaration(node); + this.InsideFluentOrInitializerExample = false; + } + else if (propertyName == "Fluent") { this.InsideFluentOrInitializerExample = true; base.VisitPropertyDeclaration(node); @@ -112,7 +118,9 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) return; } base.VisitExpressionStatement(node); - this.Blocks.Add(new CodeBlock(node.WithoutLeadingTrivia().ToFullString(), line)); + var code = node.WithoutLeadingTrivia().ToFullString(); + code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); + this.Blocks.Add(new CodeBlock(code, line, "csharp")); } else base.VisitExpressionStatement(node); @@ -131,7 +139,9 @@ public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyn this.Blocks.AddRange(walker.Blocks); return; } - this.Blocks.Add(new CodeBlock(node.WithoutLeadingTrivia().ToFullString(), line)); + var code = node.WithoutLeadingTrivia().ToFullString(); + code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); + this.Blocks.Add(new CodeBlock(code, line, "csharp")); } base.VisitLocalDeclarationStatement(node); } @@ -146,12 +156,15 @@ public override void VisitTrivia(SyntaxTrivia trivia) this.InsideMultiLineDocumentation = true; - var tokens = trivia.ToFullString().TrimStart('/', '*').TrimEnd('*', '/').Split('\n'); + var tokens = trivia.ToFullString() + .RemoveLeadingAndTrailingMultiLineComments() + .Split(new [] { Environment.NewLine }, StringSplitOptions.None); var builder = new StringBuilder(); foreach (var token in tokens) { - var decodedToken = System.Net.WebUtility.HtmlDecode(token.TrimStart().TrimStart('*').TrimStart()); + var currentToken = token.RemoveLeadingSpacesAndAsterisk(); + var decodedToken = System.Net.WebUtility.HtmlDecode(currentToken); builder.AppendLine(decodedToken); } diff --git a/src/CodeGeneration/Nest.Litterateur/project.json b/src/CodeGeneration/Nest.Litterateur/project.json index be6baede508..37dbaa50b1b 100644 --- a/src/CodeGeneration/Nest.Litterateur/project.json +++ b/src/CodeGeneration/Nest.Litterateur/project.json @@ -5,7 +5,7 @@ "emitEntryPoint": true }, "dependencies": { - + "Newtonsoft.Json": "8.0.2" }, "commands": { "Nest.Litterateur": "Nest.Litterateur" @@ -29,12 +29,14 @@ "System.Runtime": "", "System.Runtime.Serialization": "", "System.Threading.Tasks": "", - "System.Text.Encoding": "" + "System.Text.Encoding": "", + "System.IO": "" }, - "dependencies": { - "Microsoft.CSharp": "4.0.1-beta-23409", - "Microsoft.CodeAnalysis": "1.1.1" - } + "dependencies": { + "Microsoft.CSharp": "4.0.1-beta-23409", + "Microsoft.CodeAnalysis": "1.1.1", + "AsciiDoc": "1.0.0-*" + } }, "dotnet5.1": { "compilationOptions": { "define": [ "DOTNETCORE" ] }, @@ -44,6 +46,7 @@ "System.Reflection": "4.1.0-beta-23225", "System.Collections.Specialized": "4.0.0-beta-23109", "System.Linq": "4.0.0-beta-23109", + "System.IO": "4.0.0-beta-23109", "System.IO.FileSystem": "4.0.0-beta-23109", "System.IO.Compression": "4.0.0-beta-23109", "System.Runtime.Serialization.Primitives": "4.0.10-beta-23109", diff --git a/src/CodeGeneration/Nest.Litterateur/project.lock.json b/src/CodeGeneration/Nest.Litterateur/project.lock.json index a05b271d168..3f8112a00d6 100644 --- a/src/CodeGeneration/Nest.Litterateur/project.lock.json +++ b/src/CodeGeneration/Nest.Litterateur/project.lock.json @@ -3,6 +3,10 @@ "version": 2, "targets": { "DNX,Version=v4.5.1": { + "AsciiDoc/1.0.0": { + "type": "project", + "framework": "DNX,Version=v4.5.1" + }, "Microsoft.CodeAnalysis/1.1.1": { "type": "package", "dependencies": { @@ -124,6 +128,15 @@ "lib/net45/_._": {} } }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "compile": { + "lib/net45/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/net45/Newtonsoft.Json.dll": {} + } + }, "System.Collections/4.0.0": { "type": "package", "compile": { @@ -436,6 +449,15 @@ "lib/dotnet/Microsoft.CSharp.dll": {} } }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "compile": { + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll": {} + } + }, "System.Collections/4.0.11-beta-23225": { "type": "package", "dependencies": { @@ -621,12 +643,12 @@ "lib/dotnet/System.Globalization.Extensions.dll": {} } }, - "System.IO/4.0.0": { + "System.IO/4.0.0-beta-23109": { "type": "package", "dependencies": { - "System.Runtime": "4.0.0", - "System.Text.Encoding": "4.0.0", - "System.Threading.Tasks": "4.0.0" + "System.Runtime": "4.0.0-beta-23109", + "System.Text.Encoding": "4.0.0-beta-23109", + "System.Threading.Tasks": "4.0.0-beta-23109" }, "compile": { "ref/dotnet/System.IO.dll": {} @@ -967,6 +989,10 @@ } }, "DNX,Version=v4.5.1/win7-x86": { + "AsciiDoc/1.0.0": { + "type": "project", + "framework": "DNX,Version=v4.5.1" + }, "Microsoft.CodeAnalysis/1.1.1": { "type": "package", "dependencies": { @@ -1088,6 +1114,15 @@ "lib/net45/_._": {} } }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "compile": { + "lib/net45/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/net45/Newtonsoft.Json.dll": {} + } + }, "System.Collections/4.0.0": { "type": "package", "compile": { @@ -1269,6 +1304,10 @@ } }, "DNX,Version=v4.5.1/win7-x64": { + "AsciiDoc/1.0.0": { + "type": "project", + "framework": "DNX,Version=v4.5.1" + }, "Microsoft.CodeAnalysis/1.1.1": { "type": "package", "dependencies": { @@ -1390,6 +1429,15 @@ "lib/net45/_._": {} } }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "compile": { + "lib/net45/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/net45/Newtonsoft.Json.dll": {} + } + }, "System.Collections/4.0.0": { "type": "package", "compile": { @@ -1702,6 +1750,15 @@ "lib/dotnet/Microsoft.CSharp.dll": {} } }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "compile": { + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll": {} + } + }, "System.Collections/4.0.11-beta-23225": { "type": "package", "dependencies": { @@ -1887,12 +1944,12 @@ "lib/dotnet/System.Globalization.Extensions.dll": {} } }, - "System.IO/4.0.0": { + "System.IO/4.0.0-beta-23109": { "type": "package", "dependencies": { - "System.Runtime": "4.0.0", - "System.Text.Encoding": "4.0.0", - "System.Threading.Tasks": "4.0.0" + "System.Runtime": "4.0.0-beta-23109", + "System.Text.Encoding": "4.0.0-beta-23109", + "System.Threading.Tasks": "4.0.0-beta-23109" }, "compile": { "ref/dotnet/System.IO.dll": {} @@ -2393,6 +2450,15 @@ "lib/dotnet/Microsoft.CSharp.dll": {} } }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "compile": { + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll": {} + }, + "runtime": { + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll": {} + } + }, "System.Collections/4.0.11-beta-23225": { "type": "package", "dependencies": { @@ -2578,12 +2644,12 @@ "lib/dotnet/System.Globalization.Extensions.dll": {} } }, - "System.IO/4.0.0": { + "System.IO/4.0.0-beta-23109": { "type": "package", "dependencies": { - "System.Runtime": "4.0.0", - "System.Text.Encoding": "4.0.0", - "System.Threading.Tasks": "4.0.0" + "System.Runtime": "4.0.0-beta-23109", + "System.Text.Encoding": "4.0.0-beta-23109", + "System.Threading.Tasks": "4.0.0-beta-23109" }, "compile": { "ref/dotnet/System.IO.dll": {} @@ -2954,6 +3020,10 @@ } }, "libraries": { + "AsciiDoc/1.0.0": { + "type": "project", + "path": "../../wrap/AsciiDoc/project.json" + }, "Microsoft.CodeAnalysis/1.1.1": { "type": "package", "sha512": "X+UK+Ev5rQOCkb1HgMdUz47VK/qUvCe8FyObh3McgfIi+j2VXDsQq0YSPxqcKyQd72UmY0ttYDGLsA/ee0oC6w==", @@ -3089,7 +3159,7 @@ "Microsoft.CSharp/4.0.1-beta-23409": { "type": "package", "serviceable": true, - "sha512": "GGOOJF47WzXZoka0JHCToQxzSguIy1UeXZywUjA1NPqvKAWVwbSbZ2VxyeIL3jyTV1BHEbBX8FPL6vweUON2aw==", + "sha512": "I1jsSsyK89VfNebrnx2eiBD5YT6zp+DcX2v6AxZ/IosS38QYmA9YKVmssMd5yhRkXwr1f8MfgZTxF1Cli90JEQ==", "files": [ "lib/dotnet/de/Microsoft.CSharp.xml", "lib/dotnet/es/Microsoft.CSharp.xml", @@ -3127,6 +3197,28 @@ "ref/xamarinmac20/_._" ] }, + "Newtonsoft.Json/8.0.2": { + "type": "package", + "sha512": "e5yWmEfu68rmtG431zl9N/7PlNKQDIuiDW5MHlEFAZcecakcxrIGnKqrPAtWNILzK2oNanRB5cD150MYhECK3g==", + "files": [ + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll", + "lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.xml", + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.dll", + "lib/portable-net45+wp80+win8+wpa81+dnxcore50/Newtonsoft.Json.xml", + "Newtonsoft.Json.8.0.2.nupkg", + "Newtonsoft.Json.8.0.2.nupkg.sha512", + "Newtonsoft.Json.nuspec", + "tools/install.ps1" + ] + }, "System.Collections/4.0.0": { "type": "package", "sha512": "i2vsGDIEbWdHcUSNDPKZP/ZWod6o740el7mGTCy0dqbCxQh74W4QoC+klUwPEtGEFuvzJ7bJgvwJqscosVNyZQ==", @@ -3591,6 +3683,46 @@ "System.Globalization.Extensions.nuspec" ] }, + "System.IO/4.0.0-beta-23109": { + "type": "package", + "sha512": "5hFYIKRlgbPyYa9NKvizmrCACEbzVRpgMf+lF6erYxa5P7lPcbbQEt9C3xBbvShBwqNNzkosB5kD5MeaNKAmww==", + "files": [ + "lib/net45/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "License.rtf", + "ref/dotnet/de/System.IO.xml", + "ref/dotnet/es/System.IO.xml", + "ref/dotnet/fr/System.IO.xml", + "ref/dotnet/it/System.IO.xml", + "ref/dotnet/ja/System.IO.xml", + "ref/dotnet/ko/System.IO.xml", + "ref/dotnet/ru/System.IO.xml", + "ref/dotnet/System.IO.dll", + "ref/dotnet/System.IO.xml", + "ref/dotnet/zh-hans/System.IO.xml", + "ref/dotnet/zh-hant/System.IO.xml", + "ref/net45/_._", + "ref/netcore50/de/System.IO.xml", + "ref/netcore50/es/System.IO.xml", + "ref/netcore50/fr/System.IO.xml", + "ref/netcore50/it/System.IO.xml", + "ref/netcore50/ja/System.IO.xml", + "ref/netcore50/ko/System.IO.xml", + "ref/netcore50/ru/System.IO.xml", + "ref/netcore50/System.IO.dll", + "ref/netcore50/System.IO.xml", + "ref/netcore50/zh-hans/System.IO.xml", + "ref/netcore50/zh-hant/System.IO.xml", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "System.IO.4.0.0-beta-23109.nupkg", + "System.IO.4.0.0-beta-23109.nupkg.sha512", + "System.IO.nuspec" + ] + }, "System.IO/4.0.0": { "type": "package", "sha512": "MoCHQ0u5n0OMwUS8OX4Gl48qKiQziSW5cXvt82d+MmAcsLq9OL90+ihnu/aJ1h6OOYcBswrZAEuApfZha9w2lg==", @@ -4863,14 +4995,18 @@ } }, "projectFileDependencyGroups": { - "": [], + "": [ + "Newtonsoft.Json >= 8.0.2" + ], "DNX,Version=v4.5.1": [ "Microsoft.CSharp >= 4.0.1-beta-23409", "Microsoft.CodeAnalysis >= 1.1.1", + "AsciiDoc >= 1.0.0-*", "fx/System.Runtime ", "fx/System.Runtime.Serialization ", "fx/System.Threading.Tasks ", - "fx/System.Text.Encoding " + "fx/System.Text.Encoding ", + "fx/System.IO " ], ".NETPlatform,Version=v5.1": [ "System.Runtime >= 4.0.21-beta-23225", @@ -4878,6 +5014,7 @@ "System.Reflection >= 4.1.0-beta-23225", "System.Collections.Specialized >= 4.0.0-beta-23109", "System.Linq >= 4.0.0-beta-23109", + "System.IO >= 4.0.0-beta-23109", "System.IO.FileSystem >= 4.0.0-beta-23109", "System.IO.Compression >= 4.0.0-beta-23109", "System.Runtime.Serialization.Primitives >= 4.0.10-beta-23109", diff --git a/src/Tests/Aggregations/WritingAggregations.doc.cs b/src/Tests/Aggregations/WritingAggregations.doc.cs index 44b61ec73dc..b6790869f69 100644 --- a/src/Tests/Aggregations/WritingAggregations.doc.cs +++ b/src/Tests/Aggregations/WritingAggregations.doc.cs @@ -8,117 +8,133 @@ namespace Tests.Aggregations { - public class WritingAggregations + /** == Aggregations + * + * Aggregations are arguably one of the most powerful features of Elasticsearch. + * NEST allows you to write your aggregations using + * + * - a strict fluent DSL + * - a verbatim object initializer syntax that maps verbatim to the elasticsearch API + * - a more terse object initializer aggregation DSL + * + * Three different ways, yikes that's a lot to take in! Lets go over them one by one and explain when you might + * want to use each. + */ + public class Usage : UsageTestBase, SearchRequest> { /** - * Aggregations are arguably one of the most powerful features of Elasticsearch. - * NEST allows you to write your aggregations using a strict fluent dsl, a verbatim object initializer - * syntax that maps verbatim to the elasticsearch API & a more terse object initializer aggregation DSL. - * - * Three different ways, yikes thats a lot to take in! Lets go over them one by one and explain when you might - * want to use which one. - */ - public class Usage : UsageTestBase, SearchRequest> + * + * This is the json output for each example + **/ + protected override object ExpectJson => new { - protected override object ExpectJson => new + aggs = new { - aggs = new + name_of_child_agg = new { - name_of_child_agg = new + children = new { - children = new { type = "commits" }, - aggs = new { - average_per_child = new + type = "commits" + }, + aggs = new + { + average_per_child = new + { + avg = new { - avg = new { field = "confidenceFactor" } - }, - max_per_child = new + field = "confidenceFactor" + } + }, + max_per_child = new + { + max = new { - max = new { field = "confidenceFactor" } + field = "confidenceFactor" } } } } - }; - /** - * The fluent lambda syntax is the most terse way to write aggregations. - * It benefits from types that are carried over to sub aggregations - */ - protected override Func, ISearchRequest> Fluent => s => s - .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => childAggs - .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - ) + } + }; + + /** === Fluent DSL + * The fluent lambda syntax is the most terse way to write aggregations. + * It benefits from types that are carried over to sub aggregations + */ + protected override Func, ISearchRequest> Fluent => s => s + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) ) - ); + ) + ); - /** - * The object initializer syntax (OIS) is a one-to-one mapping with how aggregations - * have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one - * mapping, being dictionary based in C# means it can grow exponentially in complexity rather quickly. - */ - protected override SearchRequest Initializer => - new SearchRequest + /** === Object Initializer syntax + * The object initializer syntax (OIS) is a one-to-one mapping with how aggregations + * have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one + * mapping, being dictionary based in C# means it can grow exponentially in complexity rather quickly. + */ + protected override SearchRequest Initializer => + new SearchRequest + { + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", "confidenceFactor") - && new MaxAggregation("max_per_child", "confidenceFactor") - } - }; - } + Aggregations = + new AverageAggregation("average_per_child", "confidenceFactor") + && new MaxAggregation("max_per_child", "confidenceFactor") + } + }; + } - public class AggregationDslUsage : Usage - { - /** - * For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, - * These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. - * It also allows you to combine multiple aggregations using bitwise AND (`&&`) operator. - * - * Compare the following example with the previous vanilla OIS syntax - */ - protected override SearchRequest Initializer => - new SearchRequest + public class AggregationDslUsage : Usage + { + /** === Terse Object Initializer DSL + * For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, + * These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. + * It also allows you to combine multiple aggregations using bitwise AND (`&&`) operator. + * + * Compare the following example with the previous vanilla OIS syntax + */ + protected override SearchRequest Initializer => + new SearchRequest + { + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) - && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) - } - }; - } + Aggregations = + new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) + && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) + } + }; + } - public class AdvancedAggregationDslUsage : Usage - { - /** - * An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations - * on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor - * (`childAggs` below) in turn, returning the descriptor after each function application. - * - */ - protected override Func, ISearchRequest> Fluent - { - get + public class AdvancedAggregationDslUsage : Usage + { + /** === Aggregating over a collection of aggregations + * An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations + * on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor + * (`childAggs` below) in turn, returning the descriptor after each function application. + * + */ + protected override Func, ISearchRequest> Fluent + { + get + { + var aggregations = new List, IAggregationContainer>> { - var aggregations = new List, IAggregationContainer>> - { - a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), - a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - }; + a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), + a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + }; - return s => s - .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => - aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) - ) + return s => s + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => + aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) ) - ); - } + ) + ); } } } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs index 4fde0cd5202..8544afdefee 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs @@ -11,7 +11,11 @@ public class ConnectionPooling { /** == Connection Pooling * Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which - * we can use to issue client calls on. + * NEST can use to issue client calls on. There are 3 types of connection pool + * + * - <> + * - <> + * - <> */ /** === SingleNodeConnectionPool @@ -32,8 +36,8 @@ [U] public void SingleNode() /** and pinging */ pool.SupportsPinging.Should().BeFalse(); - /** When you use the low ceremony ElasticClient constructor that takes a single Uri, - * We default to this SingleNodeConnectionPool */ + /** When you use the low ceremony `ElasticClient` constructor that takes a single `Uri`, + * We default to using `SingleNodeConnectionPool` */ var client = new ElasticClient(uri); client.ConnectionSettings.ConnectionPool.Should().BeOfType(); @@ -57,8 +61,8 @@ [U] public void Static() /** a connection pool can be seeded using an enumerable of `Uri`s */ var pool = new StaticConnectionPool(uris); - /** Or using an enumerable of `Node` */ - var nodes = uris.Select(u=>new Node(u)); + /** Or using an enumerable of `Node`s */ + var nodes = uris.Select(u => new Node(u)); pool = new StaticConnectionPool(nodes); /** This type of pool is hardwired to opt out of sniffing*/ @@ -67,15 +71,15 @@ [U] public void Static() /** but supports pinging when enabled */ pool.SupportsPinging.Should().BeTrue(); - /** To create a client using this static connection pool pass - * the connection pool to the connectionsettings you pass to ElasticClient + /** To create a client using this static connection pool, pass + * the connection pool to the `ConnectionSettings` you pass to `ElasticClient` */ var client = new ElasticClient(new ConnectionSettings(pool)); client.ConnectionSettings.ConnectionPool.Should().BeOfType(); } /** === SniffingConnectionPool - * A subclass of StaticConnectionPool that allows itself to be reseeded at run time. + * A subclass of `StaticConnectionPool` that allows itself to be reseeded at run time. * It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. */ [U] public void Sniffing() @@ -85,8 +89,8 @@ [U] public void Sniffing() /** a connection pool can be seeded using an enumerable of `Uri` */ var pool = new SniffingConnectionPool(uris); - /** Or using an enumerable of `Node` - * A major benefit here is you can include known node roles when seeding + /** Or using an enumerable of `Node`s. + * A major benefit here is you can include known node roles when seeding and * NEST can use this information to favour sniffing on master eligible nodes first * and take master only nodes out of rotation for issuing client calls on. */ @@ -100,7 +104,7 @@ [U] public void Sniffing() pool.SupportsPinging.Should().BeTrue(); /** To create a client using the sniffing connection pool pass - * the connection pool to the connectionsettings you pass to ElasticClient + * the connection pool to the `ConnectionSettings` you pass to `ElasticClient` */ var client = new ElasticClient(new ConnectionSettings(pool)); client.ConnectionSettings.ConnectionPool.Should().BeOfType(); diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs index df4f773f2f9..8243a90532c 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs @@ -7,13 +7,20 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IdsInference { - /** = Ids + /** == Id Inference * - * Several places in the elasticsearch API expect an Id object to be passed. - * This is a special box type that you can implicitly convert to and from many value types. - */ - - /** Methods that take an Id can be passed longs, ints, strings & Guids and they will be implicitly converted to Ids */ + * === Implicit Conversions + * + * Several places in the Elasticsearch API expect an `Id` object to be passed. + * This is a special box type that you can implicitly convert to from the following types + * + * - `Int32` + * - `Int64` + * - `String` + * - `Guid` + * + * Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` + */ [U] public void CanImplicitlyConvertToId() { Id idFromInt = 1; @@ -27,10 +34,12 @@ [U] public void CanImplicitlyConvertToId() Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); } - /** Sometimes a method takes an object and we need an Id from that object to build up a path. + /** === Inferring from a Type + * + * Sometimes a method takes an object and we need an Id from that object to build up a path. * There is no implicit conversion from any object to Id but we can call `Id.From`. * - * Imagine your codebase has the following type that we want to index into elasticsearch + * Imagine your codebase has the following type that we want to index into Elasticsearch */ class MyDTO { @@ -42,19 +51,31 @@ class MyDTO [U] public void CanGetIdFromDocument() { /** By default NEST will try to find a property called `Id` on the class using reflection - * and create a cached fast func delegate based on the properties getter*/ - var dto = new MyDTO { Id =new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; + * and create a cached fast func delegate based on the properties getter + */ + var dto = new MyDTO + { + Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), + Name = "x", + OtherName = "y" + }; + Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); - /** Using the connection settings you can specify a different property NEST should look for ids. - * Here we instruct NEST to infer the Id for MyDTO based on its Name property */ + /** Using the connection settings you can specify a different property that NEST should use to infer the document Id. + * Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property + */ WithConnectionSettings(x => x .InferMappingFor(m => m .IdProperty(p => p.Name) ) ).Expect("x").WhenInferringIdOn(dto); - /** Even though we have a cache at play the cache is per connection settings, so we can create a different config */ + /** IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. + * + * Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance + * with different inference rules + */ WithConnectionSettings(x => x .InferMappingFor(m => m .IdProperty(p => p.OtherName) @@ -62,7 +83,11 @@ [U] public void CanGetIdFromDocument() ).Expect("y").WhenInferringIdOn(dto); } - /** Another way is to mark the type with an `ElasticsearchType` attribute, using a string `IdProperty` */ + /** === Using the `ElasticsearchType` attribute + * + * Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` + * to the name of the property that should be used for the document id + */ [ElasticsearchType(IdProperty = nameof(Name))] class MyOtherDTO { @@ -73,14 +98,15 @@ class MyOtherDTO [U] public void CanGetIdFromAttribute() { - /** Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the ConnectionSettings */ + /** Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` */ var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; Expect("x").WhenInferringIdOn(dto); - /** This attribute *is* cached statically/globally, however connectionsettings with a config for the type will - * still win over this static configuration. - * - * Even though we have a cache at play the cache its per connection settings, so we can create a different config + /** === Using Mapping inference on `ConnectionSettings` + * + * This attribute *is* cached statically/globally, however an inference rule on the `ConnectionSettings` for the type will + * still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance + * that will infer the document id from the property `OtherName`: */ WithConnectionSettings(x => x .InferMappingFor(m => m diff --git a/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs b/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs index de3be865d88..d33bd0d9f29 100644 --- a/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs +++ b/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs @@ -8,30 +8,40 @@ namespace Tests.CommonOptions.DateMath { public class DateMathEpressions { - /** # Date Expressions - * The date type supports using date math expression when using it in a query/filter - *Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified + /** == Date Math Expressions + * The date type supports using date math expression when using it in a query/filter + * Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified * - * The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with ||. - * It can then follow by a math expression, supporting +, - and / (rounding). - * The units supported are y (year), M (month), w (week), d (day), h (hour), m (minute), and s (second). + * The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with `||`. + * It can then follow by a math expression, supporting `+`, `-` and `/` (rounding). + * The units supported are + * + * - `y` (year) + * - `M` (month) + * - `w` (week) + * - `d` (day) + * - `h` (hour) + * - `m` (minute) + * - `s` (second) + * * as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. * - * Be sure to read the elasticsearch documentation {ref}/mapping-date-format.html#date-math[on this subject here] - + * Be sure to read the elasticsearch documentation {ref_current}/mapping-date-format.html#date-math[on this subject here] */ - [U] public void SimpleExpressions() { - /** You can create simple expressions using any of the static methods on `DateMath` */ + /** === Simple Expressions + * You can create simple expressions using any of the static methods on `DateMath` + */ Expect("now").WhenSerializing(Nest.DateMath.Now); Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05, 05))); - /** strings implicitly convert to date maths */ + /** strings implicitly convert to `DateMath` */ Expect("now").WhenSerializing("now"); /** but are lenient to bad math expressions */ var nonsense = "now||*asdaqwe"; + Expect(nonsense).WhenSerializing(nonsense) /** the resulting date math will assume the whole string is the anchor */ .Result(dateMath => ((IDateMath)dateMath) @@ -41,10 +51,10 @@ [U] public void SimpleExpressions() ) ); - /** date's also implicitly convert to simple date math expressions */ + /** `DateTime` also implicitly convert to simple date math expressions */ var date = new DateTime(2015, 05, 05); Expect("2015-05-05T00:00:00").WhenSerializing(date) - /** the anchor will be an actual DateTime, even after a serialization - deserialization round trip */ + /** the anchor will be an actual `DateTime`, even after a serialization/deserialization round trip */ .Result(dateMath => ((IDateMath)dateMath) . Anchor.Match( d => d.Should().Be(date), @@ -55,19 +65,21 @@ . Anchor.Match( [U] public void ComplexExpressions() { - /** Ranges can be chained on to simple expressions */ + /** === Complex Expressions + * Ranges can be chained on to simple expressions + */ Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); - /** plural means that you can chain multiple */ + /** Including multiple operations */ Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); - /** a rounding value can also be chained at the end afterwhich no more ranges can be appended */ + /** A rounding value can be chained to the end of the expression, after which no more ranges can be appended */ Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); - /** When anchoring date's we need to append `||` as clear separator between anchor and ranges */ - /** plural means that you can chain multiple */ + /** When anchoring dates, a `||` needs to be appended as clear separator between the anchor and ranges. + * Again, multiple ranges can be chained + */ Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); - } } diff --git a/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs b/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs index a6e3931159d..2f65ea8cb72 100644 --- a/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs +++ b/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs @@ -9,17 +9,16 @@ namespace Tests.CommonOptions.TimeUnit { public class TimeUnits { - /** # Time units + /** == Time units * Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified * as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. * - * ## Using Time units in NEST + * === Using Time units in NEST * NEST uses `Time` to strongly type this and there are several ways to construct one. * - * ### Constructor + * ==== Constructor * The most straight forward way to construct a `Time` is through its constructor */ - [U] public void Constructor() { var unitString = new Time("2d"); @@ -28,8 +27,13 @@ [U] public void Constructor() var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); /** - * When serializing Time constructed from a string, milliseconds, composition of factor and - * interval, or a `TimeSpan` the expression will be serialized as time unit string + * When serializing Time constructed from + * - a string + * - milliseconds (as a double) + * - composition of factor and interval + * - a `TimeSpan` + * + * the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` */ Expect("2d") .WhenSerializing(unitString) @@ -38,7 +42,7 @@ [U] public void Constructor() .WhenSerializing(unitMilliseconds); /** - * Milliseconds are always calculated even when not using the constructor that takes a long + * The `Milliseconds` property on `Time` is calculated even when not using the constructor that takes a double */ unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); unitComposed.Milliseconds.Should().Be(1000*60*60*24*2); @@ -46,10 +50,9 @@ [U] public void Constructor() unitString.Milliseconds.Should().Be(1000*60*60*24*2); } /** - * ### Implicit conversion - * Alternatively `string`, `TimeSpan` and `double` can be implicitly assigned to `Time` properties and variables + * ==== Implicit conversion + * Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` */ - [U] [SuppressMessage("ReSharper", "SuggestVarOrType_SimpleTypes")] public void ImplicitConversion() { @@ -62,7 +65,6 @@ public void ImplicitConversion() Expect("2d").WhenSerializing(twoDays); } - [U] [SuppressMessage("ReSharper", "SuggestVarOrType_SimpleTypes")] public void EqualityAndComparable() { @@ -71,14 +73,12 @@ public void EqualityAndComparable() Time twoDays = 1000*60*60*24*2; /** - * Milliseconds are calculated even when values are not passed as long + * Again, the `Milliseconds` property is calculated on `Time`, + * allowing you to do comparisons */ oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); twoWeeks.Milliseconds.Should().BeGreaterThan(1); - /** - * This allows you to do comparisons on the expressions - */ oneAndHalfYear.Should().BeGreaterThan(twoWeeks); (oneAndHalfYear > twoWeeks).Should().BeTrue(); (oneAndHalfYear >= twoWeeks).Should().BeTrue(); @@ -101,8 +101,8 @@ public void EqualityAndComparable() [U] public void UsingInterval() { - /** - * Time units are specified as a union of either a `DateInterval` or `Time` + /** === Time units + * Time units are specified as a union of either a `DateInterval` or `Time`, * both of which implicitly convert to the `Union` of these two. */ Expect("month").WhenSerializing>(DateInterval.Month); diff --git a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs index 7b25522564b..1cf58940b65 100644 --- a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs +++ b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs @@ -14,9 +14,9 @@ namespace Tests.QueryDsl.BoolDsl public class BoolDslTests : OperatorUsageBase { protected readonly IElasticClient Client = TestClient.GetFixedReturnClient(new { }); - + /** Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, - * take a single `bool` query with only two clauses + * take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses */ public void VerboseWay() { @@ -31,16 +31,16 @@ public void VerboseWay() ) ); } - /** Now, magine multiple nested bools this quickly becomes an exercise in - * _hadouken indenting_ + /**Now, imagine multiple nested bools this quickly becomes an exercise in _hadouken indenting_ * *[[indent]] *.hadouken indenting example - *image::{imagesdir}/hadouken_indentation.jpg[dead indent] + *image::{imagesdir}/hadouken-indentation.jpg[dead indent] * - * === Operator Overloading - * For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. - * The previous example now becomes the following with the fluent API + *=== Operator Overloading + * + *For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. + *The previous example now becomes the following with the fluent API */ public void UsingOperator() { @@ -59,23 +59,26 @@ public void UsingOperator() * * `term && term && term` to * - *> bool - *> |___must - *> |___term - *> |___bool - *> |___must - *> |___term - *> |___term + *.... + *bool + *|___must + * |___term + * |___bool + * |___must + * |___term + * |___term + *.... * * As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and * join them together to become a single bool query * - *> bool - *> |___must - *> |___term - *> |___term - *> |___term - * + *.... + *bool + *|___must + * |___term + * |___term + * |___term + *.... */ [U] public void JoinsMustQueries() => @@ -104,14 +107,16 @@ [U] public void UnaryAddOperatorAnd() => * * When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query * - *> bool - *> |___must - *> | |___term - *> | |___term - *> | |___term - > | - *> |___must_not - *> |___term + *.... + *bool + *|___must + *| |___term + *| |___term + *| |___term + *| + *|___must_not + * |___term + *.... */ [U] public void JoinsMustWithMustNot() @@ -127,20 +132,21 @@ [U] public void JoinsMustWithMustNot() } - /** Even more involved `term && term && term && !term && +term && +term` still only results in a single bool query: - - *> bool - *> |___must - *> | |___term - *> | |___term - *> | |___term - *> | - *> |___must_not - *> | |___term - *> | - *> |___filter - *> |___term - *> |___term + /** Even more involved `term && term && term && !term && +term && +term` still only results in a single `bool` query: + *.... + *bool + *|___must + *| |___term + *| |___term + *| |___term + *| + *|___must_not + *| |___term + *| + *|___filter + * |___term + * |___term + *.... */ [U] public void JoinsMustWithMustNotAndFilter() => @@ -155,8 +161,7 @@ [U] public void JoinsMustWithMustNotAndFilter() => }); /** You can still mix and match actual bool queries with the bool DSL e.g - * - * `bool(must=term, term, term) && !term` would still merge into a single bool query. + * `bool(must=term, term, term) && !term` would still merge into a single `bool` query. */ [U] public void MixAndMatch() => Assert( @@ -168,51 +173,50 @@ [U] public void MixAndMatch() => c.Bool.MustNot.Should().HaveCount(1); }); - /* NEST will also do the same with `should`'s or `||` when it sees that the boolean queries in play **ONLY** consist of `should clauses`. + /* NEST will also do the same with `should`s or `||` when it sees that the boolean queries in play **ONLY** consist of `should` clauses. * This is because the `bool` query does not quite follow the same boolean logic you expect from a programming language. - + * * To summarize, the latter: - + * * `term || term || term` - + * * becomes - - *> bool - *> |___should - *> |___term - *> |___term - *> |___term - - * but - - * `term1 && (term2 || term3 || term4)` will NOT become - - *> bool - *> |___must - *> | |___term1 - *> | - *> |___should - *> |___term2 - *> |___term3 - *> |___term4 - + *.... + *bool + *|___should + * |___term + * |___term + * |___term + *.... + * but `term1 && (term2 || term3 || term4)` does **NOT** become + *.... + *bool + *|___must + *| |___term1 + *| + *|___should + * |___term2 + * |___term3 + * |___term4 + *.... + * * This is because when a `bool` query has **only** `should` clauses, at least one of them must match. * When that `bool` query also has a `must` clause then the `should` clauses start acting as a _boost_ factor * and none of them have to match, drastically altering its meaning. - + * * So in the previous you could get back results that **ONLY** contain `term1`. This is clearly not what you want in the strict boolean sense of the input. - + * * To aid with this, NEST rewrites the previous query to - - *> bool - *> |___must - *> |___term1 - *> |___bool - *> |___should - *> |___term2 - *> |___term3 - *> |___term4 - + *.... + *bool + *|___must + * |___term1 + * |___bool + * |___should + * |___term2 + * |___term3 + * |___term4 + *.... */ [U] public void JoinsWithShouldClauses() => @@ -228,18 +232,19 @@ [U] public void JoinsWithShouldClauses() => lastClause.Bool.Should.Should().HaveCount(3); }); - /* NOTE: You can add parentheses to force evaluation order */ - - /* Also note that using shoulds as boosting factors can be really powerful so if you need this always remember that you can mix and match an actual bool query with the bool dsl */ - - /* There is another subtle situation where NEST will not blindly merge 2 bool queries with only should clauses. Image the following: - + /** TIP: You can add parentheses to force evaluation order + * + * Also note that using shoulds as boosting factors can be really powerful so if you need this + *always remember that you can mix and match an actual bool query with the bool dsl. + * + * There is another subtle situation where NEST will not blindly merge 2 bool queries with only should clauses. Imagine the following: + * * `bool(should=term1, term2, term3, term4, minimum_should_match=2) || term5 || term6` - - * if NEST identified both sides of the OR operation as only containing should clauses and it would join them together it would give a different meaning to the `minimum_should_match` parameter of the first boolean query. - * Rewriting this to a single bool with 5 should clauses would break because only matching on term5 or term6 should still be a hit. - */ - + * + * if NEST identified both sides of the OR operation as only containing `should` clauses and it would + * join them together it would give a different meaning to the `minimum_should_match` parameter of the first boolean query. + * Rewriting this to a single bool with 5 `should` clauses would break because only matching on `term5` or `term6` should still be a hit. + **/ [U] public void MixAndMatchMinimumShouldMatch() => Assert( q => q.Bool(b=>b @@ -260,6 +265,7 @@ [U] public void MixAndMatchMinimumShouldMatch() => }); /** === Locked bool queries + * * NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, * NEST will treat these as locked * diff --git a/src/Tests/QueryDsl/BoolDsl/hadouken-indentation.jpg b/src/Tests/QueryDsl/BoolDsl/hadouken-indentation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..afe03b960d1203610f217e1045a22142c0acc720 GIT binary patch literal 43939 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 literal 0 HcmV?d00001 diff --git a/src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs b/src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs index a4546a9c3a7..98e8d529567 100644 --- a/src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs +++ b/src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs @@ -6,15 +6,15 @@ namespace Tests.QueryDsl.Geo.Distance { public class DistanceUnits { - /** # Distance Units - * Whenever distances need to be specified, e.g. for a geo distance query, the distance unit can be specified - * as a double number representing distance in meters, as a new instance of a `Distance`, or as a string - * of the form number and distance unit e.g. `"2.72km"` + /** == Distance Units + * Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], + * the distance unit can be specified as a double number representing distance in meters, as a new instance of + * a `Distance`, or as a string of the form number and distance unit e.g. "`2.72km`" * - * ## Using Distance units in NEST + * === Using Distance units in NEST * NEST uses `Distance` to strongly type distance units and there are several ways to construct one. * - * ### Constructor + * ==== Constructor * The most straight forward way to construct a `Distance` is through its constructor */ [U] @@ -24,7 +24,7 @@ public void Constructor() var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); /** - * When serializing Distance constructed from a string, composition of distance value and unit + * `Distance` serializes to a string composed of a factor and distance unit */ Expect("25.0m") .WhenSerializing(unitComposed) @@ -32,7 +32,7 @@ public void Constructor() } /** - * ### Implicit conversion + * ==== Implicit conversion * Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. * If no `DistanceUnit` is specified, the default distance unit is meters */ @@ -48,54 +48,54 @@ public void ImplicitConversion() } /** - * ### Supported units + * ==== Supported units * A number of distance units are supported, from millimeters to nautical miles */ [U] public void UsingDifferentUnits() { - /** - * Miles + /** ===== Metric + *`mm` (Millimeters) */ - Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); + Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); /** - * Yards + *`cm` (Centimeters) */ - Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); + Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); /** - * Feet + *`m` (Meters) */ - Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); + Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); /** - * Inches + *`km` (Kilometers) */ - Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); + Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); - /** - * Kilometers + /** ===== Imperial + *`in` (Inches) */ - Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); + Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); /** - * Meters + *`ft` (Feet) */ - Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); + Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); /** - * Centimeters + *`yd` (Yards) */ - Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); + Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); /** - * Millimeters + *`mi` (Miles) */ - Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); + Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); /** - * Nautical Miles + *`nmi` or `NM` (Nautical Miles) */ Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); } diff --git a/src/Tests/index.asciidoc b/src/Tests/index.asciidoc index 41313633127..897e079d6ba 100644 --- a/src/Tests/index.asciidoc +++ b/src/Tests/index.asciidoc @@ -36,6 +36,7 @@ We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest === License +.... This software is licensed under the Apache 2 license, quoted below. Copyright (c) 2014 Elasticsearch @@ -51,5 +52,6 @@ This software is licensed under the Apache 2 license, quoted below. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +.... diff --git a/src/global.json b/src/global.json index 7a69a1ac22c..52a93658e3b 100644 --- a/src/global.json +++ b/src/global.json @@ -1,8 +1,11 @@ { - "projects": [ "src" ], - "sdk": { - "version": "1.0.0-rc1-update1", - "runtime": "clr", - "architecture": "x86" - } + "projects": [ + "src", + "wrap" + ], + "sdk": { + "version": "1.0.0-rc1-update1", + "runtime": "clr", + "architecture": "x86" + } } \ No newline at end of file diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll new file mode 100644 index 0000000000000000000000000000000000000000..1fc341935180ece7ba66799d7ec8146873563c2c GIT binary patch literal 68096 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Ξ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%0D4=;V>Vfk{E4OTfo~ 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 Date: Fri, 11 Mar 2016 10:24:09 +1100 Subject: [PATCH 07/18] Generate index.asciidoc from other files Support Callouts in documentation Tidy up names of generated asciidoc files Start bringing in usage documentation --- .../children-aggregation-mapping.asciidoc | 12 +- .../children-aggregation-usage.asciidoc | 79 +++++ .../date-histogram-aggregation-usage.asciidoc | 138 ++++++++ .../date-range-aggregation-usage.asciidoc | 115 +++++++ .../filter/filter-aggregation-usage.asciidoc | 142 ++++++++ .../filters-aggregation-usage.asciidoc | 310 ++++++++++++++++++ .../writing-aggregations.asciidoc | 11 +- .../connection-pooling.asciidoc | 4 +- .../date-time-providers.asciidoc | 13 +- .../keeping-track-of-nodes.asciidoc | 26 +- .../request-pipelines.asciidoc | 37 ++- .../building-blocks/transports.asciidoc | 18 +- .../exceptions/unexpected-exceptions.asciidoc | 4 +- .../unrecoverable-exceptions.asciidoc | 36 +- .../failover/falling-over.asciidoc | 4 +- .../max-retries/respects-max-retry.asciidoc | 4 +- .../pinging/first-usage.asciidoc | 4 +- .../pinging/revival.asciidoc | 4 +- .../disable-sniff-ping-per-request.asciidoc | 6 +- .../request-timeouts-overrides.asciidoc | 4 +- .../respects-allowed-status-code.asciidoc | 4 +- .../respects-force-node.asciidoc | 4 +- .../respects-max-retry-overrides.asciidoc | 4 +- .../round-robin/round-robin.asciidoc | 4 +- .../round-robin/skip-dead-nodes.asciidoc | 4 +- .../round-robin/volatile-updates.asciidoc | 4 +- .../sniffing/on-connection-failure.asciidoc | 4 +- .../sniffing/on-stale-cluster-state.asciidoc | 4 +- .../sniffing/on-startup.asciidoc | 4 +- .../sniffing/role-detection.asciidoc | 9 +- .../covariant-search-results.asciidoc | 4 +- .../inferrence/document-paths.asciidoc | 4 +- .../inferrence/field-inference.asciidoc | 4 +- .../inferrence/ids-inference.asciidoc | 4 +- .../inferrence/indices-paths.asciidoc | 4 +- .../inferrence/property-inference.asciidoc | 4 +- .../high-level/mapping/auto-map.asciidoc | 152 ++++----- .../low-level/connecting.asciidoc | 4 +- .../low-level/lifetimes.asciidoc | 4 +- .../low-level/post-data.asciidoc | 4 +- .../code-standards/descriptors.asciidoc | 4 +- .../code-standards/elastic-client.asciidoc | 4 +- .../naming-conventions.asciidoc | 15 +- docs/asciidoc/code-standards/queries.asciidoc | 4 +- .../serialization/properties.asciidoc | 4 +- .../date-math/date-math-expressions.asciidoc | 4 +- .../time-unit/time-units.asciidoc | 4 +- .../document/multiple/bulk/bulk-api.asciidoc | 49 +++ docs/asciidoc/images/hadouken_indentation.jpg | Bin 43939 -> 0 bytes docs/asciidoc/index.asciidoc | 124 ++++--- .../asciidoc/intro.asciidoc | 0 .../query-dsl/bool-dsl/bool-dsl.asciidoc | 7 +- .../compound/and/and-query-usage.asciidoc | 42 +++ .../geo/distance/distance-units.asciidoc | 4 +- libs/AsciiDoc.dll | Bin 68096 -> 0 bytes libs/AsciiDoc.pdb | Bin 235008 -> 0 bytes .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 62 +++- .../Documentation/Blocks/CodeBlock.cs | 36 +- .../Files/CSharpDocumentationFile.cs | 113 +++++-- .../Documentation/Files/DocumentationFile.cs | 5 +- .../Nest.Litterateur/Language.cs | 8 + src/CodeGeneration/Nest.Litterateur/LitUp.cs | 37 ++- .../Nest.Litterateur/StringExtensions.cs | 115 ++++++- .../Walkers/CodeWithDocumentationWalker.cs | 119 ++----- .../Walkers/DocumentationFileWalker.cs | 41 ++- .../ChildrenAggregationMapping.doc.cs | 8 +- ...s => ChildrenAggregationUsageTests.doc.cs} | 12 +- ...DateHistogramAggregationUsageTests.doc.cs} | 14 +- ... => DateRangeAggregationUsageTests.doc.cs} | 33 +- ....cs => FilterAggregationUsageTests.doc.cs} | 25 +- ...cs => FiltersAggregationUsageTests.doc.cs} | 21 +- .../Aggregations/WritingAggregations.doc.cs | 5 +- .../BuildingBlocks/DateTimeProviders.Doc.cs | 9 +- .../BuildingBlocks/KeepingTrackOfNodes.Doc.cs | 24 +- .../BuildingBlocks/RequestPipelines.doc.cs | 37 ++- .../BuildingBlocks/Transports.Doc.cs | 15 +- .../Exceptions/UnrecoverableExceptions.doc.cs | 17 +- .../DisableSniffPingPerRequest.doc.cs | 2 +- .../HighLevel/Mapping/AutoMap.doc.cs | 23 +- .../CodeStandards/NamingConventions.doc.cs | 11 +- .../Serialization/Properties.doc.cs | 3 - .../{BulkApiTests.cs => BulkApiTests.doc.cs} | 0 .../Document/Single/Update/UpdateApiTests.cs | 2 +- src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs | 2 +- ...sageTests.cs => AndQueryUsageTests.doc.cs} | 0 src/Tests/intro.asciidoc | 57 ++++ src/lib/dnx451/AsciiDoc.dll | Bin 68096 -> 69120 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 235008 -> 241152 bytes 88 files changed, 1820 insertions(+), 505 deletions(-) create mode 100644 docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc delete mode 100644 docs/asciidoc/images/hadouken_indentation.jpg rename src/Tests/index.asciidoc => docs/asciidoc/intro.asciidoc (100%) create mode 100644 docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc delete mode 100644 libs/AsciiDoc.dll delete mode 100644 libs/AsciiDoc.pdb create mode 100644 src/CodeGeneration/Nest.Litterateur/Language.cs rename src/Tests/Aggregations/Bucket/Children/{ChildrenAggregationUsageTests.cs => ChildrenAggregationUsageTests.doc.cs} (86%) rename src/Tests/Aggregations/Bucket/DateHistogram/{DateHistogramAggregationUsageTests.cs => DateHistogramAggregationUsageTests.doc.cs} (88%) rename src/Tests/Aggregations/Bucket/DateRange/{DateRangeAggregationUsageTests.cs => DateRangeAggregationUsageTests.doc.cs} (68%) rename src/Tests/Aggregations/Bucket/Filter/{FilterAggregationUsageTests.cs => FilterAggregationUsageTests.doc.cs} (84%) rename src/Tests/Aggregations/Bucket/Filters/{FiltersAggregationUsageTests.cs => FiltersAggregationUsageTests.doc.cs} (95%) rename src/Tests/Document/Multiple/Bulk/{BulkApiTests.cs => BulkApiTests.doc.cs} (100%) rename src/Tests/QueryDsl/Compound/And/{AndQueryUsageTests.cs => AndQueryUsageTests.doc.cs} (100%) create mode 100644 src/Tests/intro.asciidoc diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index b118f2c2095..71da482add2 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -1,8 +1,10 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images + +== Child Aggregation Mapping To use the child aggregation you have to make sure a `_parent` mapping is in place, here we create the project @@ -12,9 +14,9 @@ To use the child aggregation you have to make sure [source,csharp] ---- var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c - .Mappings(map=>map - .Map(m=>m.AutoMap()) - .Map(m=>m + .Mappings(map => map + .Map(tm => tm.AutoMap()) + .Map(tm => tm .Parent() ) ) diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc new file mode 100644 index 00000000000..1b72e54cd90 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -0,0 +1,79 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Children Aggregation + +A special single bucket aggregation that enables aggregating from buckets on parent document types to +buckets on child documents. + +Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "name_of_child_agg": { + "children": { + "type": "commits" + }, + "aggs": { + "average_per_child": { + "avg": { + "field": "confidenceFactor" + } + }, + "max_per_child": { + "max": { + "field": "confidenceFactor" + } + } + } + } + } +} +---- + +Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) + ) +) +---- + +Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", "confidenceFactor") && + new MaxAggregation("max_per_child", "confidenceFactor") + } +} + +new SearchRequest +{ + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) + && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) + } +} +---- + diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc new file mode 100644 index 00000000000..112bbc9d509 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -0,0 +1,138 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Date Histogram Aggregation + +A multi-bucket aggregation similar to the histogram except it can only be applied on date values. +From a functionality perspective, this histogram supports the same features as the normal histogram. +The main difference is that the interval can be specified by date/time expressions. + +When specifying a format and extended_bounds, in order for Elasticsearch to be able to parse +the serialized DateTimes of extended_bounds correctly, the date_optional_time format is included +as part of the format value. + +Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. + +[source,javascript] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month", + "min_doc_count": 2, + "format": "yyyy-MM-dd'T'HH:mm:ss||date_optional_time", + "order": { + "_count": "asc" + }, + "extended_bounds": { + "min": "2014-06-06T12:01:02.123", + "max": "2016-06-06T12:01:02.123" + }, + "missing": "2015-06-06T12:01:02.123" + }, + "aggs": { + "project_tags": { + "nested": { + "path": "tags" + }, + "aggs": { + "tags": { + "terms": { + "field": "tags.name" + } + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Size(0) +.Aggregations(aggs => aggs + .DateHistogram("projects_started_per_month", date => date + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .MinimumDocumentCount(2) + .Format("yyyy-MM-dd'T'HH:mm:ss") + .ExtendedBounds(FixedDate.AddYears(-1), FixedDate.AddYears(1)) + .Order(HistogramOrder.CountAscending) + .Missing(FixedDate) + .Aggregations(childAggs => childAggs + .Nested("project_tags", n => n + .Path(p => p.Tags) + .Aggregations(nestedAggs => nestedAggs + .Terms("tags", avg => avg.Field(p => p.Tags.First().Name)) + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = Field(p => p.StartedOn), + Interval = DateInterval.Month, + MinimumDocumentCount = 2, + Format = "yyyy-MM-dd'T'HH:mm:ss", + ExtendedBounds = new ExtendedBounds + { + Minimum = FixedDate.AddYears(-1), + Maximum = FixedDate.AddYears(1), + }, + Order = HistogramOrder.CountAscending, + Missing = FixedDate, + Aggregations = new NestedAggregation("project_tags") + { + Path = Field(p => p.Tags), + Aggregations = new TermsAggregation("tags") + { + Field = Field(p => p.Tags.First().Name) + } + } + } +} +---- + +=== Handling responses + +Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily +in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); + +var dateHistogram = response.Aggs.DateHistogram("projects_started_per_month"); +dateHistogram.Should().NotBeNull(); +dateHistogram.Buckets.Should().NotBeNull(); +dateHistogram.Buckets.Count.Should().BeGreaterThan(10); +item.Date.Should().NotBe(default(DateTime)); +item.DocCount.Should().BeGreaterThan(0); +var nested = item.Nested("project_tags"); +nested.Should().NotBeNull(); +var nestedTerms = nested.Terms("tags"); +nestedTerms.Buckets.Count.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc new file mode 100644 index 00000000000..de3ef457057 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -0,0 +1,115 @@ +:sectiontitle: Date Range Aggregation + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== {sectiontitle} + +A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` +and `to` values can be expressed in `DateMath` expressions, and it is also possible to specify a date format by which the from and +to response fields will be returned. + +IMPORTANT: this aggregation includes the `from` value and excludes the `to` value for each range. + +Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "projects_date_ranges": { + "date_range": { + "field": "startedOn", + "ranges": [ + { + "to": "now", + "from": "2015-06-06T12:01:02.123||+2d" + }, + { + "to": "now+1d-30m/h" + }, + { + "from": "2012-05-05||+1d-1m" + } + ] + }, + "aggs": { + "project_tags": { + "terms": { + "field": "tags" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .DateRange("projects_date_ranges", date => date + .Field(p => p.StartedOn) + .Ranges( + r => r.From(DateMath.Anchored(FixedDate).Add("2d")).To(DateMath.Now), + r => r.To(DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour)), + r => r.From(DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m")) + ) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.Tags)) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new DateRangeAggregation("projects_date_ranges") + { + Field = Field(p => p.StartedOn), + Ranges = new List + { + new DateRangeExpression { From = DateMath.Anchored(FixedDate).Add("2d"), To = DateMath.Now}, + new DateRangeExpression { To = DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour) }, + new DateRangeExpression { From = DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m") } + }, + Aggregations = + new TermsAggregation("project_tags") { Field = Field(p => p.Tags) } + } +} +---- + +=== Handling Responses + +Using the `.Agg` aggregation helper we can fetch our aggregation results easily +in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); + +var dateHistogram = response.Aggs.DateRange("projects_date_ranges"); +dateHistogram.Should().NotBeNull(); +dateHistogram.Buckets.Should().NotBeNull(); +---- + +We specified three ranges so we expect to have three of them in the response + +[source,csharp] +---- +dateHistogram.Buckets.Count.Should().Be(3); + +item.DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc new file mode 100644 index 00000000000..b25edef30fc --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -0,0 +1,142 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Filter Aggregation + +Defines a single bucket of all the documents in the current document set context that match a specified filter. +Often this will be used to narrow down the current aggregation context to a specific set of documents. + +Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "bethels_projects": { + "filter": { + "term": { + "leadDeveloper.firstName": { + "value": "pierce" + } + } + }, + "aggs": { + "project_tags": { + "terms": { + "field": "curatedTags.name" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filter("bethels_projects", date => date + .Filter(q => q.Term(p => p.LeadDeveloper.FirstName, FirstNameToFind)) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new FilterAggregation("bethels_projects") + { + Filter = new TermQuery {Field = Field(p => p.LeadDeveloper.FirstName), Value = FirstNameToFind}, + Aggregations = + new TermsAggregation("project_tags") {Field = Field(p => p.CuratedTags.First().Name)} + } +} +---- + +=== Handling Responses + +Using the `.Aggs` aggregation helper we can fetch our aggregation results easily +in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); + +var filterAgg = response.Aggs.Filter("bethels_projects"); +filterAgg.Should().NotBeNull(); +filterAgg.DocCount.Should().BeGreaterThan(0); +var tags = filterAgg.Terms("project_tags"); +tags.Should().NotBeNull(); +tags.Buckets.Should().NotBeEmpty(); +---- + +== Empty Filter + +When the collection of filters is empty or all are conditionless, NEST will serialize them +to an empty object. + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "empty_filter": { + "filter": {} + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filter("empty_filter", date => date + .Filter(f => f + .Bool(b => b + .Filter(new QueryContainer[0]) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new FilterAggregation("empty_filter") + { + Filter = new BoolQuery + { + Filter = new List() + } + } +} +---- + +=== Handling Response + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); +response.Aggs.Filter("empty_filter").DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc new file mode 100644 index 00000000000..8ad1dd26a2f --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -0,0 +1,310 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Filters Aggregation + +Defines a multi bucket aggregations where each bucket is associated with a filter. +Each bucket will collect all documents that match its associated filter. For documents +that do not match any filter, these will be collected in the other bucket. + +Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-filters-aggregation.html[on this subject here] + +== Named filters + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "projects_by_state": { + "filters": { + "other_bucket": true, + "other_bucket_key": "other_states_of_being", + "filters": { + "belly_up": { + "term": { + "state": { + "value": "BellyUp" + } + } + }, + "stable": { + "term": { + "state": { + "value": "Stable" + } + } + }, + "very_active": { + "term": { + "state": { + "value": "VeryActive" + } + } + } + } + }, + "aggs": { + "project_tags": { + "terms": { + "field": "curatedTags.name" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filters("projects_by_state", agg => agg + .OtherBucket() + .OtherBucketKey("other_states_of_being") + .NamedFilters(filters => filters + .Filter("belly_up", f => f.Term(p => p.State, StateOfBeing.BellyUp)) + .Filter("stable", f => f.Term(p => p.State, StateOfBeing.Stable)) + .Filter("very_active", f => f.Term(p => p.State, StateOfBeing.VeryActive)) + ) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) + ) + ) +) +---- + +Object Initializer Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new FiltersAggregation("projects_by_state") + { + OtherBucket = true, + OtherBucketKey = "other_states_of_being", + Filters = new NamedFiltersContainer + { + { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, + { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, + { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } + }, + Aggregations = + new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } + } +} +---- + +=== Handling Responses + +Using the `.Agg` aggregation helper we can fetch our aggregation results easily +in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); + +var filterAgg = response.Aggs.Filters("projects_by_state"); +filterAgg.Should().NotBeNull(); +var namedResult = filterAgg.NamedBucket("belly_up"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().BeGreaterThan(0); +namedResult = filterAgg.NamedBucket("stable"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().BeGreaterThan(0); +namedResult = filterAgg.NamedBucket("very_active"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().BeGreaterThan(0); +namedResult = filterAgg.NamedBucket("other_states_of_being"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().Be(0); +---- + +== Anonymous filters + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "projects_by_state": { + "filters": { + "other_bucket": true, + "filters": [ + { + "term": { + "state": { + "value": "BellyUp" + } + } + }, + { + "term": { + "state": { + "value": "Stable" + } + } + }, + { + "term": { + "state": { + "value": "VeryActive" + } + } + } + ] + }, + "aggs": { + "project_tags": { + "terms": { + "field": "curatedTags.name" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filters("projects_by_state", agg => agg + .OtherBucket() + .AnonymousFilters( + f => f.Term(p => p.State, StateOfBeing.BellyUp), + f => f.Term(p => p.State, StateOfBeing.Stable), + f => f.Term(p => p.State, StateOfBeing.VeryActive) + ) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new FiltersAggregation("projects_by_state") + { + OtherBucket = true, + Filters = new List + { + Query.Term(p=>p.State, StateOfBeing.BellyUp) , + Query.Term(p=>p.State, StateOfBeing.Stable) , + Query.Term(p=>p.State, StateOfBeing.VeryActive) + }, + Aggregations = + new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } + } +} +---- + +Using the `.Agg` aggregation helper we can fetch our aggregation results easily +in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); + +var filterAgg = response.Aggs.Filters("projects_by_state"); +filterAgg.Should().NotBeNull(); +var results = filterAgg.AnonymousBuckets(); +results.Count.Should().Be(4); +singleBucket.DocCount.Should().BeGreaterThan(0); +results.Last().DocCount.Should().Be(0); +---- + +== Empty Filters + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "empty_filters": { + "filters": { + "filters": [] + } + } + } +} +---- + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filters("empty_filters", agg => agg + .AnonymousFilters() + ) +) + +new SearchRequest +{ + Aggregations = new FiltersAggregation("empty_filters") + { + Filters = new List() + } +} + +response.IsValid.Should().BeTrue(); +response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); +---- + +== Conditionless Filters + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "conditionless_filters": { + "filters": { + "filters": [] + } + } + } +} +---- + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filters("conditionless_filters", agg => agg + .AnonymousFilters( + q => new QueryContainer() + ) + ) +) + +new SearchRequest +{ + Aggregations = new FiltersAggregation("conditionless_filters") + { + Filters = new List + { + new QueryContainer() + } + } +} + +response.IsValid.Should().BeTrue(); +response.Aggs.Filters("conditionless_filters").Buckets.Should().BeEmpty(); +---- + diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 9df658d1d0a..ba25185bc1f 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images/ +:imagesdir: ../images == Aggregations @@ -112,7 +112,7 @@ on the request. Using LINQ's `.Aggregate()` method, each function can be applied [source,csharp] ---- -var aggregations = new List, IAggregationContainer>> +var aggregations = new List, IAggregationContainer>> //<1> { a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) @@ -121,9 +121,12 @@ return s => s .Aggregations(aggs => aggs .Children("name_of_child_agg", child => child .Aggregations(childAggs => - aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) + aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) //<2> ) ) ); ---- +<1> a list of aggregation functions to apply + +<2> Using LINQ's `Aggregate()` function to accumulate/apply all of the aggregation functions diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index fb625e86b05..02a3fcf6394 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Connection Pooling diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 816983a8a94..eb3ac9bdd24 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -1,14 +1,14 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Date time providers Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` -in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover -in run time not being bound to wall clock time. +in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover +without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. [source,csharp] ---- @@ -31,8 +31,8 @@ to provide a custom implementation for. var dateTimeProvider = DateTimeProvider.Default; ---- -The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)` -The default values for `timeout` and `maxTimeout` are +The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the +default values for `timeout` and `maxTimeout` are [source,csharp] ---- @@ -46,6 +46,7 @@ Plotting these defaults looks as followed: [[timeout]] .Default formula, x-axis time in minutes, y-axis number of attempts to revive image::{imagesdir}/timeoutplot.png[dead timeout] + The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 142b58176f2..2696401973a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -1,14 +1,19 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Keeping track of nodes +=== Creating a Node + +A `Node` can be instantiated by passing it a `Uri` + [source,csharp] ---- var node = new Node(new Uri("http://localhost:9200")); + node.Uri.Should().NotBeNull(); node.Uri.Port.Should().Be(9200); ---- @@ -32,7 +37,10 @@ node.IsResurrected.Should().BeTrue(); When instantiating your connection pool you could switch these to false to initialize the client to a known cluster topology. -passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy +=== Building a Node path + +passing a node with a path should be preserved. +Sometimes an elasticsearch node lives behind a proxy [source,csharp] ---- @@ -58,6 +66,12 @@ which is exactly what the `CreatePath` method does on `Node` combinedPath = node.CreatePath("index/type/_search"); combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); +---- + +=== Marking Nodes + +[source,csharp] +---- var node = new Node(new Uri("http://localhost:9200")); node.FailedAttempts.Should().Be(0); node.IsAlive.Should().BeTrue(); @@ -75,7 +89,7 @@ node.IsAlive.Should().BeFalse(); node.DeadUntil.Should().Be(deadUntil); ---- -however when marking a node alive deaduntil should be reset and attempts reset to 0 +however when marking a node alive, the `DeadUntil` property should be reset and `FailedAttempts` reset to 0 [source,csharp] ---- @@ -86,7 +100,9 @@ node.DeadUntil.Should().Be(default(DateTime)); node.IsAlive.Should().BeTrue(); ---- -Nodes are considered equal if they have the same endpoint no matter what other metadata is associated +=== Node Equality + +Nodes are considered equal if they have the same endpoint, no matter what other metadata is associated [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 5da5cb7b29e..7a0b0094768 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -1,14 +1,13 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images -== Request pipeline +== Request Pipeline - * - * Every request is executed in the context of a `RequestPipeline` when using the - default `ITransport` implementation. +Every request is executed in the context of a `RequestPipeline` when using the +default `ITransport` implementation. [source,csharp] ---- @@ -24,28 +23,30 @@ var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new Memor pipeline.GetType().Should().Implement(); ---- -However the transport does not instantiate RequestPipeline directly, it uses a pluggable `IRequestPipelineFactory` +However the transport does not instantiate `RequestPipeline` directly; it uses a pluggable `IRequestPipelineFactory` +to create it [source,csharp] ---- var requestPipelineFactory = new RequestPipelineFactory(); -var requestPipeline = requestPipelineFactory.Create(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); +var requestPipeline = requestPipelineFactory.Create( + settings, + DateTimeProvider.Default, //<1> + new MemoryStreamFactory(), + new SearchRequestParameters()); requestPipeline.Should().BeOfType(); requestPipeline.GetType().Should().Implement(); ---- +<1> An <> -which can be passed to the transport when instantiating a client +you can pass your own `IRequestPipeline` implementation to the transport when instantiating a client +allowing you to have requests executed on your own custom request pipeline [source,csharp] ---- var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); ----- - -this allows you to have requests executed on your own custom request pipeline -[source,csharp] ----- var pool = setupPool(new[] { TestClient.CreateNode(), TestClient.CreateNode(9201) }); var settings = new ConnectionSettings(pool, TestClient.CreateConnection()); settings = settingsSelector?.Invoke(settings) ?? settings; @@ -65,7 +66,7 @@ sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeTrue(); ---- Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() - You can however disable this on ConnectionSettings +You can however disable this on ConnectionSettings [source,csharp] ---- @@ -81,7 +82,7 @@ sniffingPipeline.SniffsOnConnectionFailure.Should().BeTrue(); ---- Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() - You can however disable this on ConnectionSettings +You can however disable this on ConnectionSettings [source,csharp] ---- @@ -123,8 +124,8 @@ the sniffing connection pool supports reseeding so the pipeline will signal the sniffingPipeline.StaleClusterState.Should().BeTrue(); ---- -A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout - See the maxretry documentation for more details, here we assert that our request pipeline exposes this propertly +A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout. +See the <> for more details, here we assert that our request pipeline exposes this propertly [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index c945d20d8e4..a41e550697c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -1,17 +1,19 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Transports -The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. -It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote -the internals of the client, by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. +The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple and +it's ultimately responsible from translating a client call to a response. -Transport is generically typed to a type that implements IConnectionConfigurationValues -This is the minimum ITransport needs to report back for the client to function. +If for some reason you do not agree with the way we wrote the internals of the client, +by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. + +Transport is generically typed to a type that implements `IConnectionConfigurationValues` +This is the minimum `ITransport` needs to report back for the client to function. e.g in the low level client, transport is instantiated like this: @@ -32,7 +34,7 @@ var inMemoryTransport = new Transport(new ConnectionSettings The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the default `ITransport` implementation is responsible for introducing many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. -If you feel this need, please let us know as we'd love to learn why you've go down this route! +If you feel this need, {github}/issues[please let us know] as we'd love to learn why you've go down this route! [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index 25611735389..ad1341342ad 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Unexpected exceptions diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index fc6a834aaf0..3984b6f7b24 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -1,16 +1,19 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Unrecoverable exceptions -Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. -By default the client won't throw on any ElasticsearchClientException but return an invalid response. -You can configure the client to throw using ThrowExceptions() on ConnectionSettings. The following test +Unrecoverable exceptions are _excepted_ exceptions that are grounds to exit the client pipeline immediately. +By default, the client won't throw on any `ElasticsearchClientException` but instead return an invalid response which +can be detected by checking `.IsValid` on the response +You can configure the client to throw using `ThrowExceptions()` on `ConnectionSettings`. The following test both a client that throws and one that returns an invalid response with an `.OriginalException` exposed +The following are recoverable exceptions + [source,csharp] ---- var recoverablExceptions = new[] @@ -18,7 +21,14 @@ var recoverablExceptions = new[] new PipelineException(PipelineFailure.BadResponse), new PipelineException(PipelineFailure.PingFailure), }; + recoverablExceptions.Should().OnlyContain(e => e.Recoverable); +---- + +and the unrecoverable exceptions + +[source,csharp] +---- var unrecoverableExceptions = new[] { new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), @@ -28,7 +38,15 @@ var unrecoverableExceptions = new[] new PipelineException(PipelineFailure.MaxRetriesReached), new PipelineException(PipelineFailure.MaxTimeoutReached) }; + unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); +---- + +As an example, let's set up a 10 node cluster that will always succeed when pinged but + will fail with a 401 response when making client calls + +[source,csharp] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Ping(r => r.SucceedAlways()) @@ -36,6 +54,13 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .AllDefaults() ); +---- + +Here we make a client call and determine that the first audit event was a successful ping, +followed by a bad response as a result of a bad authentication response + +[source,csharp] +---- audit = await audit.TraceElasticsearchException( new ClientCall { { AuditEvent.PingSuccess, 9200 }, @@ -46,6 +71,5 @@ audit = await audit.TraceElasticsearchException( e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); } ); -e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 27a368fa892..93afbaf7f6c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Fail over diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index e5e7c5b60b5..b55737ef6d8 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == MaxRetries diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index 50a067de8ad..defe38fe597 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Pinging - First Usage diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index cee8a500461..2d4113d346a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Pinging - Revival diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 40646d0abdc..34a335e3942 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Disabling sniffing and pinging on a request basis @@ -22,7 +22,7 @@ var audit = new Auditor(() => Framework.Cluster ); ---- -We disable sniffing so eventhoug its our first call we do not want to sniff on startup +We disable sniffing so even though its our first call, we do not want to sniff on startup Instead the sniff on startup is deffered to the second call into the cluster that does not disable sniffing on a per request basis diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 5facc37443c..1bd000560d4 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Request Timeouts diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index f78b9ff4d56..1488ba9f0ad 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Allowed status codes diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 2edb99c9108..c439bc6b562 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Forcing nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index d6c4f750abb..e71e2b38242 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Maximum Retries diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index 90545f2690c..bf9263b1b1c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images Round Robin Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 96f2b678fe6..62b6711d247 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Round Robin - Skipping Dead Nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index d153d19e86f..7d91649a11a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index 6374cd9e5ba..f22882c65f1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Sniffing on connection failure diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index 25816f351d0..43401a943b1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Sniffing periodically diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index 0e3970e736e..f7dbee0f6c6 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Sniffing on startup diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index a0a28493398..bc0c4607560 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -1,14 +1,13 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Sniffing role detection - * - * When we sniff the custer state we detect the role of the node whether its master eligible and holds data - We use this information when selecting a node to perform an API call on. +When we sniff the custer state we detect the role of the node whether its master eligible and holds data +We use this information when selecting a node to perform an API call on. [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index ac96d217f32..6f8e30786b7 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images = Covariant Search Results diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc index df4686cb32d..aea54b7736f 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images = DocumentPaths diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc index 67e2daa2833..456615dd0b6 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images = Strongly typed field access diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc index ba13264f705..f0e6b6f369b 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Id Inference diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc index f422f6914ac..586c106ca00 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images = Indices paths diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc index 89f3a3519e3..75708f8f3e4 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images Property names resolve to the last token. An example using the `.Suffix()` extension diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index 7bbbc05fa74..51354e9a7b7 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -1,23 +1,20 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Auto mapping properties - * - * When creating a mapping (either when creating an index or via the put mapping API), - * NEST offers a feature called AutoMap(), which will automagically infer the correct - * Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if - * you're using attributes to map your properties, then calling AutoMap() is required - * in order for your attributes to be applied. We'll look at examples of both. - * - * +When creating a mapping (either when creating an index or via the put mapping API), +NEST offers a feature called AutoMap(), which will automagically infer the correct +Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if +you're using attributes to map your properties, then calling AutoMap() is required +in order for your attributes to be applied. We'll look at examples of both. - * For these examples, we'll define two POCOS, `Company`, which has a name - * and a collection of Employees, and `Employee` which has various properties of - different types, and itself has a collection of `Employee` types. +For these examples, we'll define two POCOS, `Company`, which has a name +and a collection of Employees, and `Employee` which has various properties of +different types, and itself has a collection of `Employee` types. [source,csharp] ---- @@ -41,8 +38,8 @@ public class Employee === Manual mapping - * To create a mapping for our Company type, we can use the fluent API - * and map each property explicitly +To create a mapping for our Company type, we can use the fluent API +and map each property explicitly [source,csharp] ---- @@ -73,9 +70,9 @@ var descriptor = new CreateIndexDescriptor("myindex") ); ---- - * This is all fine and dandy and useful for some use cases however in most cases - * this can become verbose and wieldy. The majority of the time you simply just want to map *all* - the properties of a POCO in a single go. +This is all fine and dandy and useful for some use cases however in most cases +this can become verbose and wieldy. The majority of the time you simply just want to map *all* +the properties of a POCO in a single go. [source,csharp] ---- @@ -120,8 +117,8 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); === Simple Automapping - * This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, - * explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work +This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, +explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work [source,csharp] ---- @@ -132,14 +129,19 @@ var descriptor = new CreateIndexDescriptor("myindex") ); ---- - * Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. - * In this example, - * - Birthday was mapped as a date, - * - Hours was mapped as a long (ticks) - * - IsManager was mapped as a boolean, - * - Salary as an integer - * - Employees as an object - * and the remaining string properties as strings. +Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. +In this example, + +* Birthday was mapped as a date, + +* Hours was mapped as a long (ticks) + +* IsManager was mapped as a boolean, + +* Salary as an integer + +* Employees as an object +and the remaining string properties as strings. [source,csharp] ---- @@ -236,13 +238,13 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); == Automapping with overrides - * In most cases, you'll want to map more than just the vanilla datatypes and also provide - * various options on your properties (analyzer, docvalues, etc...). In that case, it's - * possible to use AutoMap() in conjuction with explicitly mapped properties. +In most cases, you'll want to map more than just the vanilla datatypes and also provide +various options on your properties (analyzer, docvalues, etc...). In that case, it's +possible to use AutoMap() in conjuction with explicitly mapped properties. - * Here we are using AutoMap() to automatically map our company type, but then we're - * overriding our employee property and making it a `nested` type, since by default, - AutoMap() will infer objects as `object`. +Here we are using AutoMap() to automatically map our company type, but then we're +overriding our employee property and making it a `nested` type, since by default, +AutoMap() will infer objects as `object`. [source,csharp] ---- @@ -287,9 +289,9 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); == Automap with attributes - * It is also possible to define your mappings using attributes on your POCOS. When you - * use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. - Here we define the same two types but this time using attributes. +It is also possible to define your mappings using attributes on your POCOS. When you +use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. +Here we define the same two types but this time using attributes. [source,csharp] ---- @@ -473,9 +475,9 @@ var expected = new Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- - * Just as we were able to override the inferred properties in our earlier example, explicit (manual) - * mappings also take precedence over attributes. Therefore we can also override any mappings applied - via any attributes defined on the POCO +Just as we were able to override the inferred properties in our earlier example, explicit (manual) +mappings also take precedence over attributes. Therefore we can also override any mappings applied +via any attributes defined on the POCO [source,csharp] ---- @@ -638,16 +640,16 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); == Ignoring Properties - * Properties on a POCO can be ignored in a few ways: - * - * - Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO - * - * - Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings - * - * - Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` - * - * This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the - * property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` +Properties on a POCO can be ignored in a few ways: + +* Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO + +* Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings + +* Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` + +This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the +property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` [source,csharp] ---- @@ -703,17 +705,17 @@ settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); == Mapping Recursion - * If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive - * in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only - * traverse a single depth when it encounters recursive instances like this. Hence, in the - * previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. - * This is done as a safe-guard to prevent stack overflows and all the fun that comes with - * infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is - * often an edge case to have deeply nested mappings like this. However, you may still have - * the need to do this, so you can control the recursion depth of `.AutoMap()`. - * - * Let's introduce a very simple class, `A`, which itself has a property - Child of type `A`. +If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive +in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only +traverse a single depth when it encounters recursive instances like this. Hence, in the +previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. +This is done as a safe-guard to prevent stack overflows and all the fun that comes with +infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is +often an edge case to have deeply nested mappings like this. However, you may still have +the need to do this, so you can control the recursion depth of `.AutoMap()`. + +Let's introduce a very simple class, `A`, which itself has a property +Child of type `A`. [source,csharp] ---- @@ -816,13 +818,13 @@ Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRe == Applying conventions through the Visitor pattern - * It is also possible to apply a transformation on all or specific properties. - * - * AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, - * does nothing and acts as a blank canvas for you to implement your own visiting methods. - * - * For instance, lets create a custom visitor that disables doc values for numeric and boolean types. - (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) +It is also possible to apply a transformation on all or specific properties. + +AutoMap internally implements the https://en.wikipedia.org/wiki/Visitorpattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, +does nothing and acts as a blank canvas for you to implement your own visiting methods. + +For instance, lets create a custom visitor that disables doc values for numeric and boolean types. +(Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) [source,csharp] ---- @@ -848,13 +850,14 @@ Now we can pass an instance of our custom visitor to `.AutoMap()` ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms - .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) + .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) //<1> ); ---- +<1> Pass your `IPropertyVisitor` implementation to `.AutoMap` and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) - * it will apply the transformation defined in each Visit() respectively, which in this example - * disables {ref_current}/doc-values.html[doc values]. +it will apply the transformation defined in each `Visit()` respectively, which in this example +disables {ref_current}/doc-values.html[doc values]. [source,csharp] ---- @@ -900,14 +903,15 @@ var expected = new ---- You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit - * directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types - * to an Elasticsearch string (`IStringProperty`). +directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types +to an Elasticsearch string (`IStringProperty`). [source,csharp] ---- public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { - public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); + public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => + new StringProperty(); } var descriptor = new CreateIndexDescriptor("myindex") diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 2ba414a38da..abffb6a6b9c 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images = Choosing the right connection strategy diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index c8a555233b7..2a748ce8831 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images == Lifetimes diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index 07512df22ad..e52a6e02b06 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images = Post data diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 9bbe9ec0ac1..84d5902210c 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images/ +:imagesdir: ../images Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index dde8600a29d..7edaffb58e8 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images/ +:imagesdir: ../images [source,csharp] ---- diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 9c6e9843182..47ca8b2afa4 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -1,14 +1,14 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images/ +:imagesdir: ../images -= Naming Conventions +== Naming Conventions NEST uses the following naming conventions (with _some_ exceptions). -== Class Names +=== Class Names Abstract class names should end with a `Base` suffix @@ -40,7 +40,7 @@ var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() baseClassesNotAbstract.Should().BeEmpty(); ---- -== Requests and Responses +=== Requests and Responses Request class names should end with `Request` @@ -72,11 +72,11 @@ responses.Should().BeEmpty(); Request and Response class names should be one to one in *most* cases. e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => `ValidateResponse` There are a few exceptions to this rule, most notably the `Cat` prefixed requests and -`Exists` requests. +the `Exists` requests. [source,csharp] ---- -var exceptions = new[] +var exceptions = new[] //<1> { typeof(CatAliasesRequest), typeof(CatAllocationRequest), @@ -127,4 +127,5 @@ var responses = types .Select(t => t.Name.Split('`')[0].Replace("Response", "")); requests.Except(responses).Should().BeEmpty(); ---- +<1> _Exceptions to the rule_ diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index f5926e9f830..d0ea04540ee 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images/ +:imagesdir: ../images [source,csharp] ---- diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index ecf0d8aed97..31d535904bc 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images Our Json.NET contract resolver picks up attributes set on the interface diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index bfb9304e59f..c2fd6b6f53e 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images == Date Math Expressions diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index 80caeaaaa44..749db99bc69 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images == Time units diff --git a/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc b/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc new file mode 100644 index 00000000000..c44ca22247a --- /dev/null +++ b/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc @@ -0,0 +1,49 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp] +---- +response.Took.Should().BeGreaterThan(0); +response.Errors.Should().BeFalse(); +response.ItemsWithErrors.Should().NotBeNull().And.BeEmpty(); +response.Items.Should().NotBeEmpty(); +item.Index.Should().Be(CallIsolatedValue); +item.Type.Should().Be("project"); +item.Status.Should().BeGreaterThan(100); +item.Version.Should().BeGreaterThan(0); +item.Id.Should().NotBeNullOrWhiteSpace(); +item.IsValid.Should().BeTrue(); +item.Shards.Should().NotBeNull(); +item.Shards.Total.Should().BeGreaterThan(0); +item.Shards.Successful.Should().BeGreaterThan(0); +var p1 = this.Client.Source(Project.Instance.Name, p=>p.Index(CallIsolatedValue)); +p1.LeadDeveloper.FirstName.Should().Be("martijn"); + +d => d +.Index(CallIsolatedValue) +.Index(b => b.Document(Project.Instance)) +.Update(b => b.Doc(new { leadDeveloper = new { firstName = "martijn" } }).Id(Project.Instance.Name)) +.Create(b => b.Document(Project.Instance).Id(Project.Instance.Name + "1")) +.Delete(b=>b.Id(Project.Instance.Name + "1")) + +new BulkRequest(CallIsolatedValue) + { +Operations = new List +{ + new BulkIndexOperation(Project.Instance), + new BulkUpdateOperation(Project.Instance) + { + Doc = new { leadDeveloper = new { firstName = "martijn" } } + }, + new BulkCreateOperation(Project.Instance) + { + Id = Project.Instance.Name + "1" + }, + new BulkDeleteOperation(Project.Instance.Name + "1"), +} + } +---- + diff --git a/docs/asciidoc/images/hadouken_indentation.jpg b/docs/asciidoc/images/hadouken_indentation.jpg deleted file mode 100644 index afe03b960d1203610f217e1045a22142c0acc720..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43939 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 diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 897e079d6ba..694413cee35 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -1,57 +1,107 @@ -:github: https://github.com/elastic/elasticsearch-net -:stackoverflow: http://stackoverflow.com +[[elasticsearch-net-reference]] += Elasticsearch.Net and NEST documentation:.NET Elasticsearch clients -== Introduction +include::intro.asciidoc[] -You've reached the documentation page for `Elasticsearch.Net` and `NEST`. The two official .NET clients for Elasticsearch. So why two clients I hear you say? +include::aggregations/bucket/children/children-aggregation-mapping.asciidoc[] -`Elasticsearch.Net` is a very low level, dependency free, client that has no opinions about how you build and represent your requests and responses. It has abstracted -enough so that **all** the Elasticsearch API endpoints are represented as methods but not too much to get in the way of how you want to build your json/request/response objects. It also comes with builtin, configurable/overridable, cluster failover retry mechanisms. Elasticsearch is elastic so why not your client? +include::aggregations/bucket/children/children-aggregation-usage.asciidoc[] -`NEST` is a high level client that has the advantage of having mapped all the request and response objects, comes with a strongly typed query DSL that maps 1 to 1 with the Elasticsearch query DSL, and takes advantage of specific .NET features such as covariant results. NEST internally uses, and still exposes, the low level `Elasticsearch.Net` client. +include::aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] -Please read the getting started guide for both. +include::aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] -=== Who's using Nest -* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). -* http://www.7digital.com[7digital.com] (run NEST on mono). -* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). -* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. - They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] +include::aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] -=== Other resources +include::aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] -http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a great http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] -using NEST. +include::aggregations/writing-aggregations.asciidoc[] -Also checkout the https://searchbox.io/[searchbox.io guys] rocking NEST http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] -with their https://github.com/searchbox-io/.net-sample[demo project] +include::client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc[] -=== Questions, bugs, comments, requests +include::client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc[] -All of these are more then welcome on the {github}/issues[github issues pages]! We try to to at least reply within the same day. +include::client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc[] -We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or -{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow] +include::client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc[] -=== License +include::client-concepts/connection-pooling/building-blocks/transports.asciidoc[] -.... -This software is licensed under the Apache 2 license, quoted below. +include::client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc[] - Copyright (c) 2014 Elasticsearch +include::client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc[] - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +include::client-concepts/connection-pooling/failover/falling-over.asciidoc[] - http://www.apache.org/licenses/LICENSE-2.0 +include::client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc[] - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -.... +include::client-concepts/connection-pooling/pinging/first-usage.asciidoc[] +include::client-concepts/connection-pooling/pinging/revival.asciidoc[] + +include::client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc[] + +include::client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc[] + +include::client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc[] + +include::client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc[] + +include::client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc[] + +include::client-concepts/connection-pooling/round-robin/round-robin.asciidoc[] + +include::client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc[] + +include::client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc[] + +include::client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc[] + +include::client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc[] + +include::client-concepts/connection-pooling/sniffing/on-startup.asciidoc[] + +include::client-concepts/connection-pooling/sniffing/role-detection.asciidoc[] + +include::client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc[] + +include::client-concepts/high-level/inferrence/document-paths.asciidoc[] + +include::client-concepts/high-level/inferrence/field-inference.asciidoc[] + +include::client-concepts/high-level/inferrence/ids-inference.asciidoc[] + +include::client-concepts/high-level/inferrence/indices-paths.asciidoc[] + +include::client-concepts/high-level/inferrence/property-inference.asciidoc[] + +include::client-concepts/high-level/mapping/auto-map.asciidoc[] + +include::client-concepts/low-level/connecting.asciidoc[] + +include::client-concepts/low-level/lifetimes.asciidoc[] + +include::client-concepts/low-level/post-data.asciidoc[] + +include::code-standards/descriptors.asciidoc[] + +include::code-standards/elastic-client.asciidoc[] + +include::code-standards/naming-conventions.asciidoc[] + +include::code-standards/queries.asciidoc[] + +include::code-standards/serialization/properties.asciidoc[] + +include::common-options/date-math/date-math-expressions.asciidoc[] + +include::common-options/time-unit/time-units.asciidoc[] + +include::document/multiple/bulk/bulk-api.asciidoc[] + +include::query-dsl/bool-dsl/bool-dsl.asciidoc[] + +include::query-dsl/compound/and/and-query-usage.asciidoc[] + +include::query-dsl/geo/distance/distance-units.asciidoc[] diff --git a/src/Tests/index.asciidoc b/docs/asciidoc/intro.asciidoc similarity index 100% rename from src/Tests/index.asciidoc rename to docs/asciidoc/intro.asciidoc diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index 7414bd6a953..f79f8c83c0a 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images/ +:imagesdir: ../../images == Bool Queries @@ -23,11 +23,12 @@ var searchResults = this.Client.Search(s => s ); ---- -Now, imagine multiple nested bools this quickly becomes an exercise in _hadouken indenting_ +Now, imagine multiple nested bools; you'll realise that this quickly becomes an exercise in _hadouken indenting_ [[indent]] .hadouken indenting example image::{imagesdir}/hadouken-indentation.jpg[dead indent] + === Operator Overloading For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc new file mode 100644 index 00000000000..774177daa51 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -0,0 +1,42 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript] +.Example json output +---- +{ + "and": { + "_name": "named_query", + "boost": 1.1, + "filters": [ + { + "match_all": { + "_name": "query1" + } + }, + { + "match_all": { + "_name": "query2" + } + } + ] + } +} +---- + +[source,csharp] +---- +new AndQuery() + { +Name = "named_query", +Boost = 1.1, +Filters = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, +} + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc index f607f320597..e368f74ddf2 100644 --- a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc @@ -1,8 +1,8 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current/ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images/ +:imagesdir: ../../../images == Distance Units diff --git a/libs/AsciiDoc.dll b/libs/AsciiDoc.dll deleted file mode 100644 index 1fc341935180ece7ba66799d7ec8146873563c2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68096 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Ξ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%0D4=;V>Vfk{E4OTfo~ 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 Ids = new Dictionary(); + public AddAttributeEntriesVisitor(FileInfo destination) { _destination = destination; @@ -21,7 +24,7 @@ public override void Visit(Document document) { if (!document.Attributes.Any(a => a.Name == "ref_current")) { - document.Attributes.Add(new AttributeEntry("ref_current", "https://www.elastic.co/guide/en/elasticsearch/reference/current/")); + document.Attributes.Add(new AttributeEntry("ref_current", "https://www.elastic.co/guide/en/elasticsearch/reference/current")); } if (!document.Attributes.Any(a => a.Name == "github")) @@ -33,20 +36,61 @@ public override void Visit(Document document) { var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; var currentDirectory = _destination.Directory.FullName; - var count = 0; + var difference = currentDirectory.Replace(targetDirectory, string.Empty); + var count = difference.Count(c => c == '\\'); + var imagesDir = string.Join(string.Empty, Enumerable.Repeat("../", count)); + + document.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}")); + } + + base.Visit(document); + } + + public override void Visit(Source source) + { + if (source.Attributes.Count > 1 && + source.Attributes[1].Name == "javascript" && + !source.Attributes.HasTitle) + { + source.Attributes.Add(new Title("Example json output")); + } + + base.Visit(source); + } - while (currentDirectory != targetDirectory) + public override void Visit(SectionTitle sectionTitle) + { + if (sectionTitle.Level != 2) + { + return; + } + + // Generate an anchor for all section titles + if (!sectionTitle.Attributes.HasAnchor) + { + var builder = new StringBuilder(); + using (var writer = new AsciiDocVisitor(new StringWriter(builder))) { - currentDirectory = new DirectoryInfo(currentDirectory).Parent?.FullName; - ++count; + writer.Visit(sectionTitle.Elements); } - document.Attributes.Add(new AttributeEntry( - "imagesdir", - $"{string.Join(string.Empty, Enumerable.Repeat("../", count))}{Program.ImagesDir}/")); + var title = builder.ToString().PascalToHyphen(); + sectionTitle.Attributes.Add(new Anchor(title)); } - base.Visit(document); + // check for duplicate ids + var key = sectionTitle.Attributes.Anchor.Id; + string existingFile; + if (Ids.TryGetValue(key, out existingFile)) + { + throw new Exception($"duplicate id {key} in {_destination.FullName}. Id already exists in {existingFile}"); + } + else + { + Ids.Add(key, _destination.FullName); + } + + base.Visit(sectionTitle); } } } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs index 32f8d32a822..34c2beb7362 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs @@ -1,24 +1,44 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; namespace Nest.Litterateur.Documentation.Blocks { public class CodeBlock : IDocumentationBlock { - public string Value { get; } + public CodeBlock(string lineOfCode, int lineNumber, Language language, string propertyName = null) + { + Value = ExtractCallOutsFromText(lineOfCode); + LineNumber = lineNumber; + Language = language; + PropertyName = propertyName; + } + + public List CallOuts { get; } = new List(); + + public Language Language { get; set; } + public int LineNumber { get; } - public string Language { get; set; } + public string PropertyName { get; set; } - public CodeBlock(string lineOfCode, int lineNumber, string language) + public string Value { get; private set; } + + private string ExtractCallOutsFromText(string lineOfCode) { - if (language == null) + var matches = Regex.Matches(lineOfCode, @"//[ \t]*(?\<\d+\>)[ \t]*(?\S.*)"); + foreach (Match match in matches) { - throw new ArgumentNullException(nameof(language)); + CallOuts.Add($"{match.Groups["callout"].Value} {match.Groups["text"].Value}"); } - Value = lineOfCode.Trim(); - LineNumber = lineNumber; - Language = language; + if (CallOuts.Any()) + { + lineOfCode = Regex.Replace(lineOfCode, @"//[ \t]*\<(\d+)\>.*", "//<$1>"); + } + + return lineOfCode.Trim(); } } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index cd7dd7d95eb..db306d4a66c 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -28,12 +28,26 @@ private string RenderBlocksToDocumentation(IEnumerable bloc { var builder = new StringBuilder(); var lastBlockWasCodeBlock = false; - RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock); - if (lastBlockWasCodeBlock) builder.AppendLine("----"); + var callouts = new List(); + Language? language = null; + RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock, ref callouts, ref language); + if (lastBlockWasCodeBlock) + { + builder.AppendLine("----"); + foreach (var callout in callouts) + { + builder.AppendLine(callout); + } + } return builder.ToString(); } - private void RenderBlocksToDocumentation(IEnumerable blocks, StringBuilder builder, ref bool lastBlockWasCodeBlock) + private void RenderBlocksToDocumentation( + IEnumerable blocks, + StringBuilder builder, + ref bool lastBlockWasCodeBlock, + ref List callouts, + ref Language? language) { foreach (var block in blocks) { @@ -43,6 +57,15 @@ private void RenderBlocksToDocumentation(IEnumerable blocks { lastBlockWasCodeBlock = false; builder.AppendLine("----"); + if (callouts.Any()) + { + foreach (var callout in callouts) + { + builder.AppendLine(callout); + } + builder.AppendLine(); + callouts = new List(); + } } builder.AppendLine(block.Value); @@ -51,14 +74,25 @@ private void RenderBlocksToDocumentation(IEnumerable blocks { var codeBlock = (CodeBlock)block; - if (!lastBlockWasCodeBlock) + // don't write different language code blocks in the same delimited source block + if (lastBlockWasCodeBlock && codeBlock.Language != language) { - builder.AppendLine($"[source, {codeBlock.Language}]"); - if (codeBlock.Language == "javascript") + lastBlockWasCodeBlock = false; + builder.AppendLine("----"); + if (callouts.Any()) { - builder.AppendLine(".Example json output"); + foreach (var callout in callouts) + { + builder.AppendLine(callout); + } + builder.AppendLine(); + callouts = new List(); } + } + if (!lastBlockWasCodeBlock) + { + builder.AppendLine($"[source, {codeBlock.Language.ToString().ToLowerInvariant()}]"); builder.AppendLine("----"); } else @@ -66,13 +100,17 @@ private void RenderBlocksToDocumentation(IEnumerable blocks builder.AppendLine(); } - builder.AppendLine(block.Value); + builder.AppendLine(codeBlock.Value); + + // add call outs here to write out when closing the block + callouts.AddRange(codeBlock.CallOuts); lastBlockWasCodeBlock = true; + language = codeBlock.Language; } else if (block is CombinedBlock) { var mergedBlocks = MergeAdjacentCodeBlocks(((CombinedBlock)block).Blocks); - RenderBlocksToDocumentation(mergedBlocks, builder, ref lastBlockWasCodeBlock); + RenderBlocksToDocumentation(mergedBlocks, builder, ref lastBlockWasCodeBlock, ref callouts, ref language); } } } @@ -81,8 +119,9 @@ private List MergeAdjacentCodeBlocks(IEnumerable(); List collapseCodeBlocks = null; + List collapseCallouts = null; int lineNumber = 0; - string language = null; + Language? language = null; foreach (var b in unmergedBlocks) { @@ -90,8 +129,11 @@ private List MergeAdjacentCodeBlocks(IEnumerable MergeAdjacentCodeBlocks(IEnumerable(); - var codeBlock = (CodeBlock)b; + if (collapseCallouts == null) collapseCallouts = new List(); + var codeBlock = (CodeBlock)b; if (language != null && codeBlock.Language != language) { blocks.Add(codeBlock); @@ -113,19 +156,25 @@ private List MergeAdjacentCodeBlocks(IEnumerable b.LineNumber).ToList(); @@ -133,29 +182,49 @@ public override void SaveToDocumentationFolder() var mergedBlocks = MergeAdjacentCodeBlocks(blocks); var body = this.RenderBlocksToDocumentation(mergedBlocks); - var docFileName = this.CreateDocumentationLocation(); + var docFile = this.CreateDocumentationLocation(); + +#if !DOTNETCORE + CleanDocumentAndWriteToFile(body, docFile); +#else + File.WriteAllText(docFile.FullName, body); +#endif + } #if !DOTNETCORE - // tidy up + private void CleanDocumentAndWriteToFile(string body, FileInfo docFile) + { + // tidy up the asciidoc var document = Document.Parse(body); - // get the section numbers + // extract section number from doc var sectionAttributeEntry = document.Attributes.SingleOrDefault(a => a.Name == "section-number"); decimal sectionValue; + + var sectionPath = GetPathRelativeToOutput(docFile); if (sectionAttributeEntry != null && decimal.TryParse(sectionAttributeEntry.Value, out sectionValue)) { - _sections.Add(docFileName.Name, sectionValue); + _sections.Add(sectionPath, sectionValue); + } + else + { + _sections.Add(sectionPath, 1); } // add attributes and write to destination - using (var file = new StreamWriter(docFileName.FullName)) + using (var file = new StreamWriter(docFile.FullName)) { - document.Accept(new AddAttributeEntriesVisitor(docFileName)); + document.Accept(new AddAttributeEntriesVisitor(docFile)); document.Accept(new AsciiDocVisitor(file)); } -#else - File.WriteAllText(docFileName.FullName, body); + } #endif + + private string GetPathRelativeToOutput(FileInfo docFileName) + { + var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; + var currentDirectory = docFileName.FullName; + return currentDirectory.Replace(targetDirectory, string.Empty).Replace("\\", "/").TrimStart('/'); } } } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs index 5dfd76cdb9c..6afad0534b4 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs @@ -44,7 +44,10 @@ protected virtual FileInfo CreateDocumentationLocation() var testFullPath = this.FileLocation.FullName; var testInDocumentationFolder = - Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "").TrimDocExtension().PascalToHyphen() + ".asciidoc"; + Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "") + .TrimEnd(".doc") + .TrimEnd("Tests") + .PascalToHyphen() + ".asciidoc"; var documentationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputDirPath, testInDocumentationFolder)); var fileInfo = new FileInfo(documentationTargetPath); diff --git a/src/CodeGeneration/Nest.Litterateur/Language.cs b/src/CodeGeneration/Nest.Litterateur/Language.cs new file mode 100644 index 00000000000..07dea31177f --- /dev/null +++ b/src/CodeGeneration/Nest.Litterateur/Language.cs @@ -0,0 +1,8 @@ +namespace Nest.Litterateur +{ + public enum Language + { + CSharp, + JavaScript + } +} \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/LitUp.cs b/src/CodeGeneration/Nest.Litterateur/LitUp.cs index 2519149bdfe..a86eb4e1517 100644 --- a/src/CodeGeneration/Nest.Litterateur/LitUp.cs +++ b/src/CodeGeneration/Nest.Litterateur/LitUp.cs @@ -4,13 +4,17 @@ using System.Linq; using Nest.Litterateur.Documentation.Files; +#if !DOTNETCORE +using AsciiDoc; +#endif + namespace Nest.Litterateur { public static class LitUp { private static readonly string[] SkipFolders = { "Nest.Tests.Literate", "Debug", "Release" }; - private static readonly Dictionary Sections = new Dictionary(); + private static readonly Dictionary Sections = new Dictionary(); public static IEnumerable InputFiles(string extension) => from f in Directory.GetFiles(Program.InputDirPath, $"*.{extension}", SearchOption.AllDirectories) @@ -32,8 +36,37 @@ public static IEnumerable> Input public static void Go(string[] args) { - foreach (var file in Input.SelectMany(s=>s)) + foreach (var file in Input.SelectMany(s => s)) + { file.SaveToDocumentationFolder(); + } + +#if !DOTNETCORE + // generate the index.asciidoc file from the sections + var indexDoc = new Document + { + Title = new DocumentTitle("Elasticsearch.Net and NEST documentation", ".NET Elasticsearch clients") + { + Attributes = + { + new Anchor("elasticsearch-net-reference", null), + } + } + }; + + indexDoc.Elements.Add(new Include("intro.asciidoc")); + + // TODO: Only the top level sections should be in the index where each top level section should link to other sections + foreach (var section in Sections.GroupBy(s => s.Key).OrderBy(s => s.Min(kv => kv.Value)).ThenBy(s => s.Key)) + { + indexDoc.Elements.Add(new Include(section.Key)); + } + + using (var visitor = new AsciiDocVisitor(Path.Combine(Program.OutputDirPath, "index.asciidoc"))) + { + indexDoc.Accept(visitor); + } +#endif } } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs index 1c208d4c19d..cf7f17d1285 100644 --- a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs @@ -1,5 +1,13 @@ using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Newtonsoft.Json; namespace Nest.Litterateur { @@ -12,15 +20,15 @@ public static string PascalToHyphen(this string input) return Regex.Replace( Regex.Replace( Regex.Replace(input, @"([A-Z]+)([A-Z][a-z])", "$1-$2"), @"([a-z\d])([A-Z])", "$1-$2") - , @"[-\s]", "-").ToLower(); + , @"[-\s]", "-").TrimEnd('-').ToLower(); } - public static string TrimDocExtension(this string input) + public static string TrimEnd(this string input, string trim) { if (string.IsNullOrEmpty(input)) return string.Empty; - return input.EndsWith(".doc", StringComparison.OrdinalIgnoreCase) - ? input.Substring(0, input.Length - 4) + return input.EndsWith(trim, StringComparison.OrdinalIgnoreCase) + ? input.Substring(0, input.Length - trim.Length) : input; } @@ -55,9 +63,106 @@ public static string RemoveLeadingSpacesAndAsterisk(this string input) return input; } - public static string RemoveNumberOfLeadingTabsAfterNewline(this string input , int numberOfTabs) + public static string RemoveNumberOfLeadingTabsAfterNewline(this string input, int numberOfTabs) { return Regex.Replace(input, $"(?[\n|\r\n]+\t{{{numberOfTabs}}})", m => m.Value.Replace("\t", string.Empty)); } + + public static string[] SplitOnNewLines(this string input, StringSplitOptions options) + { + return input.Split(new[] { "\r\n", "\n" }, options); + } + +#if !DOTNETCORE + // TODO: Hack of replacements for now. Resolved by referencing tests assembly when building compilation unit, but might + // want to put doc generation at same directory level as Tests to reference project directly. + private static Dictionary Substitutions = new Dictionary + { + { "FixedDate", "new DateTime(2015, 06, 06, 12, 01, 02, 123)" }, + { "FirstNameToFind", "\"pierce\"" } + }; + + public static bool TryGetJsonForAnonymousType(this string anonymousTypeString, out string json) + { + json = null; + + foreach (var substitution in Substitutions) + { + anonymousTypeString = anonymousTypeString.Replace(substitution.Key, substitution.Value); + } + + var text = + $@" + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + namespace Temporary + {{ + public class Json + {{ + public string Write() + {{ + var o = {anonymousTypeString}; + var json = JsonConvert.SerializeObject(o, Formatting.Indented); + return json; + }} + }} + }}"; + + var syntaxTree = CSharpSyntaxTree.ParseText(text); + var assemblyName = Path.GetRandomFileName(); + var references = new MetadataReference[] + { + MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(JsonConvert).GetTypeInfo().Assembly.Location), + }; + + var compilation = + CSharpCompilation.Create( + assemblyName, + new[] { syntaxTree }, + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + + using (var ms = new MemoryStream()) + { + var result = compilation.Emit(ms); + + if (!result.Success) + { + var failures = result.Diagnostics.Where(diagnostic => + diagnostic.IsWarningAsError || + diagnostic.Severity == DiagnosticSeverity.Error); + + var builder = new StringBuilder(); + foreach (var diagnostic in failures) + { + builder.AppendLine($"{diagnostic.Id}: {diagnostic.GetMessage()}"); + } + + Console.Error.WriteLine(builder.ToString()); + return false; + } + + ms.Seek(0, SeekOrigin.Begin); + + var assembly = Assembly.Load(ms.ToArray()); + var type = assembly.GetType("Temporary.Json"); + var obj = Activator.CreateInstance(type); + + var output = type.InvokeMember("Write", + BindingFlags.Default | BindingFlags.InvokeMethod, + null, + obj, + new object[] { }); + + json = output.ToString(); + return true; + } + } +#endif } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs index 0904152d512..6d2799cc300 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs @@ -16,21 +16,21 @@ #endif using Microsoft.CodeAnalysis.Text; using Nest.Litterateur.Documentation.Blocks; -using Newtonsoft.Json; namespace Nest.Litterateur.Walkers { class CodeWithDocumentationWalker : CSharpSyntaxWalker { - public List Blocks { get; } = new List(); - - public List TextBlocks { get; } = new List(); - private bool _firstVisit = true; private string _code; + private readonly string _propertyName; public int ClassDepth { get; } + public List Blocks { get; } = new List(); + + public List TextBlocks { get; } = new List(); + private readonly int? _lineNumberOverride; /// @@ -39,10 +39,12 @@ class CodeWithDocumentationWalker : CSharpSyntaxWalker /// /// the depth of the class /// line number used for sorting - public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null) : base(SyntaxWalkerDepth.StructuredTrivia) + /// the name of the property that we are walking + public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null, string propertyName = null) : base(SyntaxWalkerDepth.StructuredTrivia) { ClassDepth = classDepth; _lineNumberOverride = lineNumber; + _propertyName = propertyName; } public override void Visit(SyntaxNode node) @@ -52,22 +54,33 @@ public override void Visit(SyntaxNode node) _firstVisit = false; var repeatedTabs = 2 + ClassDepth; - var language = "csharp"; + var language = Language.CSharp; _code = node.WithoutLeadingTrivia().WithTrailingTrivia().ToFullString(); _code = _code.RemoveNumberOfLeadingTabsAfterNewline(repeatedTabs); #if !DOTNETCORE - // if this is ExpectJson node, get the json for the anonymous type - if (node.Kind() == SyntaxKind.AnonymousObjectCreationExpression) + if (_propertyName == "ExpectJson" || _propertyName == "QueryJson") { - _code = GetJsonForAnonymousType(); - language = "javascript"; + // try to get the json for the anonymous type. + // Only supports system types and Json.Net LINQ objects e.g. JObject + string json; + if (_code.TryGetJsonForAnonymousType(out json)) + { + language = Language.JavaScript; + _code = json; + } } #endif + // TODO: Can do this once we get the generic arguments from the Property declaration + //if (_propertyName == "Fluent") + //{ + // // need to know what type we're operating on + // _code += $"client.Search({_code});"; + //} var nodeLine = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var line = _lineNumberOverride ?? nodeLine; - var codeBlocks = ParseCodeBlocks(_code, line, language); + var codeBlocks = ParseCodeBlocks(_code, line, language, _propertyName); base.Visit(node); @@ -96,7 +109,7 @@ public override void VisitBlock(BlockSyntax node) var nodeLine = formattedStatement.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var line = _lineNumberOverride ?? nodeLine; - var codeBlocks = ParseCodeBlocks(_code, line, "csharp"); + var codeBlocks = ParseCodeBlocks(_code, line, Language.CSharp, _propertyName); this.Blocks.AddRange(codeBlocks); } @@ -115,7 +128,7 @@ public override void VisitTrivia(SyntaxTrivia trivia) var tokens = trivia.ToFullString() .RemoveLeadingAndTrailingMultiLineComments() - .Split(new[] { Environment.NewLine }, StringSplitOptions.None); + .SplitOnNewLines(StringSplitOptions.None); var builder = new StringBuilder(); foreach (var token in tokens) @@ -133,87 +146,13 @@ public override void VisitTrivia(SyntaxTrivia trivia) this.Blocks.Add(new TextBlock(text, line)); } - private List ParseCodeBlocks(string code, int line, string language) + private List ParseCodeBlocks(string code, int line, Language language, string propertyName) { return Regex.Split(code, @"\/\*\*.*?\*\/", RegexOptions.Singleline) .Select(b => b.TrimStart('\r', '\n').TrimEnd('\r', '\n', '\t')) .Where(b => !string.IsNullOrEmpty(b) && b != ";") - .Select(b => new CodeBlock(b, line, language)) + .Select(b => new CodeBlock(b, line, language, propertyName)) .ToList(); } - -#if !DOTNETCORE - private string GetJsonForAnonymousType() - { - var text = - $@" - using System; - using Newtonsoft.Json; - - namespace Temporary - {{ - public class Json - {{ - public string Write() - {{ - var o = " + - _code + $@"; - var json = JsonConvert.SerializeObject(o, Formatting.Indented); - return json; - }} - }} - }}"; - - var syntaxTree = CSharpSyntaxTree.ParseText(text); - string assemblyName = Path.GetRandomFileName(); - - var references = new MetadataReference[] - { - MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), - MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location), - MetadataReference.CreateFromFile(typeof(JsonConvert).GetTypeInfo().Assembly.Location), - }; - - CSharpCompilation compilation = - CSharpCompilation.Create( - assemblyName, - new[] { syntaxTree }, - references, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - - using (var ms = new MemoryStream()) - { - var result = compilation.Emit(ms); - - if (!result.Success) - { - var failures = result.Diagnostics.Where(diagnostic => - diagnostic.IsWarningAsError || - diagnostic.Severity == DiagnosticSeverity.Error); - - var builder = new StringBuilder(); - foreach (var diagnostic in failures) - { - builder.AppendLine($"{diagnostic.Id}: {diagnostic.GetMessage()}"); - } - - throw new Exception(builder.ToString()); - } - - ms.Seek(0, SeekOrigin.Begin); - Assembly assembly = Assembly.Load(ms.ToArray()); - - Type type = assembly.GetType("Temporary.Json"); - object obj = Activator.CreateInstance(type); - var output = type.InvokeMember("Write", - BindingFlags.Default | BindingFlags.InvokeMethod, - null, - obj, - new object[] { }); - - return output.ToString(); - } - } -#endif } } diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index 72fc9bb2382..f924eb79294 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -1,13 +1,10 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Nest.Litterateur.Documentation; using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Text.RegularExpressions; -using Microsoft.CodeAnalysis.Text; using Nest.Litterateur.Documentation.Blocks; namespace Nest.Litterateur.Walkers @@ -16,6 +13,7 @@ class DocumentationFileWalker : CSharpSyntaxWalker { public DocumentationFileWalker() : base(SyntaxWalkerDepth.StructuredTrivia) { } + private string _propertyName; private int ClassDepth { get; set; } private bool InsideMultiLineDocumentation { get; set; } private bool InsideAutoIncludeMethodBlock { get; set; } @@ -55,23 +53,34 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { var propertyName = node.Identifier.Text; - if (propertyName == "ExpectJson") + if (propertyName == "ExpectJson" || propertyName == "QueryJson") { + _propertyName = propertyName; this.InsideFluentOrInitializerExample = true; base.VisitPropertyDeclaration(node); this.InsideFluentOrInitializerExample = false; } - else if (propertyName == "Fluent") + else if (propertyName == "Fluent" || + propertyName == "Initializer" || + propertyName == "QueryFluent" || + propertyName == "QueryInitializer") { + // TODO: Look to get the generic types for the call so that we can prettify the fluent and OIS calls in docs e.g. client.Search({Call}); + // var genericArguments = node.DescendantNodes().OfType().FirstOrDefault(); + // List arguments = new List(); + // if (genericArguments != null) + // { + // arguments.AddRange(genericArguments.TypeArgumentList.Arguments); + // } + + _propertyName = propertyName; this.InsideFluentOrInitializerExample = true; base.VisitPropertyDeclaration(node); this.InsideFluentOrInitializerExample = false; } - else if (propertyName == "Initializer") + else { - this.InsideFluentOrInitializerExample = true; - base.VisitPropertyDeclaration(node); - this.InsideFluentOrInitializerExample = false; + _propertyName = null; } } @@ -81,7 +90,7 @@ public override void VisitArrowExpressionClause(ArrowExpressionClauseSyntax node var syntaxNode = node?.ChildNodes()?.LastOrDefault()?.WithAdditionalAnnotations(); if (syntaxNode == null) return; var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var walker = new CodeWithDocumentationWalker(ClassDepth, line); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); walker.Visit(syntaxNode); this.Blocks.AddRange(walker.Blocks); } @@ -92,7 +101,7 @@ public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) var syntaxNode = node?.ChildNodes()?.LastOrDefault()?.WithAdditionalAnnotations() as BlockSyntax; if (syntaxNode == null) return; var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var walker = new CodeWithDocumentationWalker(ClassDepth, line); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); walker.VisitBlock(syntaxNode); this.Blocks.AddRange(walker.Blocks); } @@ -112,7 +121,7 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) var allchildren = node.DescendantNodesAndTokens(descendIntoTrivia: true); if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) { - var walker = new CodeWithDocumentationWalker(ClassDepth, line); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); walker.Visit(node.WithAdditionalAnnotations()); this.Blocks.AddRange(walker.Blocks); return; @@ -120,7 +129,7 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) base.VisitExpressionStatement(node); var code = node.WithoutLeadingTrivia().ToFullString(); code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); - this.Blocks.Add(new CodeBlock(code, line, "csharp")); + this.Blocks.Add(new CodeBlock(code, line, Language.CSharp)); } else base.VisitExpressionStatement(node); @@ -134,14 +143,14 @@ public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyn var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) { - var walker = new CodeWithDocumentationWalker(ClassDepth, line); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); walker.Visit(node.WithAdditionalAnnotations()); this.Blocks.AddRange(walker.Blocks); return; } var code = node.WithoutLeadingTrivia().ToFullString(); code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); - this.Blocks.Add(new CodeBlock(code, line, "csharp")); + this.Blocks.Add(new CodeBlock(code, line, Language.CSharp)); } base.VisitLocalDeclarationStatement(node); } @@ -158,7 +167,7 @@ public override void VisitTrivia(SyntaxTrivia trivia) var tokens = trivia.ToFullString() .RemoveLeadingAndTrailingMultiLineComments() - .Split(new [] { Environment.NewLine }, StringSplitOptions.None); + .SplitOnNewLines(StringSplitOptions.None); var builder = new StringBuilder(); foreach (var token in tokens) diff --git a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs index c17558c70db..7aee813a2a8 100644 --- a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs +++ b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs @@ -3,6 +3,8 @@ namespace Tests.Aggregations.Bucket.Children { + /** == Child Aggregation Mapping + */ public class ChildrenAggregationMapping { private void MappingExample() @@ -12,9 +14,9 @@ private void MappingExample() * index with two mapped types, `project` and `commitactivity` and * we add a `_parent` mapping from `commitactivity` to `parent` */ var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c - .Mappings(map=>map - .Map(m=>m.AutoMap()) - .Map(m=>m + .Mappings(map => map + .Map(tm => tm.AutoMap()) + .Map(tm => tm .Parent() ) ) diff --git a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.doc.cs similarity index 86% rename from src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.doc.cs index 29dc4b93ef0..b36b58d7f70 100644 --- a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.doc.cs @@ -6,13 +6,12 @@ namespace Tests.Aggregations.Bucket.Children { - /** + /** == Children Aggregation * A special single bucket aggregation that enables aggregating from buckets on parent document types to * buckets on child documents. * - * Be sure to read the elasticsearch documentation {ref}/search-aggregations-bucket-children-aggregation.html[on this subject here] + * Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] */ - public class ChildrenAggregationUsageTests : AggregationUsageTestBase { public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -39,6 +38,7 @@ public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : b } }; + /** Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Children("name_of_child_agg", child => child @@ -49,6 +49,7 @@ public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : b ) ); + /** Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -61,10 +62,7 @@ public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : b }; } - - // TODO : move this to a general documentation test explaining how to - // combine aggregations using boolean operators? - + // TODO: This looks to be a duplicate of what is in the writing aggregations documentation public class ChildrenAggregationDslUsage : ChildrenAggregationUsageTests { public ChildrenAggregationDslUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } diff --git a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.doc.cs similarity index 88% rename from src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.doc.cs index 21f8a2d578c..0d2928a298d 100644 --- a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.doc.cs @@ -8,7 +8,7 @@ namespace Tests.Aggregations.Bucket.DateHistogram { - /** + /** == Date Histogram Aggregation * A multi-bucket aggregation similar to the histogram except it can only be applied on date values. * From a functionality perspective, this histogram supports the same features as the normal histogram. * The main difference is that the interval can be specified by date/time expressions. @@ -17,7 +17,7 @@ namespace Tests.Aggregations.Bucket.DateHistogram * the serialized DateTimes of extended_bounds correctly, the date_optional_time format is included * as part of the format value. * - * Be sure to read the elasticsearch documentation {ref}/search-aggregations-bucket-datehistogram-aggregation.html[on this subject here] + * Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. */ public class DateHistogramAggregationUsageTests : AggregationUsageTestBase { @@ -65,6 +65,7 @@ public DateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage } }; + /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Size(0) .Aggregations(aggs => aggs @@ -87,6 +88,7 @@ public DateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage ) ); + /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -117,12 +119,12 @@ public DateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage protected override void ExpectResponse(ISearchResponse response) { + /** === Handling responses + * Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily + * in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] + */ response.IsValid.Should().BeTrue(); - /** - * Using the `.Agg` aggregation helper we can fetch our aggregation results easily - * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() - */ var dateHistogram = response.Aggs.DateHistogram("projects_started_per_month"); dateHistogram.Should().NotBeNull(); dateHistogram.Buckets.Should().NotBeNull(); diff --git a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.doc.cs similarity index 68% rename from src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.doc.cs index ea3ad958bae..c48414bb192 100644 --- a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.doc.cs @@ -8,12 +8,15 @@ namespace Tests.Aggregations.Bucket.DateRange { - /** + /** :sectiontitle: Date Range Aggregation + * == {sectiontitle} * A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` - * and `to` values can be expressed in Date Math expressions, and it is also possible to specify a date format by which the from and to response fields will be returned. - * Note that this aggregation includes the from value and excludes the to value for each range. + * and `to` values can be expressed in `DateMath` expressions, and it is also possible to specify a date format by which the from and + * to response fields will be returned. * - * Be sure to read the elasticsearch documentation {ref}/search-aggregations-bucket-daterange-aggregation.html[on this subject here] + * IMPORTANT: this aggregation includes the `from` value and excludes the `to` value for each range. + * + * Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] */ public class DateRangeAggregationUsageTests : AggregationUsageTestBase { @@ -30,9 +33,9 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : field = "startedOn", ranges = new object[] { - new { to = "now", from = "2015-06-06T12:01:02.123||+2d" }, - new { to = "now+1d-30m/h" }, - new { from = "2012-05-05||+1d-1m" }, + new { to = "now", from = "2015-06-06T12:01:02.123||+2d" }, + new { to = "now+1d-30m/h" }, + new { from = "2012-05-05||+1d-1m" }, } }, aggs = new @@ -43,6 +46,7 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : } }; + /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .DateRange("projects_date_ranges", date => date @@ -58,6 +62,7 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ) ); + /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -66,9 +71,9 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : Field = Field(p => p.StartedOn), Ranges = new List { - {new DateRangeExpression { From = DateMath.Anchored(FixedDate).Add("2d"), To = DateMath.Now} }, - {new DateRangeExpression { To = DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour) } }, - {new DateRangeExpression { From = DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m") } } + new DateRangeExpression { From = DateMath.Anchored(FixedDate).Add("2d"), To = DateMath.Now}, + new DateRangeExpression { To = DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour) }, + new DateRangeExpression { From = DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m") } }, Aggregations = new TermsAggregation("project_tags") { Field = Field(p => p.Tags) } @@ -77,17 +82,17 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : protected override void ExpectResponse(ISearchResponse response) { - response.IsValid.Should().BeTrue(); - - /** + /** === Handling Responses * Using the `.Agg` aggregation helper we can fetch our aggregation results easily * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() */ + response.IsValid.Should().BeTrue(); + var dateHistogram = response.Aggs.DateRange("projects_date_ranges"); dateHistogram.Should().NotBeNull(); dateHistogram.Buckets.Should().NotBeNull(); - /** We specified three ranges so we expect to three of them in the response */ + /** We specified three ranges so we expect to have three of them in the response */ dateHistogram.Buckets.Count.Should().Be(3); foreach (var item in dateHistogram.Buckets) { diff --git a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.doc.cs similarity index 84% rename from src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.doc.cs index 8f9a3fdf19d..a306e685c14 100644 --- a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.doc.cs @@ -9,13 +9,13 @@ namespace Tests.Aggregations.Bucket.Filter { - /** + /** + * == Filter Aggregation * Defines a single bucket of all the documents in the current document set context that match a specified filter. * Often this will be used to narrow down the current aggregation context to a specific set of documents. * - * Be sure to read the elasticsearch documentation {ref}/search-aggregations-bucket-filter-aggregation.html[on this subject here] + * Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] */ - public class FilterAggregationUsageTests : AggregationUsageTestBase { public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) @@ -45,6 +45,7 @@ public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : bas } }; + /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filter("bethels_projects", date => date @@ -55,6 +56,7 @@ public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : bas ) ); + /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -68,12 +70,12 @@ public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : bas protected override void ExpectResponse(ISearchResponse response) { - response.IsValid.Should().BeTrue(); - - /** - * Using the `.Agg` aggregation helper we can fetch our aggregation results easily + /** === Handling Responses + * Using the `.Aggs` aggregation helper we can fetch our aggregation results easily * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() */ + response.IsValid.Should().BeTrue(); + var filterAgg = response.Aggs.Filter("bethels_projects"); filterAgg.Should().NotBeNull(); filterAgg.DocCount.Should().BeGreaterThan(0); @@ -82,7 +84,11 @@ protected override void ExpectResponse(ISearchResponse response) tags.Buckets.Should().NotBeEmpty(); } } - + + /** == Empty Filter + * When the collection of filters is empty or all are conditionless, NEST will serialize them + * to an empty object. + */ public class EmptyFilterAggregationUsageTests : AggregationUsageTestBase { public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) @@ -100,6 +106,7 @@ public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) } }; + /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filter("empty_filter", date => date @@ -111,6 +118,7 @@ public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) ) ); + /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -123,6 +131,7 @@ public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) } }; + /** === Handling Response */ protected override void ExpectResponse(ISearchResponse response) { response.IsValid.Should().BeTrue(); diff --git a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs similarity index 95% rename from src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs index 2582a4acaa4..2cf614b95bc 100644 --- a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs @@ -9,12 +9,12 @@ namespace Tests.Aggregations.Bucket.Filters { - /** + /** == Filters Aggregation * Defines a multi bucket aggregations where each bucket is associated with a filter. * Each bucket will collect all documents that match its associated filter. For documents * that do not match any filter, these will be collected in the other bucket. * - * Be sure to read the elasticsearch documentation {ref}/search-aggregations-bucket-filters-aggregation.html[on this subject here] + * Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-filters-aggregation.html[on this subject here] */ /** == Named filters **/ @@ -47,6 +47,7 @@ public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba } }; + /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filters("projects_by_state", agg => agg @@ -63,6 +64,7 @@ public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba ) ); + /** Object Initializer Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -83,12 +85,12 @@ public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba protected override void ExpectResponse(ISearchResponse response) { - response.IsValid.Should().BeTrue(); - - /** + /** === Handling Responses * Using the `.Agg` aggregation helper we can fetch our aggregation results easily * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() */ + response.IsValid.Should().BeTrue(); + var filterAgg = response.Aggs.Filters("projects_by_state"); filterAgg.Should().NotBeNull(); @@ -111,7 +113,6 @@ protected override void ExpectResponse(ISearchResponse response) } /** == Anonymous filters **/ - public class AnonymousUsage : AggregationUsageTestBase { public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -139,6 +140,7 @@ public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } }; + /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filters("projects_by_state", agg => agg @@ -154,6 +156,7 @@ public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { ) ); + /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -173,12 +176,12 @@ public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { protected override void ExpectResponse(ISearchResponse response) { - response.IsValid.Should().BeTrue(); - /** * Using the `.Agg` aggregation helper we can fetch our aggregation results easily * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() */ + response.IsValid.Should().BeTrue(); + var filterAgg = response.Aggs.Filters("projects_by_state"); filterAgg.Should().NotBeNull(); var results = filterAgg.AnonymousBuckets(); @@ -193,6 +196,7 @@ protected override void ExpectResponse(ISearchResponse response) } } + /** == Empty Filters */ public class EmptyFiltersAggregationUsageTests : AggregationUsageTestBase { public EmptyFiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -234,6 +238,7 @@ protected override void ExpectResponse(ISearchResponse response) } } + /** == Conditionless Filters */ public class ConditionlessFiltersAggregationUsageTests : AggregationUsageTestBase { public ConditionlessFiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } diff --git a/src/Tests/Aggregations/WritingAggregations.doc.cs b/src/Tests/Aggregations/WritingAggregations.doc.cs index b6790869f69..045966b62db 100644 --- a/src/Tests/Aggregations/WritingAggregations.doc.cs +++ b/src/Tests/Aggregations/WritingAggregations.doc.cs @@ -23,7 +23,6 @@ namespace Tests.Aggregations public class Usage : UsageTestBase, SearchRequest> { /** - * * This is the json output for each example **/ protected override object ExpectJson => new @@ -121,7 +120,7 @@ protected override Func, ISearchRequest> Fluent { get { - var aggregations = new List, IAggregationContainer>> + var aggregations = new List, IAggregationContainer>> //<1> a list of aggregation functions to apply { a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) @@ -131,7 +130,7 @@ protected override Func, ISearchRequest> Fluent .Aggregations(aggs => aggs .Children("name_of_child_agg", child => child .Aggregations(childAggs => - aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) + aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) // <2> Using LINQ's `Aggregate()` function to accumulate/apply all of the aggregation functions ) ) ); diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs index b65850ad8ea..31fd3a66960 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs @@ -8,12 +8,11 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class DateTimeProviders { - /** == Date time providers * * Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` - * in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and clusterfailover - * in run time not being bound to wall clock time. + * in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover + * without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. */ [U] public void DefaultNowBehaviour() { @@ -31,8 +30,8 @@ [U] public void DeadTimeoutCalculation() { var dateTimeProvider = DateTimeProvider.Default; /** - * The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)` - * The default values for `timeout` and `maxTimeout` are + * The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the + * default values for `timeout` and `maxTimeout` are */ var timeout = TimeSpan.FromMinutes(1); var maxTimeout = TimeSpan.FromMinutes(30); diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs index 49c64481fe7..38bba015513 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs @@ -14,6 +14,9 @@ public class KeepingTrackOfNodes [U] public void Creating() { + /** === Creating a Node + * A `Node` can be instantiated by passing it a `Uri` + */ var node = new Node(new Uri("http://localhost:9200")); node.Uri.Should().NotBeNull(); node.Uri.Port.Should().Be(9200); @@ -21,18 +24,25 @@ [U] public void Creating() /** By default master eligible and holds data is presumed to be true **/ node.MasterEligible.Should().BeTrue(); node.HoldsData.Should().BeTrue(); + /** Is resurrected is true on first usage, hints to the transport that a ping might be useful */ node.IsResurrected.Should().BeTrue(); - /** When instantiating your connection pool you could switch these to false to initialize the client to + /** + * When instantiating your connection pool you could switch these to false to initialize the client to * a known cluster topology. */ } [U] public void BuildingPaths() { - /** passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy */ + /** === Building a Node path + * passing a node with a path should be preserved. + * Sometimes an elasticsearch node lives behind a proxy + */ var node = new Node(new Uri("http://test.example/elasticsearch")); + node.Uri.Port.Should().Be(80); node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); + /** We force paths to end with a forward slash so that they can later be safely combined */ var combinedPath = new Uri(node.Uri, "index/type/_search"); combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); @@ -42,6 +52,7 @@ [U] public void BuildingPaths() combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); } + /** === Marking Nodes */ [U] public void MarkNodes() { var node = new Node(new Uri("http://localhost:9200")); @@ -59,7 +70,7 @@ [U] public void MarkNodes() node.IsAlive.Should().BeFalse(); node.DeadUntil.Should().Be(deadUntil); } - /** however when marking a node alive deaduntil should be reset and attempts reset to 0*/ + /** however when marking a node alive, the `DeadUntil` property should be reset and `FailedAttempts` reset to 0*/ node.MarkAlive(); node.FailedAttempts.Should().Be(0); node.DeadUntil.Should().Be(default(DateTime)); @@ -68,15 +79,20 @@ [U] public void MarkNodes() [U] public void Equality() { - /** Nodes are considered equal if they have the same endpoint no matter what other metadata is associated */ + /** === Node Equality + * Nodes are considered equal if they have the same endpoint, no matter what other metadata is associated */ var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; var nodeAsMaster = new Node(new Uri("http://localhost:9200")) { MasterEligible = true }; + (node == nodeAsMaster).Should().BeTrue(); (node != nodeAsMaster).Should().BeFalse(); + var uri = new Uri("http://localhost:9200"); (node == uri).Should().BeTrue(); + var differentUri = new Uri("http://localhost:9201"); (node != differentUri).Should().BeTrue(); + node.Should().Be(nodeAsMaster); } } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs index 10ea5b93474..71d4ef46bc8 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs @@ -7,15 +7,13 @@ using Tests.Framework; namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks -{ - public class RequestPipelines - { - /** == Request pipeline - * - * Every request is executed in the context of a `RequestPipeline` when using the - * default `ITransport` implementation. - */ - +{ + /** == Request Pipeline + * Every request is executed in the context of a `RequestPipeline` when using the + * default `ITransport` implementation. + */ + public class RequestPipelines + { [U] public void RequestPipeline() { @@ -25,16 +23,23 @@ public void RequestPipeline() var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); pipeline.GetType().Should().Implement(); - /** However the transport does not instantiate RequestPipeline directly, it uses a pluggable `IRequestPipelineFactory`*/ + /** However the transport does not instantiate `RequestPipeline` directly; it uses a pluggable `IRequestPipelineFactory` + * to create it + */ var requestPipelineFactory = new RequestPipelineFactory(); - var requestPipeline = requestPipelineFactory.Create(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); + var requestPipeline = requestPipelineFactory.Create( + settings, + DateTimeProvider.Default, //<1> An <> + new MemoryStreamFactory(), + new SearchRequestParameters()); + requestPipeline.Should().BeOfType(); requestPipeline.GetType().Should().Implement(); - /** which can be passed to the transport when instantiating a client */ + /** you can pass your own `IRequestPipeline` implementation to the transport when instantiating a client + * allowing you to have requests executed on your own custom request pipeline + */ var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); - - /** this allows you to have requests executed on your own custom request pipeline */ } private IRequestPipeline CreatePipeline( @@ -111,8 +116,8 @@ public void SniffsOnStaleCluster() } - /** A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout - * See the maxretry documentation for more details, here we assert that our request pipeline exposes this propertly + /** A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout. + * See the <> for more details, here we assert that our request pipeline exposes this propertly */ [U] public void IsTakingTooLong() diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs index 27907f1d0b7..d4064216c7f 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs @@ -10,16 +10,17 @@ public class Transports { /** == Transports * - * The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple. - * It's ultimately responsible from translating a client call to a response. If for some reason you do not agree with the way we wrote - * the internals of the client, by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. + * The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple and + * it's ultimately responsible from translating a client call to a response. + * + * If for some reason you do not agree with the way we wrote the internals of the client, + * by implementing a custom `ITransport`, you can circumvent all of it and introduce your own. */ - public async Task InterfaceExplained() { /** - * Transport is generically typed to a type that implements IConnectionConfigurationValues - * This is the minimum ITransport needs to report back for the client to function. + * Transport is generically typed to a type that implements `IConnectionConfigurationValues` + * This is the minimum `ITransport` needs to report back for the client to function. * * e.g in the low level client, transport is instantiated like this: */ @@ -34,7 +35,7 @@ public async Task InterfaceExplained() /** * The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the default `ITransport` implementation is responsible for introducing * many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. - * If you feel this need, please let us know as we'd love to learn why you've go down this route! + * If you feel this need, {github}/issues[please let us know] as we'd love to learn why you've go down this route! */ var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.cs index 7778b57aac1..f4876344ccb 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Exceptions/UnrecoverableExceptions.doc.cs @@ -11,21 +11,25 @@ namespace Tests.ClientConcepts.ConnectionPooling.Exceptions public class UnrecoverableExceptions { /** == Unrecoverable exceptions - * Unrecoverable exceptions are excepted exceptions that are grounds to exit the client pipeline immediately. - * By default the client won't throw on any ElasticsearchClientException but return an invalid response. - * You can configure the client to throw using ThrowExceptions() on ConnectionSettings. The following test + * Unrecoverable exceptions are _excepted_ exceptions that are grounds to exit the client pipeline immediately. + * By default, the client won't throw on any `ElasticsearchClientException` but instead return an invalid response which + * can be detected by checking `.IsValid` on the response + * You can configure the client to throw using `ThrowExceptions()` on `ConnectionSettings`. The following test * both a client that throws and one that returns an invalid response with an `.OriginalException` exposed */ [U] public void SomePipelineFailuresAreRecoverable() { + /** The following are recoverable exceptions */ var recoverablExceptions = new[] { new PipelineException(PipelineFailure.BadResponse), new PipelineException(PipelineFailure.PingFailure), }; + recoverablExceptions.Should().OnlyContain(e => e.Recoverable); + /** and the unrecoverable exceptions */ var unrecoverableExceptions = new[] { new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), @@ -35,9 +39,13 @@ [U] public void SomePipelineFailuresAreRecoverable() new PipelineException(PipelineFailure.MaxRetriesReached), new PipelineException(PipelineFailure.MaxTimeoutReached) }; + unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); } + /** As an example, let's set up a 10 node cluster that will always succeed when pinged but + will fail with a 401 response when making client calls + */ [U] public async Task BadAuthenticationIsUnrecoverable() { var audit = new Auditor(() => Framework.Cluster @@ -48,6 +56,9 @@ [U] public async Task BadAuthenticationIsUnrecoverable() .AllDefaults() ); + /** Here we make a client call and determine that the first audit event was a successful ping, + * followed by a bad response as a result of a bad authentication response + */ audit = await audit.TraceElasticsearchException( new ClientCall { { AuditEvent.PingSuccess, 9200 }, diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs index f4cab6e9b1d..575d6d24ed1 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs @@ -28,7 +28,7 @@ [U] public async Task DisableSniff() audit = await audit.TraceCalls( /** - * We disable sniffing so eventhoug its our first call we do not want to sniff on startup + * We disable sniffing so even though its our first call, we do not want to sniff on startup */ new ClientCall(r=>r.DisableSniffing()) { { PingSuccess, 9200 }, diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index 89dc690f749..9ece5afdb8d 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -8,14 +8,14 @@ namespace Tests.ClientConcepts.HighLevel.Mapping { - /** == Auto mapping properties - * - * When creating a mapping (either when creating an index or via the put mapping API), - * NEST offers a feature called AutoMap(), which will automagically infer the correct - * Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if - * you're using attributes to map your properties, then calling AutoMap() is required - * in order for your attributes to be applied. We'll look at examples of both. - * + /**== Auto mapping properties + * + * When creating a mapping (either when creating an index or via the put mapping API), + * NEST offers a feature called AutoMap(), which will automagically infer the correct + * Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if + * you're using attributes to map your properties, then calling AutoMap() is required + * in order for your attributes to be applied. We'll look at examples of both. + * **/ public class AutoMap { @@ -830,11 +830,11 @@ public void UsingACustomPropertyVisitor() /** Now we can pass an instance of our custom visitor to `.AutoMap()` */ var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms - .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) + .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) //<1> Pass your `IPropertyVisitor` implementation to `.AutoMap` ); /** and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) - * it will apply the transformation defined in each Visit() respectively, which in this example + * it will apply the transformation defined in each `Visit()` respectively, which in this example * disables {ref_current}/doc-values.html[doc values]. */ var expected = new @@ -884,7 +884,8 @@ public void UsingACustomPropertyVisitor() */ public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { - public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); + public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => + new StringProperty(); } [U] diff --git a/src/Tests/CodeStandards/NamingConventions.doc.cs b/src/Tests/CodeStandards/NamingConventions.doc.cs index a58ec15e024..a4a145f33e3 100644 --- a/src/Tests/CodeStandards/NamingConventions.doc.cs +++ b/src/Tests/CodeStandards/NamingConventions.doc.cs @@ -7,13 +7,13 @@ namespace Tests.CodeStandards { - /** # Naming Conventions + /** == Naming Conventions * * NEST uses the following naming conventions (with _some_ exceptions). */ public class NamingConventions { - /** ## Class Names + /** === Class Names * * Abstract class names should end with a `Base` suffix */ @@ -50,7 +50,7 @@ [U] public void ClassNameContainsBaseShouldBeAbstract() baseClassesNotAbstract.Should().BeEmpty(); } - /** ## Requests and Responses + /** === Requests and Responses * * Request class names should end with `Request` */ @@ -88,13 +88,12 @@ public void ResponseClassNamesEndWithResponse() * Request and Response class names should be one to one in *most* cases. * e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => `ValidateResponse` * There are a few exceptions to this rule, most notably the `Cat` prefixed requests and - * `Exists` requests. + * the `Exists` requests. */ [U] public void ParityBetweenRequestsAndResponses() { - // Add any exceptions to the rule here. - var exceptions = new[] + var exceptions = new[] // <1> _Exceptions to the rule_ { typeof(CatAliasesRequest), typeof(CatAllocationRequest), diff --git a/src/Tests/CodeStandards/Serialization/Properties.doc.cs b/src/Tests/CodeStandards/Serialization/Properties.doc.cs index 5e27213f989..23049da6abd 100644 --- a/src/Tests/CodeStandards/Serialization/Properties.doc.cs +++ b/src/Tests/CodeStandards/Serialization/Properties.doc.cs @@ -8,7 +8,6 @@ namespace Tests.CodeStandards.Serialization { public class JsonProperties { - /** * Our Json.NET contract resolver picks up attributes set on the interface */ @@ -27,8 +26,6 @@ public void SeesInterfaceProperties() serialized = c.Serializer.SerializeToString(new AnalysisDescriptor().CharFilters(cf=>cf)); serialized.Should().NotContain("char_filters").And.NotContain("charFilters"); serialized.Should().Contain("char_filter"); - - } } } diff --git a/src/Tests/Document/Multiple/Bulk/BulkApiTests.cs b/src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs similarity index 100% rename from src/Tests/Document/Multiple/Bulk/BulkApiTests.cs rename to src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs diff --git a/src/Tests/Document/Single/Update/UpdateApiTests.cs b/src/Tests/Document/Single/Update/UpdateApiTests.cs index cbcf8909490..fc71b21b602 100644 --- a/src/Tests/Document/Single/Update/UpdateApiTests.cs +++ b/src/Tests/Document/Single/Update/UpdateApiTests.cs @@ -43,7 +43,7 @@ protected override LazyResponses ClientUsage() => Calls( protected override UpdateDescriptor NewDescriptor() => new UpdateDescriptor(DocumentPath.Id(CallIsolatedValue)); - protected override Func, IUpdateRequest> Fluent => d => d + protected override Func, IUpdateRequest> Fluent => u => u .Doc(Project.Instance) .DocAsUpsert() .DetectNoop(); diff --git a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs index 1cf58940b65..5384b333457 100644 --- a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs +++ b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs @@ -31,7 +31,7 @@ public void VerboseWay() ) ); } - /**Now, imagine multiple nested bools this quickly becomes an exercise in _hadouken indenting_ + /**Now, imagine multiple nested bools; you'll realise that this quickly becomes an exercise in _hadouken indenting_ * *[[indent]] *.hadouken indenting example diff --git a/src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.cs b/src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.doc.cs similarity index 100% rename from src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.cs rename to src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.doc.cs diff --git a/src/Tests/intro.asciidoc b/src/Tests/intro.asciidoc new file mode 100644 index 00000000000..897e079d6ba --- /dev/null +++ b/src/Tests/intro.asciidoc @@ -0,0 +1,57 @@ +:github: https://github.com/elastic/elasticsearch-net +:stackoverflow: http://stackoverflow.com + +== Introduction + +You've reached the documentation page for `Elasticsearch.Net` and `NEST`. The two official .NET clients for Elasticsearch. So why two clients I hear you say? + +`Elasticsearch.Net` is a very low level, dependency free, client that has no opinions about how you build and represent your requests and responses. It has abstracted +enough so that **all** the Elasticsearch API endpoints are represented as methods but not too much to get in the way of how you want to build your json/request/response objects. It also comes with builtin, configurable/overridable, cluster failover retry mechanisms. Elasticsearch is elastic so why not your client? + +`NEST` is a high level client that has the advantage of having mapped all the request and response objects, comes with a strongly typed query DSL that maps 1 to 1 with the Elasticsearch query DSL, and takes advantage of specific .NET features such as covariant results. NEST internally uses, and still exposes, the low level `Elasticsearch.Net` client. + +Please read the getting started guide for both. + +=== Who's using Nest +* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). +* http://www.7digital.com[7digital.com] (run NEST on mono). +* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). +* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. + They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] + +=== Other resources + +http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a great http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] +using NEST. + +Also checkout the https://searchbox.io/[searchbox.io guys] rocking NEST http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] +with their https://github.com/searchbox-io/.net-sample[demo project] + +=== Questions, bugs, comments, requests + +All of these are more then welcome on the {github}/issues[github issues pages]! We try to to at least reply within the same day. + +We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow] + +=== License + +.... +This software is licensed under the Apache 2 license, quoted below. + + Copyright (c) 2014 Elasticsearch + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +.... + + diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index 1fc341935180ece7ba66799d7ec8146873563c2c..778f15fe53a18977a330325e9491659e16f2a9eb 100644 GIT binary patch literal 69120 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 D{@1ou literal 68096 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 yhS>VAFll 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 PYT!r>9I1i-+coen1w|l| literal 235008 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Ξ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%0D4=;V>Vfk{E4OTfo~ zCxSIkT?Up7T@KFeRW%RuP-et2>$ucQve@+q#aey#ZY9(OX|RWaXG z$CtAq*{9#P&OMV6+UGUU%ciD*6-yhzik(g1!@(`!GM+B(4EQ}Xu3pfqH#t|HisF6f zl-rZ$5YYyozpH~iDX{G0Ca~yk21~{*VCm&Ha0U2-V8yRHz#5}F!E?ZK z!Jh!%1zrN42WHPB`Z#zkcs}?A@IBzo;053mZTS?KXVfF!S&%sb{8=!$fAo3q1n?KY zt?fzq)Cq3f{N7unyP+ zl%0UD0|S9kz$Bmrm;)>XmH}&k4Zs$l>mYJpU@$Nas0L;M^MJ*`3gB5_BS1PB^#J+< z6~IKG9+(X*0G0x)fc3y8pvy^&Eif1u15^VufqB3pUvZrRsrjPO+eXT`UwmKMgfz67GMsr5LgDR0X6_zfUZn%y@A2NIG`Gs1e#=e~T ztTuSvC)X?5qln|CAFu1==f?Jib`R?70ao6uIdL=JHP#Duwrx_ z*CDh8r~oDcEx=r0F|ZO?2W)S7FaKYGEv>q=wO^LX|3jPoE^^kGoFZ&i?UYa1nD{p5 z#!qgdaaAFYakhv3k#FYK8?ss7hUBr7t!ga0g7e361IJa=r%jAY8HVL zm;Q3}iX(Q}>Cvw(o2=twqY*>~bb@mV(4W>AZoEwP77rvLWdvIlLiY}VkegtAXVcG>0csdF-@;`%KgkuUgh&FxdFDHc0_*h%ZnVcB@- z$03>a4|%j+Z^^W~m8ss-v-SFZCesdZv}b1Hr9D$sPCLioS2KZmzzX15AYzf&6Bwbz z;*QcL4aom3_t8A0qIucMFfNDnCSW=&MXMDth1r{ODJn}LtRTL-dRnYcO@Ld z(eQrPc%{#6@Uqr-C6s#(ypI{L^qKd*YqNo+33Ay}O|LOt$=wETFKr@G!ZweA_gUlJ zj^9wtAICYdEbVnz8H+4EyXe%8tYUvd)nr*tZ}0Rw#sq=cV@&_SWEJsypeDogK2eTO zxxyp&_k3jZU=Uq@&MyA`3>(EB)<4f{2p)(z=?;BHc(p&h9=D;k_c=(_!D$K8>r77pZI<3CHyk>gW#5L@;Bj>ns`B+WWwl zgD(SjCj02j`apZ$ow+BdGnS{i8S}`;hvc^|} z15^VUU;(fUSOdHaYz2A_rH{ZUU@|Zh_`fJ+2(>&eDgS$jb@hq1F4sIBzlcRSj`2;8 z8y?QXT+>buF+R=V0iVqa>ta5QqZO`!r$-oHiS`?ZqEkE5^ue5aIf0vCh_ky*X}$`*_j|t&K&zTTOioV~`)GyB$03=P^-!z#|9PDz#~Q^L#d>s} z5%Lz`|3l%O74jD7|HI(F&G@(B|91ZW%KwMc#=EVJMfkt^82Y~-r({3P_kTYw$+Y?Y z@5dpTb~k)6eE+A{Y2p6w^{{>Ze|(&PI{(MF>w($8LSQ+t4%h^A8G-);gMf}+Xe$Ge z9%_7w#qSamxxVH~xaOhl=~2dC#F~dDW#f(3{wlhc-)w+>W%qQt#&fpT7n-vbe|mux zTMh?v={q}zcVfpU|F=;6cqYdj)g9(1e*BVYB|oI~^LgoeN+82x zgsw5GguePT?Rd~+B;+yX=eAc6^8Os&Z-%_VUWW16HRRCGpMmeY#<#6Kkhra(pFRuU zW5!p6pPJ6!LQ=Ej zlnba1?Jdhx<$Jy^Jtv&oljzMkKNiXUqWVIg^}0`{m2ZW6D_-BpJ}X+=TNy|jyp9X^ z!-utqp{R}}_|!^Z9q=kpb{2CYFa($Y)C04D`+#M@e_9Fszcy|hd;i(;3by#YgIfE4 zvG@O+5#MLBB(6R5u|Fc`8IvRb9ML#qN`1|Un)Kl-W4=)KpWu7N__pEes}g+uHTd2zz9M{G<6~<8 z`KcePl&;^n68dRp>_5#>`s?-!X@8~%-!&(9;(1s3X!vZZ{M3(0vhT^?!|Nqp_sPB| zTAKq^uh(&My*_^Q%I>Xty(ZTy+R&%HE|Yzl*yQF`#ew{}wVaAn?wUE z-yDy8A&+NmOldZ%ujGU2sm2rM8O6pK%LBT`{ucHJJ50|qIqJ{E3u~?le$&@@N5#Bh zzsNh&w;8YcmB(v(ToUtkgVqY>mHsea+^Hh`T>3FTm;d-NN%kN4`Mx}>uK8cIek_vx zN3;jV*BeJc>&GBDexOGeKNK(IF3RB*Kjhn;xTaR-o)vfyl zPSIL!E+6%}EZooaE+iGzp~Xs1U?4CGm<+T4bAiRcN?<*(8R$A%4F7$lj4qko*2dk7 z(;N5g7uek|dX;AWH#uu!Iidgm5;-sB$tmPsD791mVgB1C!S|noW{b&?@8kM4O*IWw zHGa)*ydx5Pe;vH<7_WRkkJtLPIKlUS1@F$=F~?iq2k9pyM*#G0(zjey?0K35>dZQ`iH(*;RE*_&(zr=q)(C=xLEmex!>X(KuJlB*9Z%!v_Yk0mgmZ-KC z5^H4>;<2@u{qEMW)Nkb)XpSVIRGXr4u7CE1pWJJf z9pCI2#oXK5=7kD=lyDBJr_C3&q0O6UZ$13tHTwS_ZJrzZm$?eHv1T!tBh+DAHy7l=cd(FS8IP?=VU(NIsF!qT3M`JTE9nV zflg`k$bY8a4JZ9;zneKLADTm-yTKBadnX8?z(#A#biqB}Ro#jD0Tk2Ze@3hNLWUJvh*~#$6`o@OQ{^kAVOCgQT zW%19b7d<8xpI3IF5tQ3Ja(|oXZ|%vUO~n_!g8O^aXZ@zlEcnH1^lGyzIW*{V*8iI? zuB@L?<6?yRo=7vMuDJ!{)i|EfmbsRS$VVg1J2ubmnu>1Snd7SCoOoYxW1I`V8plbs zu^FEKefNG|QrA*Du9073Be`(?w2J;NqAt~Ayq0qume^+>6V%`Ed~-`>lY)Zu*libb zB@?VqmD-`$6Y^BeXkr!9GQ763$;BphKRj=- zNp&uu&gCrJ*FbYfT&LPWsA$F0I9=*!j*jGwW7byd4O-L+9ubURQ@a+@rfTYa6xxU5dNp2q z=J96x5B+55Kgan;V|v-6^4?I^dyQ8;4JY14?>{xCLj{zu4$C#v&U$3l!ZQV)J7XTT z^Z&8;KJZmlSKjvth8PeuC@3gsP*707BqSkG(1auy6chwhTBrmPByAuFp@kOOi-i`Z zIs;Rj$`o5@vBi#dpo3HFU<*^7!46Jwit|86JJRA*I@-b%J1~Ro`(1mjeeb^ao&>6S z-p}(q)1!-D&f073KWneO_CEWZdk)uyX*#~1n~`rsUan2{nY`G9>&GTz48j zkUabvYn3=G$KS&D2lsFD{+HEDuUEz|nA5VPk>#GV+gsFq5_+QJ<)rpe~Nx?hW^Kz8(rp-CjAoX&ueOaU>^39{@6`B9-|#wXyn>kQ+^=*5$Yt%bbhed z>8`^2HlX`w=x#7wDNp(<)Rq2P3Qx-0gU&j1R-m&fD38#TrjuTt?lZ{z80Op9%wk@) zW-M>{Zq38wJ(RqU2YEAnr0FH|Hox@#6XJXECBM!;C;^{C+U$>y;!6$Hp)XBonj=dc zTWpJM4pR5c=!%|~6?;k^gFEo4FwI{Bh@SXVnAXzt(I$z%-lxK}#c8$CvGrbT;Kx&& zOlTZa72Llc!v=@bY@m&owjZM1Rp^Mkm+@`CHfXzVpY+xHso$$sKiofgETw+K$NE0f zS58Rc`zdFWZSFWyIe^aY#_dMti_w5&NtX9HfoXj!>p4 z_-^KV=>tC=hsXkk<9iD3-%rqn>u*bMLv`c)R{2G|1QcmYBkec|iJq7BeZg8RX>T9n zWvwJ_2-6yZJm0I&`t`$cYsaU9b}XkI$1>WXUvAYl3`1u(BsyNs_s8`?8`|rSQ0D#i zhu;@ib(J>YP6_&UFdyW#)Tj4H`s-e_Jtt|)F!V*&%lr0los;a7nkj=u-%@e^{d~lh z7aSBN_o+h}YY(F&H3x_3evC<)BarDDFXQ*7 zgS&e88uEFu^5Yk@H7#1u(2~kq%0E9=R<17^oHL7z%*kOL8{K10?7Tg zEi<;YrBUaM?y>3hEGAmqfDgQJ#ZB*X9XHnY*^8u8ISwkge?LVXPiE9{+Je?ajXYq}DEs~6xucJy)OT1R`(BXf zdmUfj;X!@FH`avHN>j&-(S#CUIO2-ano^ z64+ti-Rl3oukOmQg7ZIYI1hc%_3|=KC8H664Kgk0Z4t^W(AStIpKS=!mMml!u)1a8 zyaruch%LhOme!A@rOO&BOn3Tsx6W@^p!%|Y3e%mwrAyspy%eVVetNIA_SX*eGRQf4 zD!6}FV(XWurrVlr*MHD)hJ40Ub`y5$o`sYY|>>I>Jh#V|2lgBE`tGp+@yeZA|7s?G* zvCS&#cpMTPFXv-PabTPG8~c16*I6B9&F7ER)Ny4-9j7+%>jebfi#_~1F;8BrC49mc z1b&9HHu$opEM$7RYk}POYna1Y^{ypti<=wujs|`#_Sryv_mGd|;q|XrAlbJr zXuR-EgqAO!)Bq;Z|O2I3^GVmI(94rGXz+1pdkZ(%K`XDh0 zycwJgjsdwpE^#Hno*Qpp;#)yrHTXqvEVvo00lx*-f!_zmf%`zVI}$$ziC2k#2kF1W zaqteX3-j7U@IvrT@DlJYkndLT1uMQU0p1OkgHyqJkgiWm0q+Bwzz={Ag7{M6qu@+% z4R}BJd9VT83^sv(0X_ge2R4H*f*%I|5&Q`FFW`Le=imZRo>`->5*Of@4}zD0i$Hm& zAkLh)8C(M12GW;_3E;=TkATa-kAWWtmxG@GzX+}XzYcy9d!G8GUT5vGgMwt$=~&s&xf3xmet7Lx1WVy8ssDLbtWJF-5l`4vPQ$dnYxJ0d|RcS^8UL#{<{*q z47*yWe_jq7U?0(H!^OsPxGN&^q~pqZ! zr_Xuj*cWnmI3C_qNRIDE`dyK~2m5gTA~+EI0eCg|5;y|J{75~$35=l9!@1BfC zMxV`$f8PB^=;tGI5bO=U0&0FkBLBSme)#&VWR81ol2eKO(H{AO<1jk1j`^|W@hT|x z{8#WM@CbMt_%l%2cN8SXx$k<;0e{Zyr=Jc{?=~=-U&~C544kf^x4RqIPQ&N7RtdgU8TAAQgBOC=f$-cn5V?R$ zRB_%L%#B7x+6KWqXc5!`$vY(FeSoZ*__rJW)0KE4?*@?hTI#OPH|8Xtj|}VHkG#d- zuK@dlyzjx)UFPY5cFvsZzFAoU7Lr~IN_xGe-w85@y6;900%vf}_Y@KfK<=|Aa-*xL z(>2uW8aT2hkXToWor~SMd{0~JUWQ!y_jL5x#+<0oNxI)^B-gsb$Xoo8=KvDoVCA?h2Ymgp2>WOxF+8$P5cz(K5gO+ zkhNLjO_2MQiMK&1=huc2V~TrEZav7on*`%8VlO5k*K7&!QqZka!G}1PF}Vtqd-GgN zBu0Xt1?g+|t;kw%E$6p^tOXPFP4qBG9o;u0KMDQ`=kTI+;Cc{B{2BPCpsX9E+%1OR z1Rv#`_a(aTK>iK*80UWrZUp}xL?`hNpw#mK_&Dc30ly6X0wk}*Z^5sCxn1=8jr;&1 z+RFI|@N3xZ9`GBSH-diw@;xi}{l*W2Pjk-qsa!cr3?Blw!{=L3(GKuWKuQ}fd?gC!}zXQtpaW~}-J&*5Pb3O-r9$XCm9r#(0wk0-!td$dA0%>F7 zY49cRFTo#z-vw!NVh{Ku@Q2_*@MZ9y!JmSxu@i5A{{p@Vz6!n#N68H`%&$Y_9`HA5#z|)*-%#v?YUQ9f{6t9)IHwcooVSi%hb z8O!-xE#$MtJfDAiFpuSPRg=#ZM?U!|UC65PW=4ED`N;ZjApc%NJ~C3}_ivIw zaxpyzl=56fCp<{kMqpPzf=`sH>!S7uRJ3lw6@DbPS{ zJ`R7MK%ZR)UIg7@IL1)YuC~8rl_C2A*O0e-zce+s%k{24*OrrfCax6O6kejcpj{LjI0;3kmk@WfZa@!%8S z9U#{U(VgJ;z`H=!%F!h7HE=R0a}?L@iQ}Mr>+rup`PQNIoAmE_*l{}N-N6~)h2V!k znVaqhuK;I(H-NLjQg9Af2@=oUx3cGgcXLi$PuvR<*AvXUQ49DWxBw(BM(h_PPJ!|r z!goRW4k5l05%&}LO7t-h8@X=`Vx#EeoKxrM6CibV-x^#Dev)%^meC$a&6or24y`j*VD4Dk!x$Y##0~b z&fjv#TbJ{Q7ZTs{`1b;0(fRB+rT)I${e3>`wDa*ViJ9GbQ;)`yG3}sF{~%GZiri#f zF7denlxxhCKZ=huRO_CZtUKk9wVkX1<-j)1AK9OA{wUv86o33P@H%iKI0pQ4unznp zI1AhaJ^(%rE(V#0U0nDwsCJa~r`S>IByp-7l51bFtE~G{bzFu1VXNa*{+6Q~xY z@{~Gn1up@=21;yu6088f0geWr0&BsiL8V>FxOr0N`0grVlP>L>e^qfU;Ns< z2>Ib-)m{bsEeGylvmI*-@{;vFK180kCiTuRua7Z3|IC_{eH^|Ve}nw_;BHXbCgV)j zuzNTk0RAmF1jHv3L&3iTWv#jol(p%Lpsclj0L}vUgA2fyK(YTnf~&y;;OD`Y!N1$s1iuZw0`3O?8T?1^5csd)VelyUW033C=vDB1#v|*eL=W&M;FaL(pv3Vbpp5&U zg5$uWpp5f3z!~7bfeXMl!HTST-UN09Zv)Q!Myb=64SOWeM{4Vx64VH1&f4;w-xUFh5LTto}cH- ze&2ZXWL+oweYN(t?Dxrc0{nho$d_*i2w%$ddwW&mEs(-|zEz zNhS)Q_I7w!Yb@nyfy=Ogkpfv*2s_WS(bsj|}d^HSfVll4v&izvB2@e5~F zxu@gyP~6#QY%bTYV?eoHy%m%_n`%&E?pW{|P-4Siu#WQ*a2!|()_`|`_26Xi4)8-D zd)@9k9HJ*N`7X}ez)9dIz=`0a;8gIhLHsVUAG`;YHNm~$5%50n7&slw#s0c(>Wy7w zZt?S(%!Pe9uP0shtzdf=R$Lm&z4F|-2=%nlk$6k_k;aF z#z#WDv=OWVo50&ZX|Ke_d7R$^HiI)k#*v$gTEH)GJ|FxVxB&bn*b06JTnK&_d=O0S zQ^@=v@3)kmlX0Q#%VnLP%bg8f6Ue)B(&w;k$m(;VsXdh*@HR;%9Nd3!eZLeG{xa}t z@Z+G&ImFd-U-TZT)IqsQIveLeQFNfGxeDx9Xm-_xO*cV)PUi3#|>rI@Ctse&)L9Uk* z9|6A%%Dl80d=T6MiZ6Zz6kq%*DD~e8t^}U|SAkyxKMQUHW!?J?@DWhz@u%QZoQo}= z24z0`OHk$=Vxs%D^G;-eXFh7Hn!RNv0;0xe~zcDp@`*Fc$HUI$NuN5CB7_fJ9QqUdMf0PrYS2)+R_ zXGH%74grb%i6!7Ma0U1a5Fd)(20sV>3Va+q4$=qF2@o4bCqddA{RaFy@Dz9u{BKa^ zlXpS#ihc`{2NNvy%4LlNo)5C0k+=fP1Fr$$B}%}2@K&%JI2P;<-UiC|1vh{_!A;;wJ?>4=evtSXp7c2(<4lD(K2$q9Kz)|2aumU^< zvVW84%0Lx3k6XgD3;$HA}a3**MI2*hZ{4h8PYz3!) z%RufkCLRLs1vh}aJ0h_OoDTj4I0Ka5?9T+B1!sYK!P(&7fsNn+a4z^$@B#1_;5_g& z*bH`I0sCR_d~iN^5!edKH-#2~*Me=}jUe|m6J_8>!JEKk;8^ez;BDXv@J{ekU^BQ9 z{3!Toa3#1Jd=&f)xE1^?_!PJX{3iH0@Y^8o*hqX2{1fmW!FAw4a6R}M_<8W(!7qS0 zTzEeQ7JwVUJ|I4q7yy0=yc)#!64!%Y1#bku23CXHz}vwm!AT&#nV1GX4bBAFe@n~; zcYyNT^Hu3LtsL=5=?IKH?bOWEKg~R)K&JBq^=Vn zDNpJ;$o;MLl)c9G^1R0K9O2|MZIjQMS?wnJQnv0Prpw)!A#($H&4h{|sY_8ty5w;U zl$m!Qc%x`bF;vJ}eK<53x|Z|q{8wgwk96(rhW|*rx$9^t$>(t88sI1-2k)*( zFs!4uK^aBA1Pj6ApzP278mtCSg0lX42b>N529$NyDR3Eh8ccw)Zh8o$fo?sO1Fq-v zzjLEc|BbLY|31iEnfM`iKKLUrAJqLD+0&B!64^(U{TpeI?3)aM`alDbmh3NuuH;H54|oT7Dfj`f zFSrow2Yv>;9F+Cp72sci{lOoASAzcp7J@$m2ZC>cSA)_ggTVg;2ZI+;C)NmwUf^|L zKX52m2wo3XfP5!1aTCZIB2fd50B;9x1ZDrD2%HWUgR?=t73uc3xwo14DCeUNIR6W<8vGV`bJyt8$H6+z#b)C`vFUAKKFHc7q5UQM+|pmNCn^0k z8oCjZST5HzAzh1{+^3g&_Hqqh0m*&hj?QZ`(&b!yLVO|fT1o04{xH;~d0!Zfo%NaC z)c2!h2`Se^(4T8j`S0~HgN+0O+w7j34zvUPR zJ!XH;A|I*yY*4OUSxY7cflc6Ga4sm<^z*mx5csW#Cu9kAr^+E(hh>cLgYM;FI7!FagT=UkM%r z9|DhntH8Iw)u7zV{tWnE;2N+iZC(rJfe(W+ZvF&RJC0xl;rDoC54;LH%6?B7|N3XW z+T+XKjF%C4zX#La-?BHOWyv#F-dChw^%>)wWDL)RCw?f$ql~SA;700P4*ofK8~8=n z23h~;{)Nv^{8XPC&WSGJZ#l$YrGMr4GJ5&oW~VQ{Kf>Lc%f~MIEN_l`u2*DxLucd< zjwg_pdF5;1h2S=@5BL|L?5sQmiZ6W=lzB&Dh4}V%&aVY`fWyGQ0>#Il0i})K2F16Y z1;w|%15O1029!O8=fFAOcfkih$^RpUa?Sp?oXfLFAz z9^rZO`v@Gk9D;M&S{I3YZpZJ(L^v1ffy(F5??TV{G9)(0A%5+TKSpM0CzRoz(U-F2 z;4&?Fuve2O0njDMyML?wPkt9O=2G7xtc}rKhwf)X-I(w0`1dU=kJ0D;MBX2V`cw5s zfl{v5lY13%gm(E;^d9wk^3LHv&)c)F1PqP>1^4gg(R*a+5Wz_J2-P z=yI1e8vbX0Q?9$0b}bnHmH>tWy7wQ!& z;}lu{E@Ww^_DB5tjnQ#&nwXr(C5K#QgOlipFZ@CVC`SdfbrSIcIshGo&OrSqvu6ZN zg<7Ch&?aanv>!SOb##Q|f2#>z6e#>BzVzGaHg4`|<}G>pyAsiBfkf7)|L^?%m-ly> z`{Xcif3uFw>&YVC@vM%&PmGc_hB2xorVRFQ^DgYfGI-|89br5Ei!v_i#4<`PHqd>^ z+QTQomhtK|H~1MkFJz4yc5evSQ(+MBxsg(Vi`wc$~d1g z$~&=)dRr8RzRSKx-l$G2L+&eN_D46$7}tqq$UO%+!gh40j5|BAj5aGH>~o&q%$wPX zWgN0HLf_^2o4gNoVi}`ZjLH$VqbFs|?Zh%R$CSadta%S~Vi~zCrZd~YbFz8!Ixn7#Wi@| zlbu+GylYpE(69PY#*R)bV-gqDa)j-;oHF)wVi`MQ%HSF7ynUTmMqe{h*pB{`ai9~+ zkoWA$5%$Lb$~e@CWxO6!#+8)u^G+;7-uEj9D{|F@!L);qem}o zM_9%{%J^L;ma)*v2yJyWW$<&FPTOZVXk~!!n0Z=7-|TOnWV-)bPEu_dn1Z4e1_UPBO;H zRz(pchwSCbC5`OmN=Ro(lF<9|*QV{s>K>dtt*nQj-w(yd6XE`??xn@cVumzX-4lzK zy)2O3NqM@rmBW)jddO6|&Hlc^$-3|MBxHM`kaJmqg4cl~!0W*>Q0|Y7 zvU9n|It+fTo!@Ec_krjnuWguK11^o#C&rS_g>i)@f&$iclw*I(2*A@%TjlCJw%@nzf`l+l8$?n~wH6oww+ z1GDV!TdfSSja>T3xx}$*Q10H#c_Aq2*pWM~a<36fbM$og!297Fm%H<@e!5Q;U%%VP z!^?`#>V8wa&)$Ko)OP|XK06W2rN`yoqt8S9Lidw$c)DB<@rO> zH))fEynEn_f7AEwUWc3ywe*o7(@_FD$duvkm(B$5=KMpT-qY@ZUlha1_6vDmgFX|N zs;~5)?oGwpXEyozwn_i#9#ee(%|%x1->${T`!d7^x*rrT`>{Y)d_?zk;(g>3$Vz>d zgW@AAz)T;JHtD`ie4AEU9uGO))IBOGTlZq(%l?e%eHN6m*Es!j|CF}sUQ2viA4bR9 zMe3=0Ch_%LXXUMT<)rEM}hWr(cqXT-~H%#hW6iFnz^16i?^?k~jKY74T` zPhSDWR$m1(`$_W9{e$>CzHWIi=3O37x;*6B)6_d-q-hLS`!+g~$1bOv{+mL*HjmfaZF_hYA*vZ3hdwPn2CPfYJ$onHT>?WL`Hy%^utpPAlK zP}=&2(@$@!1(Ls`8R ziy`0qpTlOKE8@Hz3#|K zUXOHxw-l12ujO~S<=5Zx^Xn8j?~5G2w{`0jIUmZoq{}*`kaLMkQf_~qr<0>6tFx}G zLF9c#a`?WLy6E*td|d{Sm$dC#mnXlA0i|ueE^;n)xgNXOGCRKvmFGs0ES-5fYj+`j{;Z@UQ7h--pq#5Hr`DGv&;PxTa{hySiy-Z*9M^ABl-PBU{K1h=c#{2+?%*xa z>}1RrJ+*24bIM#ZyX#?mAu$23@NHns!iSAro`?_gcc@ExW!@AMO z?l;_m-PxJBfnAuB$WiC02OCmy6hixmJFh|~p?ogD3!%}_RA?deha=qr;rO3tN#Xe4 zj1M;4mp-0;-*GG1hGS~8l_S?S{@6k}t-c%?Q^B*Y{u$XrCMfA&!SOoq>AKV2ne5IR5XnfQ*0t+`PX&3CHCc{QM%;kZuUYJU8!kms;~f-L>dm8tU3z zlEui%*zxyvcE#xOj)lAdp>E7G_kP_nBW8TdGwiZHc1bqAW!r_xC(^nlZ`)qwpKjyc_&HDdT_2!lpUR4K2xU zPB57L^}urUMAysz?;Ka&=e4XHSFTiBhFM?vgM)c?RW7ry_YdCL;`vc6eLwFH{U1sH z`#3sJ%_HM1d2kVwC-1v);mcywdtLwea`wlRb1~)cyQQ>pexK_psi({-zKkMQVU6>? zFVl7 z$f2Ir{oG@#_xt@4G&y8k$V-+sKuoD< z@0k|d4y{iQ_kZ+y@Auo^ks+&ky7#ir>JhFfU!y*Ae0^j-8m}Lr5A`&N=-z;D3ioC5 zKJ4}6Ix*1m>(DBT8DV+c$H`md^`yKB^6~Dw=FTM#$y>_x`U%sQ@#~M*(O>5ErQ8^O ze|@_vru-x5uk`w^d>%Jq&JEjpJf_^AqPNEDxpK4hc(%wLVS9gu-a4-*(nL zn`L@oJCCCG1+ORN#pwCpiiPF9f!>$Bo|HGW;Q@br;O)XYNZk>Z_iyNZ&Fe{dfu5fO zN^QPpy_r0Ij@~!D-g}q>WITv1WDbyLEY$Z?_d=v?vmiP6J0aKo64PalkeJ>ZWRES; zAC&d*Fp#;=-G^a*N}T83ebR?ji@e)b-YGKO{XW4U z>Y;ufpYLTEvg*_E`HJk-yt7AaB>AfU#^>7)*?!y?_p<7<@%f7EmF$~%S@qNSe6K(@ zw1fI)e7+(Z+Clv>K3`lXEnoG)_WDIc7om zJUrANDupIN^PpAGCTKTw5IPCna} zS>SgZmv_7I#H6dZZ%BaMSgUjWE4hk~Pf+5_|-S+`OJG1S5QBZd*M38;)#j_ZdQC|vf|-u6<=fjU*uo5 z`c(6`oac;CoXKKd&Z|c&4&XkfoDa16bz|_#`Ah<~;2Q)o!Pf|yf?JqW1ji7R1m7N_ z_yTj4obO=F3NE=tvCQl`u}aV1xkzy+6NJb$->q29q#@_Mtp1O)XqWT7*C-a7ou4kz z^DP4vD@zp*->#Traxab7^Z8|p%O)s3I8;%;8^rq|@6_|d)~=VVzAsKueox|r)Z;nx zgW=Xs#pVY`%nx3(a-TK3Pn)KC1FfIO7;drt9%K2Qu>5*izpu4^Z)P%)at~WSRGS~X zV}5YrCQX0C`oE{~UnJm)ULO{zg7YE4_15n_t>4F6zrW3%|FJN ze{8v4(|ekqyk!2d-uz>z+5NEPKYyUgH<^DtZvOFhq4M7~|7bA1XN&^bv*1vmAuFmXp*y6$x>)$7=AA6bHP{U(p$LfovD;S%0n^qUm+k zUz5$ghijDI?L&%Bn;)+<>}R<4gPQ)1+3Q8amnSLz3B$?OAA^0r)NA@nX79swR*vCB z^P7Pltv)BJRqllO`3q)`jfO8+{WltpG3;e{#O(Vx3smWcYQxnx==pTRN6g+YTRa(K zc3NrUaGGKBVAbnp{{I>a9m#ix;ac;%;f6Ve^RKk>4JQuJ^MQubtzU;5<`^!q{#)5k z<)<0$uz1q5K>0^(oDMd8v8VDMH+;}=bvNZtH+(c-&zlY9owm}RmkhTU@*XwEA8*L} z7~T0^L*Ae7&iQVDL%xsTa0i)5eyct5x18h74jDcUg(vjv6^i4l6^~f?4cF-Tjv0z& zHh${Nf1WjedDi0blf^1mZF+-y==lm8*N3eg^6q~rm*0sxxVH!xn!YwD_^4Uelkp`0=QXvmF*kj#wNSX#M@D z`QgT!RByG};mK?De7?nzCFajh+c?=`@#DnBD%Wh|yv%U8#s7EBzxGjpvDG=K*Gqo|P*1h{dC4hwAxZvvb`9J%4SmVvfa$p7-kcN*kveZG84Idu}xQ zK4Sg$${3a3Yv=uL(esJMUvD_n?AFJ|^-IO0Wvd)mf#H|zfwZG4wm zzjiZwylmswH`z5yr1<)wZ*#^EMC24<@PdvoHyeS6V+DzEsbrS%17}{qf)j zmH&eEM>n(MVY73C;o;FLciQYd{6al{$^5#(&L>;@_L{vXdwZMz%{TvEVs<@kae1xD zzhLq&+dSN0dao2}d27wCWoFkEmOjAh@rI3$)8>~G&CdPI&ZqCxeBQPA!h2L*oO;6S zTy1uK*8JxgvvVIi?`h*|qS?LJ?EbyHx_FP|}7X1KSP>OX1yQv3luUuOOHsM+HYv-8_F?)KXGUh|{LR^N?g_huUx z)BQNNak$s|=^2Yl)2zQQ^;=i#w=w3A>r1uX^k4-aoY6On%>i9{|D`S{k@vcdb7{7 zmQV9cm3z+c9rKeV<|p&bPo6M8X*NHpGk-W?IMDmWMVjAG zE2rnJdcM~D;c@GaH_R^vnqPFgLFFDazj)I8;)Jauip?KhvH9yc^MgL-2h%Q4{S)Q~ zPg{TXvHpJ1$1z)XtTg{vZS|>}q5AJyzjd|#S!UyYqQ#+!V^wZUvEoJ+QaKTOv{p~Q zSHHTy@}D+)z0*_ApXsi+qnqLu^TP(Kmwa1F^4kFkuC;c(VfEN(?bvAY?@m>@m3IDQ zwVrpYQGCw);|c5E9oC=A#%TIr>*truA6~P1o-n^TV*RqiaHC=506-U*m8x+z4IZ(nZ_SFP0x2&dwQBbJ!p0~X6<>w{Ox6H*Q0j6(d_oF z`QNf@G{3#cXp-v=81 zW%IAW#vg2c^-hu1>wd)n7FYV!>-l)|tENglZ!-TpVs`0je)xphrK{Dy?pl>^u>6mh zznr%5|E}5VWwXNEX()#E!iuAcMF4ihbXt)(w9ySy=7<(@Ts#IV7z%&?o`Yxk-A4#U-k z(+!6k<`}+W^UsrpD-0(a4mLb}kLLT5;TFRshT{zf7@n|s?*+q+hVu=p4f_}#vw8nH z!}W$uhLwgr4UbsAK4ZAnaHe6gVOPV$Hh!NrTxmGXaH!$CleL}QZdQElCbOsEYQyP< z!wqu`U#V32CkxCBrR-OAN;w4lq1XqVml) zu7=Oj^TRV0kJ-G_$M7ZVr#Ec8zGL&%%eSfg;}(xr)am&No0m@5cpG3?T&?K?EdJ~r zt>?{FpCcA$dKxaXxHNy5%JnjwdA*)j4^`}G>xuOiA0D-MeAwpcw=M2WFI4%Lud@7X zemr6GT;1i$f2ObEj*ArEv3OT)@ln1#C2{asiysf>>3KhkhkUQgrSt7xhtm)i`MqYJ zcLwYEOBT1fPSEovlRs_kf7jB-Tikua=GDioKem|t=bQcaR%<>R%^t5=|2CODhFZIi z*m|yywRg3(ccrzr+S=1#?O0*;s_bL+wDG#v+S|*I=PFG9dif4e*!W9BTGlJy7Leuyx3zhE0ZjZrAiWYggB%{HXgCxjDHwUp+rYFQ`gH zvl3A>tKjM=QCPrtlln#7yXW#-fc%1dOD`mS?7G7IL?Pe6puU%P&ynvb(2X(a&jZygRALlqKNzpTzZ}4pNMj+qugYAq9CfGzt>Qa>sDW#-yI*OeAS<20dj(WiGO1D8(C3v#0>N#7G~OBA}VP4k9EIjYE?^c;6mP(`5$ zisA`(X_*|F9(9R|_$74}Px&UQBt7cR=#O%`6kN?m-zMEBlD>YV^LKt!RhUa2c`koz zpKFv8<)1+iF6zFg&;o9Pwn2NKqtF>BpOOlp3aA#E1j%n(63}DNZfGC$I&=!cxX}=Z zhC~yf`=Eu;a%cne6toL^9(omuXhjdG2&#u>L93v3&^AcE*U9%k<=dK3Ayf-Zg7^lb zJd`BgMvS&YyPOWe9K3^StH+>iJpgEh2DgCY%b~n4T45PQ=wVV zQfL(<-a+zlOs`q3bO!3pTv7{7g62W;bk<9y$P>gybPVc}HatG#Z)(Err%Wo1ksbPG}FbA36k`fqFAM3L$xC<0Ob77d-}T zg?2;xpo7p`&?!j9Uw>!_Gy!Uam<% zbO<^Q^}d9%7)SR0%Ds%ffvTYUpoP#HXfyOY^eXfw z6cMxfLPgMMXe!hKt%5c|JE1+$A?OU$o4M^2luLXY0+m7&p!=XkXd$#5S_5r>HbYNA zyP)Tx1JIk$Nl0F!(F5uW4T6fG(NH}!6`BRLK&zm2&?aabv>*GUbRV=3S`NuGmz$wo&;jU8h{sT)zEBY~ z8k!2tf|f$Zp?uacy`f=H1yl>ofaXDM(8JJHXg72adJD=eqz+JjXadv-ZGbjIyPyNm zn-H%eiTXlCP(3siYJrwQtDtSrPG}FbA36jbg^ojKpx#$wCukT{0o6j2pczmb^f2@o zv>n8ZwkTp-DGTA7~!b1|^`!psmn$XyGvW23iAchMtEGKzBKOFxvEpTx(SZ0MN7rN9w@O5b~%EFbmpYWlC_oUr2h!n>uI{_HHxg(@nNTDKQajF zrhJocO0{45pjS*E^omrrp(G`{Ax2htCOa}!|5Hvj-c~FfVh>84kf^82==p1#Dxj}zsae0fU#DJSoK#N$4U=jD}e^28rM zu8unS>~W=hlMiB$jH^px#?>W$Trp;SY}*+lt31m$7_WV)M`pgtGugQ*TP}C9@ncXN zNz+wtc2TOWyOMfS+LpC6VFQhC$~XDql>BigFSbmVSH8&;M|>QW>&Htv=wnScJz|RQ zgLz54^gdR;$>U32ezTL$?qlVfeBeWeoP2g4E8pbtA>VJ($5+Ml@m1Q##YNQJ%g&3D zRi4YYxG1RiekYq<59OOY_4av7JqEQZIfCYr5$LV{A=QFTH=2Z}N;W-@kjDe0KjT-{hI=z5FRBpKVv=n|wpc zR$|v1V(fZ@^=}zt#@lsYjI8opzQtvX7cV=EdSvFSJdxJq zj{D&!?bq?Ee3K9SO?HuPh{TTR^2#^)V4RG0^4WG&zRBYc*V>vy>^LSGZ7;4L+tNDc zBX>5;Z@Ojn{r6)*>7UfvZ;aZuq-1uw{w?RIe~Z^|Oxat?zc8jBFSPMd7Rb(vkyV~+ zS5X*Uin7dl&K>u8$lln3!x_T?^&vhA&W zlMnn$+IwY8d#|+i&c(Lg7o}~PvdYtZ=LTz1Y15S*!~;z?J&X~yS@p8lztZMpy|Aqx ztI{^rN%u+RTN&8Z%gbDLWsDCi-^mvjVN)NYb|&+Wk5QU#df3+MiEVp#U;|Cp`pqV` zc^g!v^p>>ElP?;ld_~hthxq1odQe9z%jql*bTrL$h;d%0KB-gNI%n##g_tzylbU8a z4Jn;fPDjRnwvMKm4u0dykr=CW%kEQ6GadZL>zqlJldYp^ri1Tzdsh%^w4C^U(sa`c z{AX!WZ)$T}u!d2-$p`+k-O0PTBu!rVDnBQP_isA+39Sv()yFU8nQSl~H=ieMNS9Tf z$%fZhI8g6sQp2Lfsdd)|$1~X=&dZ*6@0hrte3K96{lyCBZpUIk7%Se}3zR3rECTrsIm_Ad!%F9~Z$7i~p-}0yT znev=$(Ma0sV_=Jum9;|p`bqgFAGCF=lh0m1Dc|ISw!Z4*v*#h@n>=j|>wbMq-LE$v zDy8mTb|-mf$|}$0TU<)LeH`hF4X<}TWG^R0*ZZ@knGSXLI?{jFJ737w(KOSc{@zz} z$@ki5>Y`<=Tt3>gsBLQN_yui2S(>hTBZKwtX3DxYN-EvmI=^87YRNiky6FY$-&Mqv zYq6Jp@jfN5e3K962Pyx29ZL)5WXvg==5&fmg7xHRrz3q{ou#8`rW3>&X|tA7)4Bu; zcv~yqwzP@3x72|a@&2)%2zJKjACW|eR9!F7gQFP`swCtY6oCLdg997^UtzO89~sy@m$`3B)@ z%&B62(EQWom2dL1Q)5N$o1Pz4H#P=sRi4QP<7yL*kSVJ?lO+>B1|#N&Oj+fbEaS<` zHpa**&t!u*u+PcXv@|s=O7@NNRCZ*r)*Y57b+AhX7Chc>lyCCPt=@JUOn%|AsjXq( zE8pY;|3BsAZ)<9+Td-t))1rnpmSVmPO*5Uq{~Nj2dwwJ@?^${m%}UBE-{kRsU#I;h zznGX2)=Bv$A6!orBoTuY8lo?|uFo0{Lo6@by=|$>Z-gnSY&e@>7;A z#v4b}w6?S~&1q|HU9fn>cr(K6mZlNuCQ0V0x|SznB8-iba~E^I zE)suk)i_@w{X4?ya?0^Xy9JJ|0#lm{l1*j$HKEG8@=He2@4iiK#0x237D`$9+}qqX zZ&K^xW@)A5SzMG>H`TQ~@eN^G8nc|BRv zcBH52THZ+N7xvMhm_8b0Yp#+Y-fyGqOj+f*e2YtnM!r6By*a3Zb-SjU9zoLEt3Iih z-XF?W`7r(`oP740RQVnpMM&=~s+HT#q@{(PHvJ6TyzPvAvn zcP^PfyJ-=uWNg%QEu)n2=Jh0I4Rt;huczsz7sT~a+A`GHSoBimDBt9Rbxezs7h9#v zE8pZ9SH3T{I{Dh>#S2@xx=iJ-e3K8xQV-(KQ0AqE#`OG^Z}JVP{M(#-cK*sY`3zsZ zCZ;d0@xDr1y_m%9SUekeJYr5&tR=-}|pVZ6V z%g{8_p}pSz`Pk>07++Ps$p>pU@zvrO`xKjfa%+vhqzn@Xw`AK0CH5-{k2#-)6B-L5zJ0)ILS> z{Joczxh7Lqc`o0g%Ano{oUGU<{eG76O+Ki%w7CVV z+OPSi+g%j z@tNVS@1`^_c%Y?e@{(4!sPXGwP1iEYm;Z-#F!D+mFYZZhFDoCF_D= z>WfQeFK%mYTOt=cDO+i}={2Nm+m_Tz_Yvir{OpwcQ%+udH(g%&CQl6UeRtH!XUB2n zn>=wN9Df(b*!5zIibT7VsM1t`3syytswf7)uhn2V<|y zeM04%JYy-eZ`T<6b~XDJ2YHK+c6IiZTeMWLv;V`7x@O}-)J zTTeOp?D(O4lgGDwoeGFIUBy>oVw9$tPB501JDuz@lyCBl>3!WNrmy>0U(X5FMB?n(Kety1^vV)g`-uXT}YZa!9If6J}+inqkNSwDN5N!?48$+Kl%EU1nWzwXOEb= z_prK`1?!)KPFCjYam|Ysx49_h+pB3>pR&?m?9*30Tze-pm`c+A1uo5Wg6p&iNu7z! zjg2i$7A})|nr?a-2S!wr#hS^Om$$BW?tFDBtB>JUhdNg)w;- zTHZy-`f(_8W1;KY>XzmQ79{PWe9gNkSa*uO3Y}fj<&|&p!TM0_<@0ZATC|{{t;t;o zdY{vD(+k#zwN6iBaCJ+Zo~D~#LuyU4Dpg)v+oI;#OWM+(bJuj!3u6ABq~5re)`rx5 zLgkx$5c5wZ>z6LCe3NfXjiDmqk=miYsri9YfUp9;*6hj=Q$m*LAH*jnNARE zj3#zW)y;%Se}3zR3sULgsqSUq4vj`%(EOAB>B7CogSCmsh^Y zGcJ6663P7UZspOJq>Yqs^28=DFW)Fqe@vHGzR3q;>3A~#^!uU8H~C=Idf9eXzR3sI%(HT&>t1<(Vvf z9>)Ie8M4ym?q=K4V0?;gySHQ8qF|x`t*~XM? z-@NR6m1nZVSYO}eF|x`t*mJK-#1de$p=2%$h#*pZJ|7q4SaZCjI8oZ zHt^wL7i8zFJd+K4cwLOF@=P}H;Y5$@e3fUife*`j0y5jCJd+K4xV~q$tny4Y@L?Vx z&&pSMCL8#$yk8)*4$3pxz=!w6$SO}|D*_)L#ybWw^HrY720kqBCCHRjp2-G2TvU)P zt2~npe0YD1tny4Y@Zq9fG5I>4$p$faLyWBQOg8Y}Q!%p2Gugm@XIz|J2j!V;;J}-r2IsGugm@cgDyn&twDt zm3KX4)0leLBll3RcGt?;I+|uW*vRWtIh|BF+^9>oS<_4>u+#F4 zazY(VGac;Y`(l^V$zIvoCJ)7}yy*+Ow zc~>Q$$IE_pjV?>tKxJJXB_oL+K99s%@}OIid8n-AL0s{9oH%32-`sXUfq z*N)nPNt1b~tmQ!*^7fN9Uf`~e>gG2zr}nCp@8pY0X^@v6?d0VeJ6&G+CLj1%TQdLb zJwQz}oxsPoC(Fpz(KOS+$Gk7Ul`3aROH2Aa7ELo9jN*0f!+zTK@e6ncvY};h%3hjg zI?OX(=lP^g_Wq=%nGXKqb)qg(j@T?)N7GCP|M1tXvUjX?i{I1KbkoBpyx!7eS@C+B zZhH8Euj5Xq7k}?a(@cl4=XDCtlRBakbMHvgOs6sBKMy;d?E5szH+kkLUxw_JT+q(F zAWbtJ<|^-_GjQGuVq${wRbGCR>gD%1`RqC=-{gtUUS7t=C^u%(pEFUulP{hf$jjIm z<@!HeUil^;%yTj>MrFi5<(X_S&%Nqovtz6BO`fsk{X^uFVfB-G5)K3ZIi_0u>C_~+MmoDfAO-?{+tY1 z<+*%|il~RL|28Kp>x1~`-!$FysE@bR(WG9stu)Pa0zWRK4|80>@y&mZhFiSzMKP2FWVQDZ}N6_l2gLUf@fz_PZ=5Rw>`)gZaJ6$;(`o9;=jZ@PczrW|(LYuE}b#MQkugYjSO${ksStnfK{G)wcl`&mngzxi{$#ToDCrpo)mQ zUYo#dyrmXTzHdrGbaI(@~n%lIfX~CS- z?~OIhbb`6E2X*i3?4PZpX{HnOS-sQA_6g;id@x5!+eSq8vm*WuePV>oU**XAew#u5 z$ji@wl0RtlI-2InC@ybEjUicMdL4iBq;5gmqGdsODr36zxgWd7&p}sZOqag*x?5TE zovmDzFtc z(KOYOy=mXBw^BO1K!BgsEojpleStky#&n6}{@oz2vR7?&v`IC7PF6Y7C$5*+b?@`} z?dyj>1EVU*cBqc!Ma=g$ev7?KtIPNWb6S?jL!`d#nr1qsDV;S1Nu8|y6-_gpV9q{x zaZ+cB{uD3$zNn^~UNB}4U6RzxvahC@4rA8G%%#1Zj{Zz9uz~VTJ{YgBwN9F_=4I^fBurx(KOS+N4zf&D-3j|EofcTNMPl+GmG2Of7h#Wrq9^( z`lSN{{kt-?Q|(nb)tCKsZ`;jR2l|A>h6ffkEM(#3ZL8^~7p#ZnJ)_CC#^`Cf=`r?v zdA$b(di;E~p?QI9nBZ9`3r;hb7-3B1mkST;6P_;1HULtm7{5< z!#MMMQ5&4jl!ZLje%FGUc^G64kHOrvq-}9?qdvI5I9XSfwLBPe;rv?^GyfLZTvUP2 zcv)HFX38qh@}gtqWE)bl2V-QFXR^d9pKk?ggv>f9&t!>FUUpNAtny4Y@UMvVLuS6p zGgaA|9w72R(U2H`0o&&GstY4@=P}H--lyl zm1nYn{~nK#Ri4QP{yUYmd1f7yXR?9+?uwCBp2-IO+n?tQGV@iQ$p-$Lh>=yE$p-#= zG)7i=CL8!~eL;2|l&7-c{nn>qWR+*Kf&Uit%Fb7LCL8!~Ta2voOg8Y}Lou?-Gugm@ z<$DjA_EnzA;=g`vvpFT}F9O{{FS&ko>86J-`|HnwOOj>Si({G=*~MgXeWx;}i*Nfi z;;IVBiEk9V2$XVo=b^(yEyZ>OrHUiMzT zrkM`$%9ph~snh;_j~o4U0kO-sN$zjl7_;Z6d@Co2U$f}L8#DStc_xcLdEb}zjnwOb zg-vs~*PFb~NnP8hjOtbfF-rKk8RaO?$rcsUkI8v6MppVfSKC`u9Q5G<$ItFV9X0XIJ-40ocs)&5y{2GXtxA>0yFXHWr+kwS#?|gr zIcf6BH~FAXPA2nD{|$liO`bmSK0A!-lFMBjNtai?$(N?&8=buL%hZMkh*aKA$~Spp zz0Y5+aWwyQdF7itG2Y7`bn@9grF@eouK(fqKi>j5eC6Tu_#;bvcbpdu`xjqpN!vtP zL2Me|zai~9OOv?a57^O<_=ig(cVwphm^3a`V$*&~T90|Zs#?{o6)ygEo@w?w?hVm_t@Laibqbg|>$5F`s zbm#Id|rj z4@7IMvXj6L>h1GSdaZg^acxCuMOkI_xs)|6+3&LN+HP56TU#2V>XD_T^mEa<AcGS4BBhO{bEr=%d)q2Rc?%K`Y4?g#}F|Wa3I8>L99mf*d z9Ub?>2P2vL}g*PoRY#hATXC;g7|uH!qXnz!uPwp;%Ryr6JVLrYXr zQCe5ymcLG^+hFD@xB8acA)Tuxrt;eAQAM@#ia&RBY@d%suUf@tf$g?ooIE>Q8Yil$9#>OVUUF_@=_BVBi^tDzc%Uh&95t%Eyrk}2 zV)3V=3iHRdj_mF4o{y_6D;`^0QLW}ai_a`Qx7awojW@^4iN@6ym)DG{th21olJ~r5 zvvpvH_I8i`1b1vl71!2Qm)7Y>J=^?OAI&gd+}cr}O8Aw#q}3Hg4A)||B;3)lFHVf) zI!%s;&z85l)m&CmT~}IDdro8Zwy4PR-bMcQrz=bT@gaRg_WkVgQKhxxYAeP%*^cY~ z;b^PP;gfPZC_|s1sH`k1A6H$?#UDq<`F=8b(<*!v*>>xG*FyKcne!G=U}6Ill7m~ zao&p;N7dCOl{KaE?i@Kfw#%%jx7AtvzFoVpeIW0inAp%ZXCALltsYxlHr73jdoE?% z9ldE~9Pha9u8hS|34SxGy3SU99oN6{+~SSA;IF|wqB63mbZkX&@wu!wmPF5+K{{NI zxt9kqyD^=N#l%wPPKa^bSbr^@;_H{|^ z*pkZ1V)nhxp6|?Pzs-FzR@<$&{6r_1w#SvbODHwWS?m6Z=+w1ZmqRynP=u;sXX(!moZC8VihOFJw!EUQe3T8Pv*bJH+}7=~)jwxZ^TM{MqGn`K@u)hTu{*ZM z%1Gu?IYvY6`bzRP0@q5_W9zsks64mz-KWmA?hBh1S?!C;_{Lyet#_7=>)zM{`z zm5wZ~si-JpbC;vzeD8{;+Sr%pg4(rjz;+1QezQRkHJjB{H%^4T1DZB>gspBTnQ*JANYd9VGwg zVLKU;|Bjys-|u(xXIdK5YP)IDUG3>fT=x6qnR!-speOqu1&|#e z)dSz0?tbe#Tb(+!boHr&<#FG^ydYS7VX)w|`MloNGziu+9Czk*KKJlwXu^x;;hU|i z^fP~-o)&bE_A|4|MDocF@i}eQ{pSM?;ey}c1AktJk3P zj)sEx%U%*69}o7GT_*9&3`0TBejJ|k)2nm;Qyz1J?os*WIK|mM=^J69TJ-GIqsPF* ze%v{8Veo!5rVQT6vGP9A%7{0Hs0{bBEVtZ+!LlbjY&A@`BkNo1VXwh-8?(N*VGSK+ z*$QjtV2!Bva0e@c>9%6?lV|R@*esat%dGEySOZ6X&%)TG!eD)G!d&(H3^u^w>sHI{ z>+fO1VXm^2!(4sheAv#{?XbQV!t{I8-GdXZjfzZv9@h5(Ckuj2FdbfM2fu5d@dd$O zv+}b{?nl=CV%avBj-Qt8#kDW>>3Ar4%68WXrasH$doQiKZWrpy%SzL-Lp{FU9$$ah zgOUNkrujAOnKb$VdxXyAD(6!$t-DQgwa2&C<9pr1-ht_MWb^w7rv1gTMpR&oqka`I zT}Re87dFJ~+A>*PptzK5-V@Pu)cDbYaKo8$xr6BWA%o?rnvz&&C!>Ju;X|6M#AWZJ593?mU6H;Fq%6I zwk(T1?0OHo3-+`l%~Cq9tIh6%xz>9g2QQ~P(v-RBTGGDnS1Sl*c6zyi%oMLO#2|apEyYUmcrPq!(iEc zS@~J^h=)A|)Bb6Ft6^GB%ie(Lc&7V7DVUV=LzvdfvVX#~JuTY-)3R8$JDpR@QkBgg z-4v$2WvGPOv`E6_^kXatMK?{czkm_zJ(s& zWgg$v9^W#LZ@I^JFHF~it^3n3UGEGvagg?WEh|6E-pb0)vJX7IPdvUaU|LR_W{v$b zzZqaSiG!4LZ&5@~|y1t%FT-tH<|smXDWl zkUD(tVY{}u%X;e4ur(tjOaV@9|Z5d^0?3wkJ)Q56D%A zOFh1;J-(YfzU3a@Js#h~9^aE5-}4^d%O2lr9^YFY-v=<=#&{VA=`Vlh105$UtCPy? zi+LFb@ik9nj)`~~2VtF4GOt}a@G=g<2BtE{A-s%(uo0HX#y4=aUff3d!^ zJ-(?P-+3P2Jeanp&2I_p_#hqhnwPwj`n{Ku`FhjAvc@E&$B~w`hH3pQ>*!$z!L*## zmk-nReqdB4iE5xxFg;eZYywQnVp)ZU&4B6HV|{aAT29L@haDA_PmiUwoa;QSE)}lH z_Y)GVuYQLhSdd0M_car0@Ny|^goAws>svDotuK$AkshP8%On}LXFg2Z%(7!(+Afxz z=<$v4_{PArJ#Cs3v(jvD$~o1;&hxMfvhuTOUJ29ox9m}v?(=EdILLZ?npPh;I~3&nYb{hw1of**utT zo0ctw6-IgJcLwrS^7{rh)WHUI$&}OjPKIgUwQRJ96~bye@+*UB|Fmh&fTbcI%^nA- z!?iFSvn+c6rscHkF%MhiVK2h84mQnoFs*}Sn_zlgOS8v8>hN_|ewJ;^%FnV|T{HEw ztPV`eX<0)LYXPehmCpLw!L)vs^?*^-Fj!UuOF7sDFg;X6M6#puc2Hu)c{sf?!e_{eZm-OF7v0un7(} zj)Q^=9PBT!&m8Ttp$~O%l=E74nrotcm90ZzKfb?qNqur&w(r=D>9SVA&GbOh4%VOE$tTemFxuyHrRUUSOhuxNypH1^Y znD%+gHo&4`iD$27g4F$eSStF+GWh~p+r_foJ**x~+syi!czi8AzP2!JYn$d_S!wF} zmnup9`edbP*+7`~3Cm8(%FnW~Fm2DnqqfuhCS>_6n+enQ>}h;+J#3MOU6z%fP4i}$ z_6f_Lhv_=%Wy-QPD^1JZfoa`!f2MW+vxjZXO4Itb!|F$6IKq^r?&$P-l#eZ|=VA3d zY;PD@hQX#;=JAb(X`5MJg~wM3)8ldLyUF8Q26MH`y|9xVb*OQgyUl9CTxID3bJg!K zPntbE>~NT?4o7?P8|v|$?#XYAC(Tli?<@}+=V4_qSN*1Y*aAV zdRe$70rIjlicK3mRCFx}@{HpauQfa$SfA5-_+VNIjYjx_8E*q+g6dL2~WO1)OY zw0~Omdk=d97Mb;Fe| zGvB3u8PtGfYeyB<&m_(d@+mjPb<38_QQ0a;F*|JQ;6V2MZTSsLd#)39s|F{2^aDb6V2RmxFAb6FFLB+cU!MVI%NqZea zJ2oZ$jsvN6bhH(G-eH#@n8N3Iyl>6-*YT4brMM$q5-`NhF9|Q--3#%m6ZjR;ScHy z3S~mQ;z>mX`pdS0XvU+iMU_9+5zT#-z!A+lmB67>k0rD)T}}c=_QVkhY_8w;{`eNG zGP_!Wob}i4IatCUvM2Dxm5e9(OJJ@t<3|EtGy_a!0!v&@=`jg>(T|9K{5q4F_7bIE znWP%JX4CVqB+4gxcuxY4On{MK@pvA+1fHtD<4<6$Iw?v5qs-EhVDWg8y#$`B6BH#d z#+@{QXD2h>C2+@cktFcM^A{!XRQ+vn0%P1H;oKKVjNvowWcJRSlQ5IFCCGdy({?0q zhm)2iSU#L|FTwKRBr6G)?{#nXRyBSB6s(_ui?>oogc z_`9U*!8NYj@csxX%b?O#$254P?{N=(_wnqdC+Zc2~8=RQl4WOI5`cU3tNpOrpU8^ zaw~Xc)h#>uimR-;$>x?oIE!446^M@QbI3TnLXcywnV~It#*^id%sFl+veg&IJvO(( zPl?VPl9#+P{Y>6!bkz#x#;j)Xb%Uu0N4?yd;2fqd&2ftnYdGs^ZaGh;_RRPeo+~F` z0g?Oc^pvr=mLPqmo=fgo=ibTf(NllRWt!)lx7tbR35%=QhuDb93Uh0|>J>k9r!U$i zZ@}`xu_fgt#nmf8SvX60Zgnq9Kl?jJvrMU;qqVw2UTHWLeQueTq^HQw(afWt%j3>k zjUx;l^>QmlQTl=PxtVzqdHVSbx!HNfv^+W@H}g1srbTXcJ;<%r@h!7+7fq<%MmILP zn3{Z>FAUG`%eegWpXf!I)N*W3y@HZMMf5PcqNJ3Ezw>B_9E+go$Qt2DCVKMEe;~1H zCQ*%zJ6^T96`^cmIZwK)&goYPQzllsEvs?*S6Iv-QzmoCOAE+1;A0S92nIK{+Wzg1 zPUla1ZdBv&3+Frd`dRp3zEwPcSb}^}S%mn4F!%#+S`iQ7o5GI7_4vk8?&4Yl>_&VG z-xSKX_nS#a53g-v?X58@&^*{2A4ZQ8{q3eyozr? zVp7Bfb=0JK}YuD|Z^mx2XFPH{tU(#B=4FQF%{!_9NcTd%4TuRhDZ( z+=}|j9f7ZquH5yo5BaBvSuC6m_Ri?_W-dX<-54#2Su_}ezd3O`+9RKMKIM};{7T_+ zM?intw+r!Z#GQ%XC!dDI`vdzBuOtJx+w&Hdm%9f)KqL{&V)?Gbg)Da@@c=%QI~A9+ zP=8_x?+iN>*H0lVppq%HFWp3X?Va53p!XoIXZ6jd6}gq-CnMPsy3>`AtUd9;l@Lq(ovCC@&RIVo4rg(tJ@K)BqCu!1RQMrV@uUF0XR3{w&hX7gUf>tbGSWSL9o+2R*2 zlDVWMPf4#c`U>_uHzRK5bwTTNnd9Y2qc(hR%2As}kS(g<%yd$Z!=6A-qNmW)XeC;O zoQS@*Igf&~kJqx(nTneuI9C>Xs}l2Kbmd>QR!q?OTEMnD;DWh9l+RYrap^<|HfLI)sLWjLa@A#RJ> zq4r4na!1q&hRRDmkd6f_l0L+7IDXa@Qvnu*Rsze4AuS!gzzgXW?O&^&Y@nvWKsg=i7F2wjXW zLBB?e(WU4zbUC^LU5S>UtI$$(HM#~}i>^c0qZ`nT=q9ub-HdKQx1!t7?dT4)9NmfT zLU*Izpx>hZLieD1(S2wIx*t7&9z+kJhtVVGQS>|X7S!Mth(=Q601wlKTPcq55cV)Bx>+8lpz1F=~RE zqGqT$+84Dz@_aKnn%N(Xec@n z{Q?a`C!v$kDQGwvflfsu(P%UZorVg~>1Yf(1D%Nq(O6W3ictwFMQ5RLs0@uq6Hqxi z8%;!$&}4KDsz8-!3Yvxr6Gz0w-%|z#+U!n8SEHoR Date: Mon, 14 Mar 2016 23:15:47 +1100 Subject: [PATCH 08/18] Make all aggregation usage tests part of documentation Apply conventions to add a section title for Fluent DSL, Object Initializer Syntax and Handling Responses source code blocks --- .../children-aggregation-mapping.asciidoc | 2 +- .../children-aggregation-usage.asciidoc | 10 +- .../date-histogram-aggregation-usage.asciidoc | 8 +- .../date-range-aggregation-usage.asciidoc | 12 +- .../filter/filter-aggregation-usage.asciidoc | 16 +- .../filters-aggregation-usage.asciidoc | 69 ++- .../geo-distance-aggregation-usage.asciidoc | 86 ++++ .../geo-hash-grid-aggregation-usage.asciidoc | 63 +++ .../global/global-aggregation-usage.asciidoc | 68 +++ .../histogram-aggregation-usage.asciidoc | 66 +++ .../ip-range-aggregation-usage.asciidoc | 74 +++ .../missing-aggregation-usage.asciidoc | 54 ++ .../nested/nested-aggregation-usage.asciidoc | 74 +++ .../range/range-aggregation-usage.asciidoc | 81 +++ .../reverse-nested-aggregation-usage.asciidoc | 108 ++++ .../sampler-aggregation-usage.asciidoc | 75 +++ ...gnificant-terms-aggregation-usage.asciidoc | 71 +++ .../terms/terms-aggregation-usage.asciidoc | 108 ++++ .../average-aggregation-usage.asciidoc | 74 +++ .../cardinality-aggregation-usage.asciidoc | 57 +++ .../extended-stats-aggregation-usage.asciidoc | 61 +++ .../geo-bounds-aggregation-usage.asciidoc | 69 +++ .../metric/max/max-aggregation-usage.asciidoc | 52 ++ .../metric/min/min-aggregation-usage.asciidoc | 52 ++ ...ercentile-ranks-aggregation-usage.asciidoc | 81 +++ .../percentiles-aggregation-usage.asciidoc | 82 ++++ ...scripted-metric-aggregation-usage.asciidoc | 72 +++ .../stats/stats-aggregation-usage.asciidoc | 56 +++ .../metric/sum/sum-aggregation-usage.asciidoc | 52 ++ .../top-hits-aggregation-usage.asciidoc | 168 +++++++ .../value-count-aggregation-usage.asciidoc | 52 ++ .../average-bucket-aggregation-usage.asciidoc | 92 ++++ .../bucket-script-aggregation-usage.asciidoc | 140 ++++++ ...bucket-selector-aggregation-usage.asciidoc | 102 ++++ .../cumulative-sum-aggregation-usage.asciidoc | 88 ++++ .../derivative-aggregation-usage.asciidoc | 88 ++++ .../max-bucket-aggregation-usage.asciidoc | 90 ++++ .../min-bucket-aggregation-usage.asciidoc | 90 ++++ ...ng-average-ewma-aggregation-usage.asciidoc | 103 ++++ ...age-holt-linear-aggregation-usage.asciidoc | 106 ++++ ...ge-holt-winters-aggregation-usage.asciidoc | 114 +++++ ...-average-linear-aggregation-usage.asciidoc | 99 ++++ ...-average-simple-aggregation-usage.asciidoc | 102 ++++ ...al-differencing-aggregation-usage.asciidoc | 93 ++++ .../sum-bucket-aggregation-usage.asciidoc | 87 ++++ .../writing-aggregations.asciidoc | 12 +- .../connection-pooling.asciidoc | 38 +- .../date-time-providers.asciidoc | 12 +- .../keeping-track-of-nodes.asciidoc | 38 +- .../request-pipelines.asciidoc | 79 ++- .../building-blocks/transports.asciidoc | 8 +- .../exceptions/unexpected-exceptions.asciidoc | 13 +- .../unrecoverable-exceptions.asciidoc | 8 +- .../failover/falling-over.asciidoc | 11 +- .../max-retries/respects-max-retry.asciidoc | 17 +- .../pinging/first-usage.asciidoc | 12 +- .../pinging/revival.asciidoc | 4 +- .../disable-sniff-ping-per-request.asciidoc | 59 ++- .../request-timeouts-overrides.asciidoc | 10 +- .../respects-allowed-status-code.asciidoc | 4 +- .../respects-force-node.asciidoc | 4 +- .../respects-max-retry-overrides.asciidoc | 10 +- .../round-robin/round-robin.asciidoc | 21 +- .../round-robin/skip-dead-nodes.asciidoc | 52 +- .../round-robin/volatile-updates.asciidoc | 20 +- .../sniffing/on-connection-failure.asciidoc | 10 +- .../sniffing/on-stale-cluster-state.asciidoc | 12 +- .../sniffing/on-startup.asciidoc | 61 ++- .../sniffing/role-detection.asciidoc | 118 +++-- .../covariant-search-results.asciidoc | 116 +++-- .../inference/document-paths.asciidoc | 126 +++++ .../inference/field-inference.asciidoc | 460 ++++++++++++++++++ .../inference/ids-inference.asciidoc | 135 +++++ .../inference/indices-paths.asciidoc | 56 +++ .../inference/property-inference.asciidoc | 37 ++ .../inferrence/document-paths.asciidoc | 51 +- .../inferrence/field-inference.asciidoc | 113 +++-- .../inferrence/ids-inference.asciidoc | 22 +- .../inferrence/indices-paths.asciidoc | 12 +- .../inferrence/property-inference.asciidoc | 14 +- .../high-level/mapping/auto-map.asciidoc | 53 +- .../low-level/connecting.asciidoc | 153 ++++-- .../low-level/lifetimes.asciidoc | 29 +- .../low-level/post-data.asciidoc | 87 +++- .../code-standards/descriptors.asciidoc | 6 +- .../code-standards/elastic-client.asciidoc | 50 +- .../naming-conventions.asciidoc | 20 +- docs/asciidoc/code-standards/queries.asciidoc | 34 +- .../serialization/properties.asciidoc | 2 +- .../date-math/date-math-expressions.asciidoc | 24 +- .../time-unit/time-units.asciidoc | 43 +- .../document/multiple/bulk/bulk-api.asciidoc | 134 ++++- docs/asciidoc/index.asciidoc | 146 ++++-- .../query-dsl/bool-dsl/bool-dsl.asciidoc | 20 +- .../compound/and/and-query-usage.asciidoc | 6 +- .../geo/distance/distance-units.asciidoc | 26 +- .../search/suggesters/suggest-api.asciidoc | 226 +++++++++ .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 87 +++- .../Documentation/Blocks/CodeBlock.cs | 4 +- .../Files/CSharpDocumentationFile.cs | 31 +- src/CodeGeneration/Nest.Litterateur/LitUp.cs | 2 +- .../Nest.Litterateur/StringExtensions.cs | 8 +- .../Walkers/CodeWithDocumentationWalker.cs | 18 +- .../Walkers/DocumentationFileWalker.cs | 60 ++- .../FiltersAggregationUsageTests.doc.cs | 17 +- ...> GeoDistanceAggregationUsageTests.doc.cs} | 0 ...> GeoHashGridAggregationUsageTests.doc.cs} | 0 ....cs => GlobalAggregationUsageTests.doc.cs} | 0 ... => HistogramAggregationUsageTests.doc.cs} | 0 ...cs => IpRangeAggregationUsageTests.doc.cs} | 2 +- ...cs => MissingAggregationUsageTests.doc.cs} | 0 ....cs => NestedAggregationUsageTests.doc.cs} | 0 ...s.cs => RangeAggregationUsageTests.doc.cs} | 2 +- ...ReverseNestedAggregationUsageTests.doc.cs} | 2 +- ...cs => SamplerAggregationUsageTests.doc.cs} | 0 ...nificantTermsAggregationUsageTests.doc.cs} | 2 +- ...s.cs => TermsAggregationUsageTests.doc.cs} | 2 +- ...cs => AverageAggregationUsageTests.doc.cs} | 5 +- ...> CardinalityAggregationUsageTests.doc.cs} | 2 +- ...ExtendedStatsAggregationUsageTests.doc.cs} | 2 +- ... => GeoBoundsAggregationUsageTests.doc.cs} | 2 +- ...sts.cs => MaxAggregationUsageTests.doc.cs} | 2 +- ...sts.cs => MinAggregationUsageTests.doc.cs} | 2 +- ...rcentileRanksAggregationUsageTests.doc.cs} | 2 +- ...> PercentilesAggregationUsageTests.doc.cs} | 2 +- ...criptedMetricAggregationUsageTests.doc.cs} | 0 ...s.cs => StatsAggregationUsageTests.doc.cs} | 2 +- ...sts.cs => SumAggregationUsageTests.doc.cs} | 2 +- ...cs => TopHitsAggregationUsageTests.doc.cs} | 6 +- ...=> ValueCountAggregationUsageTests.doc.cs} | 2 +- ...AverageBucketAggregationUsageTests.doc.cs} | 0 ... BucketScriptAggregationUsageTests.doc.cs} | 0 ...ucketSelectorAggregationUsageTests.doc.cs} | 0 ...CumulativeSumAggregationUsageTests.doc.cs} | 0 ...=> DerivativeAggregationUsageTests.doc.cs} | 0 ... => MaxBucketAggregationUsageTests.doc.cs} | 0 ... => MinBucketAggregationUsageTests.doc.cs} | 0 ...ngAverageEwmaAggregationUsageTests.doc.cs} | 0 ...ageHoltLinearAggregationUsageTests.doc.cs} | 0 ...geHoltWintersAggregationUsageTests.doc.cs} | 0 ...AverageLinearAggregationUsageTests.doc.cs} | 0 ...AverageSimpleAggregationUsageTests.doc.cs} | 0 ...lDifferencingAggregationUsageTests.doc.cs} | 0 ... => SumBucketAggregationUsageTests.doc.cs} | 0 .../Aggregations/WritingAggregations.doc.cs | 3 +- .../BuildingBlocks/ConnectionPooling.Doc.cs | 3 +- .../BuildingBlocks/DateTimeProviders.Doc.cs | 3 +- .../BuildingBlocks/KeepingTrackOfNodes.Doc.cs | 3 +- .../BuildingBlocks/RequestPipelines.doc.cs | 3 +- .../BuildingBlocks/Transports.Doc.cs | 3 +- .../Pinging/FirstUsage.doc.cs | 3 +- .../ConnectionPooling/Pinging/Revival.doc.cs | 3 +- .../DisableSniffPingPerRequest.doc.cs | 41 +- .../RequestTimeoutsOverrides.doc.cs | 3 +- .../RespectsAllowedStatusCode.doc.cs | 3 +- .../RequestOverrides/RespectsForceNode.doc.cs | 3 +- .../RespectsMaxRetryOverrides.doc.cs | 3 +- .../RoundRobin/RoundRobin.doc.cs | 9 +- .../Sniffing/OnConnectionFailure.doc.cs | 3 +- .../Sniffing/OnStaleClusterState.doc.cs | 3 +- .../Sniffing/OnStartup.doc.cs | 3 +- .../Sniffing/RoleDetection.doc.cs | 7 +- .../CovariantSearchResults.doc.cs | 93 ++-- .../DocumentPaths.doc.cs | 21 +- .../FeaturesInference.cs | 17 +- .../FieldInference.doc.cs | 11 +- .../IdsInference.doc.cs | 7 +- .../IndicesPaths.doc.cs | 3 +- .../PropertyInference.doc.cs | 4 +- .../HighLevel/Mapping/AutoMap.doc.cs | 3 +- .../ClientConcepts/LowLevel/Connecting.doc.cs | 113 ++--- .../ClientConcepts/LowLevel/Lifetimes.doc.cs | 20 +- .../ClientConcepts/LowLevel/PostData.doc.cs | 35 +- .../DateMath/DateMathExpressions.doc.cs | 4 +- .../Multiple/Bulk/BulkApiTests.doc.cs | 54 +- .../DeleteByQuery/DeleteByQueryApiTests.cs | 15 +- ...ggestApiTest.cs => SuggestApiTests.doc.cs} | 48 +- src/lib/dnx451/AsciiDoc.dll | Bin 69120 -> 69632 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 241152 -> 241152 bytes 179 files changed, 6137 insertions(+), 882 deletions(-) create mode 100644 docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc create mode 100644 docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc create mode 100644 docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc create mode 100644 docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc create mode 100644 docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc create mode 100644 docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc create mode 100644 docs/asciidoc/search/suggesters/suggest-api.asciidoc rename src/Tests/Aggregations/Bucket/GeoDistance/{GeoDistanceAggregationUsageTests.cs => GeoDistanceAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/GeoHashGrid/{GeoHashGridAggregationUsageTests.cs => GeoHashGridAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/Global/{GlobalAggregationUsageTests.cs => GlobalAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/Histogram/{HistogramAggregationUsageTests.cs => HistogramAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/IpRange/{IpRangeAggregationUsageTests.cs => IpRangeAggregationUsageTests.doc.cs} (96%) rename src/Tests/Aggregations/Bucket/Missing/{MissingAggregationUsageTests.cs => MissingAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/Nested/{NestedAggregationUsageTests.cs => NestedAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/Range/{RangeAggregationUsageTests.cs => RangeAggregationUsageTests.doc.cs} (97%) rename src/Tests/Aggregations/Bucket/ReverseNested/{ReverseNestedAggregationUsageTests.cs => ReverseNestedAggregationUsageTests.doc.cs} (98%) rename src/Tests/Aggregations/Bucket/Sampler/{SamplerAggregationUsageTests.cs => SamplerAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Bucket/SignificantTerms/{SignificantTermsAggregationUsageTests.cs => SignificantTermsAggregationUsageTests.doc.cs} (97%) rename src/Tests/Aggregations/Bucket/Terms/{TermsAggregationUsageTests.cs => TermsAggregationUsageTests.doc.cs} (98%) rename src/Tests/Aggregations/Metric/Average/{AverageAggregationUsageTests.cs => AverageAggregationUsageTests.doc.cs} (95%) rename src/Tests/Aggregations/Metric/Cardinality/{CardinalityAggregationUsageTests.cs => CardinalityAggregationUsageTests.doc.cs} (96%) rename src/Tests/Aggregations/Metric/ExtendedStats/{ExtendedStatsAggregationUsageTests.cs => ExtendedStatsAggregationUsageTests.doc.cs} (96%) rename src/Tests/Aggregations/Metric/GeoBounds/{GeoBoundsAggregationUsageTests.cs => GeoBoundsAggregationUsageTests.doc.cs} (97%) rename src/Tests/Aggregations/Metric/Max/{MaxAggregationUsageTests.cs => MaxAggregationUsageTests.doc.cs} (95%) rename src/Tests/Aggregations/Metric/Min/{MinAggregationUsageTests.cs => MinAggregationUsageTests.doc.cs} (95%) rename src/Tests/Aggregations/Metric/PercentileRanks/{PercentileRanksAggregationUsageTests.cs => PercentileRanksAggregationUsageTests.doc.cs} (97%) rename src/Tests/Aggregations/Metric/Percentiles/{PercentilesAggregationUsageTests.cs => PercentilesAggregationUsageTests.doc.cs} (97%) rename src/Tests/Aggregations/Metric/ScriptedMetric/{ScriptedMetricAggregationUsageTests.cs => ScriptedMetricAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Metric/Stats/{StatsAggregationUsageTests.cs => StatsAggregationUsageTests.doc.cs} (96%) rename src/Tests/Aggregations/Metric/Sum/{SumAggregationUsageTests.cs => SumAggregationUsageTests.doc.cs} (95%) rename src/Tests/Aggregations/Metric/TopHits/{TopHitsAggregationUsageTests.cs => TopHitsAggregationUsageTests.doc.cs} (96%) rename src/Tests/Aggregations/Metric/ValueCount/{ValueCountAggregationUsageTests.cs => ValueCountAggregationUsageTests.doc.cs} (95%) rename src/Tests/Aggregations/Pipeline/AverageBucket/{AverageBucketAggregationUsageTests.cs => AverageBucketAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/BucketScript/{BucketScriptAggregationUsageTests.cs => BucketScriptAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/BucketSelector/{BucketSelectorAggregationUsageTests.cs => BucketSelectorAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/CumulativeSum/{CumulativeSumAggregationUsageTests.cs => CumulativeSumAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/Derivative/{DerivativeAggregationUsageTests.cs => DerivativeAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MaxBucket/{MaxBucketAggregationUsageTests.cs => MaxBucketAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MinBucket/{MinBucketAggregationUsageTests.cs => MinBucketAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageEwmaAggregationUsageTests.cs => MovingAverageEwmaAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageHoltLinearAggregationUsageTests.cs => MovingAverageHoltLinearAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageHoltWintersAggregationUsageTests.cs => MovingAverageHoltWintersAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageLinearAggregationUsageTests.cs => MovingAverageLinearAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageSimpleAggregationUsageTests.cs => MovingAverageSimpleAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/SerialDifferencing/{SerialDifferencingAggregationUsageTests.cs => SerialDifferencingAggregationUsageTests.doc.cs} (100%) rename src/Tests/Aggregations/Pipeline/SumBucket/{SumBucketAggregationUsageTests.cs => SumBucketAggregationUsageTests.doc.cs} (100%) rename src/Tests/ClientConcepts/HighLevel/{Inferrence => Inference}/DocumentPaths.doc.cs (77%) rename src/Tests/ClientConcepts/HighLevel/{Inferrence => Inference}/FeaturesInference.cs (51%) rename src/Tests/ClientConcepts/HighLevel/{Inferrence => Inference}/FieldInference.doc.cs (97%) rename src/Tests/ClientConcepts/HighLevel/{Inferrence => Inference}/IdsInference.doc.cs (95%) rename src/Tests/ClientConcepts/HighLevel/{Inferrence => Inference}/IndicesPaths.doc.cs (97%) rename src/Tests/ClientConcepts/HighLevel/{Inferrence => Inference}/PropertyInference.doc.cs (91%) rename src/Tests/Search/Suggesters/{SuggestApiTest.cs => SuggestApiTests.doc.cs} (94%) diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index 71da482add2..ac427837537 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -11,7 +11,7 @@ To use the child aggregation you have to make sure index with two mapped types, `project` and `commitactivity` and we add a `_parent` mapping from `commitactivity` to `parent` -[source,csharp] +[source,csharp,method-name="mappingexample"] ---- var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c .Mappings(map => map diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index 1b72e54cd90..a82e206a0db 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -11,7 +11,7 @@ buckets on child documents. Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -39,7 +39,9 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation Fluent DSL Example -[source,csharp] +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -54,7 +56,9 @@ s => s Object Initializer Syntax Example -[source,csharp] +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] ---- new SearchRequest { diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index 112bbc9d509..a13335b2190 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -16,7 +16,7 @@ as part of the format value. Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -58,7 +58,7 @@ Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregati === Fluent DSL Example -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Size(0) @@ -85,7 +85,7 @@ s => s === Object Initializer Syntax Example -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -120,7 +120,7 @@ new SearchRequest Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] -[source,csharp] +[source,csharp,method-name="expectresponse"] ---- response.IsValid.Should().BeTrue(); diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index de3ef457057..6fc4bc00e1c 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -16,7 +16,7 @@ IMPORTANT: this aggregation includes the `from` value and excludes the `to` valu Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -51,7 +51,7 @@ Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.h === Fluent DSL Example -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -71,7 +71,7 @@ s => s === Object Initializer Syntax Example -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -95,7 +95,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp] +[source,csharp,method-name="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -106,7 +106,9 @@ dateHistogram.Buckets.Should().NotBeNull(); We specified three ranges so we expect to have three of them in the response -[source,csharp] +=== Handling Responses + +[source,csharp,method-name="expectresponse"] ---- dateHistogram.Buckets.Count.Should().Be(3); diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index b25edef30fc..37d423873dd 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -11,7 +11,7 @@ Often this will be used to narrow down the current aggregation context to a spec Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -38,7 +38,7 @@ Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html === Fluent DSL Example -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -53,7 +53,7 @@ s => s === Object Initializer Syntax Example -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -71,7 +71,7 @@ new SearchRequest Using the `.Aggs` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp] +[source,csharp,method-name="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -88,7 +88,7 @@ tags.Buckets.Should().NotBeEmpty(); When the collection of filters is empty or all are conditionless, NEST will serialize them to an empty object. -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -102,7 +102,7 @@ to an empty object. === Fluent DSL Example -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -118,7 +118,7 @@ s => s === Object Initializer Syntax Example -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -134,7 +134,7 @@ new SearchRequest === Handling Response -[source,csharp] +[source,csharp,method-name="expectresponse"] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filter("empty_filter").DocCount.Should().BeGreaterThan(0); diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index 8ad1dd26a2f..a3a47250bcd 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -14,7 +14,7 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation == Named filters -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -59,9 +59,9 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation } ---- -=== Fluent DSL Example +=== Fluent DSL Example -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -80,9 +80,9 @@ s => s ) ---- -Object Initializer Example +=== Object Initializer Syntax Example -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -107,7 +107,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp] +[source,csharp,method-name="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -129,7 +129,7 @@ namedResult.DocCount.Should().Be(0); == Anonymous filters -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -173,9 +173,9 @@ namedResult.DocCount.Should().Be(0); } ---- -=== Fluent DSL Example +=== Fluent DSL Example -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -193,9 +193,9 @@ s => s ) ---- -=== Object Initializer Syntax Example +=== Object Initializer Syntax Example -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -204,20 +204,25 @@ new SearchRequest OtherBucket = true, Filters = new List { - Query.Term(p=>p.State, StateOfBeing.BellyUp) , - Query.Term(p=>p.State, StateOfBeing.Stable) , - Query.Term(p=>p.State, StateOfBeing.VeryActive) + Query.Term(p=>p.State, StateOfBeing.BellyUp) , + Query.Term(p=>p.State, StateOfBeing.Stable) , + Query.Term(p=>p.State, StateOfBeing.VeryActive) }, Aggregations = - new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } + new TermsAggregation("project_tags") + { + Field = Field(p => p.CuratedTags.First().Name) + } } } ---- +=== Handling Responses + Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp] +[source,csharp,method-name="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -231,7 +236,7 @@ results.Last().DocCount.Should().Be(0); == Empty Filters -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -245,7 +250,9 @@ results.Last().DocCount.Should().Be(0); } ---- -[source,csharp] +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -253,7 +260,12 @@ s => s .AnonymousFilters() ) ) +---- +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- new SearchRequest { Aggregations = new FiltersAggregation("empty_filters") @@ -261,14 +273,19 @@ new SearchRequest Filters = new List() } } +---- + +=== Handling Responses +[source,csharp,method-name="expectresponse"] +---- response.IsValid.Should().BeTrue(); response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); ---- == Conditionless Filters -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -282,7 +299,9 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); } ---- -[source,csharp] +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -292,7 +311,12 @@ s => s ) ) ) +---- +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- new SearchRequest { Aggregations = new FiltersAggregation("conditionless_filters") @@ -303,7 +327,12 @@ new SearchRequest } } } +---- + +=== Handling Responses +[source,csharp,method-name="expectresponse"] +---- response.IsValid.Should().BeTrue(); response.Aggs.Filters("conditionless_filters").Buckets.Should().BeEmpty(); ---- diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc new file mode 100644 index 00000000000..6753dd411e8 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -0,0 +1,86 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "rings_around_amsterdam": { + "geo_distance": { + "field": "location", + "origin": { + "lat": 52.376, + "lon": 4.894 + }, + "ranges": [ + { + "to": 100.0 + }, + { + "from": 100.0, + "to": 300.0 + }, + { + "from": 300.0 + } + ] + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .GeoDistance("rings_around_amsterdam", g => g + .Field(p => p.Location) + .Origin(52.376, 4.894) + .Ranges( + r => r.To(100), + r => r.From(100).To(300), + r => r.From(300) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new GeoDistanceAggregation("rings_around_amsterdam") + { + Field = Field((Project p) => p.Location), + Origin = "52.376, 4.894", + Ranges = new List + { + new Nest.Range { To = 100 }, + new Nest.Range { From = 100, To = 300 }, + new Nest.Range { From = 300 } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var ringsAroundAmsterdam = response.Aggs.GeoDistance("rings_around_amsterdam"); +ringsAroundAmsterdam.Should().NotBeNull(); +ringsAroundAmsterdam.Buckets.Where(r => r.Key == "*-100.0").FirstOrDefault().Should().NotBeNull(); +ringsAroundAmsterdam.Buckets.Where(r => r.Key == "100.0-300.0").FirstOrDefault().Should().NotBeNull(); +ringsAroundAmsterdam.Buckets.Where(r => r.Key == "300.0-*").FirstOrDefault().Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc new file mode 100644 index 00000000000..8362425ef93 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -0,0 +1,63 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "my_geohash_grid": { + "geohash_grid": { + "field": "location", + "precision": 3, + "size": 1000, + "shard_size": 100 + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .GeoHash("my_geohash_grid", g => g + .Field(p => p.Location) + .GeoHashPrecision(GeoHashPrecision.Precision3) + .Size(1000) + .ShardSize(100) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new GeoHashGridAggregation("my_geohash_grid") + { + Field = Field(p => p.Location), + Precision = GeoHashPrecision.Precision3, + Size = 1000, + ShardSize = 100 + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var myGeoHashGrid = response.Aggs.GeoHash("my_geohash_grid"); +myGeoHashGrid.Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc new file mode 100644 index 00000000000..90615ec164e --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -0,0 +1,68 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "all_projects": { + "global": {}, + "aggs": { + "names": { + "terms": { + "field": "name" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Global("all_projects", g => g + .Aggregations(aa => aa + .Terms("names", t => t + .Field(p => p.Name) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new GlobalAggregation("all_projects") + { + Aggregations = new TermsAggregation("names") + { + Field = Field(p => p.Name) + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var allProjects = response.Aggs.Global("all_projects"); +allProjects.Should().NotBeNull(); +var names = allProjects.Terms("names"); +names.Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc new file mode 100644 index 00000000000..756085c889d --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -0,0 +1,66 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits": { + "histogram": { + "field": "numberOfCommits", + "interval": 100.0, + "missing": 0.0, + "order": { + "_key": "desc" + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Histogram("commits", h => h + .Field(p => p.NumberOfCommits) + .Interval(100) + .Missing(0) + .Order(HistogramOrder.KeyDescending) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new HistogramAggregation("commits") + { + Field = Field(p => p.NumberOfCommits), + Interval = 100, + Missing = 0, + Order = HistogramOrder.KeyDescending + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commits = response.Aggs.Histogram("commits"); +commits.Should().NotBeNull(); +item.DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc new file mode 100644 index 00000000000..d1ce3173006 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -0,0 +1,74 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "ip_ranges": { + "ip_range": { + "field": "leadDeveloper.iPAddress", + "ranges": [ + { + "to": "10.0.0.5" + }, + { + "from": "10.0.0.5" + } + ] + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .IpRange("ip_ranges", ip => ip + .Field(p => p.LeadDeveloper.IPAddress) + .Ranges( + r => r.To("10.0.0.5"), + r => r.From("10.0.0.5") + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new IpRangeAggregation("ip_ranges") + { + Field = Field((Project p) => p.LeadDeveloper.IPAddress), + Ranges = new List + { + new Nest.IpRange { To = "10.0.0.5" }, + new Nest.IpRange { From = "10.0.0.5" } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var ipRanges = response.Aggs.IpRange("ip_ranges"); +ipRanges.Should().NotBeNull(); +ipRanges.Buckets.Should().NotBeNull(); +ipRanges.Buckets.Count.Should().BeGreaterThan(0); +range.DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc new file mode 100644 index 00000000000..a6f8c14c041 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -0,0 +1,54 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "projects_without_a_description": { + "missing": { + "field": "description" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Missing("projects_without_a_description", m => m + .Field(p => p.Description) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new MissingAggregation("projects_without_a_description") + { + Field = Field(p => p.Description) + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsWithoutDesc = response.Aggs.Missing("projects_without_a_description"); +projectsWithoutDesc.Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc new file mode 100644 index 00000000000..a79c6c84a50 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -0,0 +1,74 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "tags": { + "nested": { + "path": "tags" + }, + "aggs": { + "tag_names": { + "terms": { + "field": "tags.name" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Nested("tags", n => n + .Path(p => p.Tags) + .Aggregations(aa => aa + .Terms("tag_names", t => t + .Field(p => p.Tags.Suffix("name")) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new NestedAggregation("tags") + { + Path = "tags", + Aggregations = new TermsAggregation("tag_names") + { + Field = "tags.name" + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var tags = response.Aggs.Nested("tags"); +tags.Should().NotBeNull(); +var tagNames = tags.Terms("tag_names"); +tagNames.Should().NotBeNull(); +item.Key.Should().NotBeNullOrEmpty(); +item.DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc new file mode 100644 index 00000000000..1dcdfb7cd71 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -0,0 +1,81 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_ranges": { + "range": { + "field": "numberOfCommits", + "ranges": [ + { + "to": 100.0 + }, + { + "from": 100.0, + "to": 500.0 + }, + { + "from": 500.0 + } + ] + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Range("commit_ranges", ra => ra + .Field(p => p.NumberOfCommits) + .Ranges( + r => r.To(100), + r => r.From(100).To(500), + r => r.From(500) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new RangeAggregation("commit_ranges") + { + Field = Field(p => p.NumberOfCommits), + Ranges = new List + { + { new Nest.Range { To = 100 } }, + { new Nest.Range { From = 100, To = 500 } }, + { new Nest.Range { From = 500 } } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitRanges = response.Aggs.Range("commit_ranges"); +commitRanges.Should().NotBeNull(); +commitRanges.Buckets.Count.Should().Be(3); +commitRanges.Buckets.Where(r => r.Key == "*-100.0").FirstOrDefault().Should().NotBeNull(); +commitRanges.Buckets.Where(r => r.Key == "100.0-500.0").FirstOrDefault().Should().NotBeNull(); +commitRanges.Buckets.Where(r => r.Key == "500.0-*").FirstOrDefault().Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc new file mode 100644 index 00000000000..c1867778c0f --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -0,0 +1,108 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "tags": { + "nested": { + "path": "tags" + }, + "aggs": { + "tag_names": { + "terms": { + "field": "tags.name" + }, + "aggs": { + "tags_to_project": { + "reverse_nested": {}, + "aggs": { + "top_projects_per_tag": { + "terms": { + "field": "name" + } + } + } + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Nested("tags", n => n + .Path(p => p.Tags) + .Aggregations(aa => aa + .Terms("tag_names", t => t + .Field(p => p.Tags.Suffix("name")) + .Aggregations(aaa => aaa + .ReverseNested("tags_to_project", r => r + .Aggregations(aaaa => aaaa + .Terms("top_projects_per_tag", tt => tt + .Field(p => p.Name) + ) + ) + ) + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new NestedAggregation("tags") + { + Path = "tags", + Aggregations = new TermsAggregation("tag_names") + { + Field = "tags.name", + Aggregations = new ReverseNestedAggregation("tags_to_project") + { + Aggregations = new TermsAggregation("top_projects_per_tag") + { + Field = Field(p => p.Name) + } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var tags = response.Aggs.Nested("tags"); +tags.Should().NotBeNull(); +var tagNames = tags.Terms("tag_names"); +tagNames.Should().NotBeNull(); +tagName.Key.Should().NotBeNullOrEmpty(); +tagName.DocCount.Should().BeGreaterThan(0); +var tagsToProjects = tagName.ReverseNested("tags_to_project"); +tagsToProjects.Should().NotBeNull(); +var topProjectsPerTag = tagsToProjects.Terms("top_projects_per_tag"); +topProjectsPerTag.Should().NotBeNull(); +topProject.Key.Should().NotBeNullOrEmpty(); +topProject.DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc new file mode 100644 index 00000000000..b34082451c6 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -0,0 +1,75 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "sample": { + "sampler": { + "shard_size": 200, + "field": "name" + }, + "aggs": { + "significant_names": { + "significant_terms": { + "field": "name" + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(aggs => aggs + .Sampler("sample", sm => sm + .ShardSize(200) + .Field(p => p.Name) + .Aggregations(aa => aa + .SignificantTerms("significant_names", st => st + .Field(p => p.Name) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new SamplerAggregation("sample") + { + ShardSize = 200, + Field = "name", + Aggregations = new SignificantTermsAggregation("significant_names") + { + Field = "name" + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var sample = response.Aggs.Sampler("sample"); +sample.Should().NotBeNull(); +var sigTags = sample.SignificantTerms("significant_names"); +sigTags.Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc new file mode 100644 index 00000000000..1dda79e617c --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -0,0 +1,71 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "significant_names": { + "significant_terms": { + "field": "name", + "min_doc_count": 10, + "mutual_information": { + "background_is_superset": true, + "include_negatives": true + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .SignificantTerms("significant_names", st => st + .Field(p => p.Name) + .MinimumDocumentCount(10) + .MutualInformation(mi => mi + .BackgroundIsSuperSet() + .IncludeNegatives() + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new SignificantTermsAggregation("significant_names") + { + Field = Field(p => p.Name), + MinimumDocumentCount = 10, + MutualInformation = new MutualInformationHeuristic + { + BackgroundIsSuperSet = true, + IncludeNegatives = true + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var sigNames = response.Aggs.SignificantTerms("significant_names"); +sigNames.Should().NotBeNull(); +sigNames.DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc new file mode 100644 index 00000000000..7283841fda0 --- /dev/null +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -0,0 +1,108 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "states": { + "meta": { + "foo": "bar" + }, + "terms": { + "field": "state", + "min_doc_count": 2, + "size": 5, + "shard_size": 100, + "show_term_doc_error_count": true, + "execution_hint": "map", + "missing": "n/a", + "script": { + "inline": "'State of Being: '+_value" + }, + "order": [ + { + "_term": "asc" + }, + { + "_count": "desc" + } + ] + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Terms("states", st => st + .Field(p => p.State) + .MinimumDocumentCount(2) + .Size(5) + .ShardSize(100) + .ShowTermDocumentCountError() + .ExecutionHint(TermsAggregationExecutionHint.Map) + .Missing("n/a") + .Script("'State of Being: '+_value") + .Order(TermsOrder.TermAscending) + .Order(TermsOrder.CountDescending) + .Meta(m => m + .Add("foo", "bar") + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new TermsAggregation("states") + { + Field = Field(p => p.State), + MinimumDocumentCount = 2, + Size = 5, + ShardSize = 100, + ShowTermDocumentCountError = true, + ExecutionHint = TermsAggregationExecutionHint.Map, + Missing = "n/a", + Script = new InlineScript("'State of Being: '+_value"), + Order = new List + { + TermsOrder.TermAscending, + TermsOrder.CountDescending + }, + Meta = new Dictionary + { + { "foo", "bar" } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var states = response.Aggs.Terms("states"); +states.Should().NotBeNull(); +states.DocCountErrorUpperBound.Should().HaveValue(); +states.SumOtherDocCount.Should().HaveValue(); +item.Key.Should().NotBeNullOrEmpty(); +item.DocCount.Should().BeGreaterOrEqualTo(1); +states.Meta.Should().NotBeNull().And.HaveCount(1); +states.Meta["foo"].Should().Be("bar"); +---- + diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc new file mode 100644 index 00000000000..d1a34806415 --- /dev/null +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -0,0 +1,74 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "average_commits": { + "meta": { + "foo": "bar" + }, + "avg": { + "field": "numberOfCommits", + "missing": 10.0, + "script": { + "inline": "_value * 1.2" + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Average("average_commits", avg => avg + .Meta(m => m + .Add("foo", "bar") + ) + .Field(p => p.NumberOfCommits) + .Missing(10) + .Script("_value * 1.2") + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new AverageAggregation("average_commits", Field(p => p.NumberOfCommits)) + { + Meta = new Dictionary + { + { "foo", "bar" } + }, + Missing = 10, + Script = new InlineScript("_value * 1.2") + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitsAvg = response.Aggs.Average("average_commits"); +commitsAvg.Should().NotBeNull(); +commitsAvg.Value.Should().BeGreaterThan(0); +commitsAvg.Meta.Should().NotBeNull().And.HaveCount(1); +commitsAvg.Meta["foo"].Should().Be("bar"); +---- + diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc new file mode 100644 index 00000000000..7ec6a3c505d --- /dev/null +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -0,0 +1,57 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "state_count": { + "cardinality": { + "field": "state", + "precision_threshold": 100 + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Cardinality("state_count", c => c + .Field(p => p.State) + .PrecisionThreshold(100) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new CardinalityAggregation("state_count", Field(p => p.State)) + { + PrecisionThreshold = 100 + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectCount = response.Aggs.Cardinality("state_count"); +projectCount.Should().NotBeNull(); +projectCount.Value.Should().Be(3); +---- + diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc new file mode 100644 index 00000000000..62308fdeeef --- /dev/null +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -0,0 +1,61 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_stats": { + "extended_stats": { + "field": "numberOfCommits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .ExtendedStats("commit_stats", es => es + .Field(p => p.NumberOfCommits) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new ExtendedStatsAggregation("commit_stats", Field(p => p.NumberOfCommits)) +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitStats = response.Aggs.ExtendedStats("commit_stats"); +commitStats.Should().NotBeNull(); +commitStats.Average.Should().BeGreaterThan(0); +commitStats.Max.Should().BeGreaterThan(0); +commitStats.Min.Should().BeGreaterThan(0); +commitStats.Count.Should().BeGreaterThan(0); +commitStats.Sum.Should().BeGreaterThan(0); +commitStats.SumOfSquares.Should().BeGreaterThan(0); +commitStats.StdDeviation.Should().BeGreaterThan(0); +commitStats.StdDeviationBounds.Should().NotBeNull(); +commitStats.StdDeviationBounds.Upper.Should().BeGreaterThan(0); +commitStats.StdDeviationBounds.Lower.Should().NotBe(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc new file mode 100644 index 00000000000..fc20f4f0ea7 --- /dev/null +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -0,0 +1,69 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "viewport": { + "geo_bounds": { + "field": "location", + "wrap_longitude": true + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .GeoBounds("viewport", gb => gb + .Field(p => p.Location) + .WrapLongitude(true) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new GeoBoundsAggregation("viewport", Field(p => p.Location)) + { + WrapLongitude = true + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var viewport = response.Aggs.GeoBounds("viewport"); +viewport.Should().NotBeNull(); +viewport.Bounds.Should().NotBeNull(); +var bottomRight = viewport.Bounds.BottomRight; +bottomRight.Should().NotBeNull(); +bottomRight.Lat.Should().HaveValue(); +GeoLocation.IsValidLatitude(bottomRight.Lat.Value).Should().BeTrue(); +bottomRight.Lon.Should().HaveValue(); +GeoLocation.IsValidLongitude(bottomRight.Lon.Value).Should().BeTrue(); +var topLeft = viewport.Bounds.TopLeft; +topLeft.Should().NotBeNull(); +topLeft.Lat.Should().HaveValue(); +GeoLocation.IsValidLatitude(topLeft.Lat.Value).Should().BeTrue(); +topLeft.Lon.Should().HaveValue(); +GeoLocation.IsValidLongitude(topLeft.Lon.Value).Should().BeTrue(); +---- + diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc new file mode 100644 index 00000000000..93b7f4e11ba --- /dev/null +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "max_commits": { + "max": { + "field": "numberOfCommits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Max("max_commits", m => m + .Field(p => p.NumberOfCommits) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new MaxAggregation("max_commits", Field(p => p.NumberOfCommits)) +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var max = response.Aggs.Max("max_commits"); +max.Should().NotBeNull(); +max.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc new file mode 100644 index 00000000000..fde7d62514a --- /dev/null +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "min_commits": { + "min": { + "field": "numberOfCommits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Min("min_commits", m => m + .Field(p => p.NumberOfCommits) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new MinAggregation("min_commits", Field(p => p.NumberOfCommits)) +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var min = response.Aggs.Max("min_commits"); +min.Should().NotBeNull(); +min.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc new file mode 100644 index 00000000000..d46b028356b --- /dev/null +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -0,0 +1,81 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits_outlier": { + "percentile_ranks": { + "field": "numberOfCommits", + "values": [ + 15.0, + 30.0 + ], + "tdigest": { + "compression": 200.0 + }, + "script": { + "inline": "doc['numberOfCommits'].value * 1.2" + }, + "missing": 0.0 + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .PercentileRanks("commits_outlier", pr => pr + .Field(p => p.NumberOfCommits) + .Values(15, 30) + .Method(m => m + .TDigest(td => td + .Compression(200) + ) + ) + .Script("doc['numberOfCommits'].value * 1.2") + .Missing(0) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new PercentileRanksAggregation("commits_outlier", Field(p => p.NumberOfCommits)) + { + Values = new List { 15, 30 }, + Method = new TDigestMethod + { + Compression = 200 + }, + Script = (InlineScript)"doc['numberOfCommits'].value * 1.2", + Missing = 0 + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitsOutlier = response.Aggs.PercentileRanks("commits_outlier"); +commitsOutlier.Should().NotBeNull(); +commitsOutlier.Items.Should().NotBeNullOrEmpty(); +item.Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc new file mode 100644 index 00000000000..302697ffd7d --- /dev/null +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -0,0 +1,82 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits_outlier": { + "percentiles": { + "field": "numberOfCommits", + "percents": [ + 95.0, + 99.0, + 99.9 + ], + "hdr": { + "number_of_significant_value_digits": 3 + }, + "script": { + "inline": "doc['numberOfCommits'].value * 1.2" + }, + "missing": 0.0 + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Percentiles("commits_outlier", pr => pr + .Field(p => p.NumberOfCommits) + .Percents(95, 99, 99.9) + .Method(m => m + .HDRHistogram(hdr => hdr + .NumberOfSignificantValueDigits(3) + ) + ) + .Script("doc['numberOfCommits'].value * 1.2") + .Missing(0) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new PercentilesAggregation("commits_outlier", Field(p => p.NumberOfCommits)) + { + Percents = new[] { 95, 99, 99.9 }, + Method = new HDRHistogramMethod + { + NumberOfSignificantValueDigits = 3 + }, + Script = new InlineScript("doc['numberOfCommits'].value * 1.2"), + Missing = 0 + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitsOutlier = response.Aggs.Percentiles("commits_outlier"); +commitsOutlier.Should().NotBeNull(); +commitsOutlier.Items.Should().NotBeNullOrEmpty(); +item.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc new file mode 100644 index 00000000000..01a6797e521 --- /dev/null +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -0,0 +1,72 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "sum_the_hard_way": { + "scripted_metric": { + "init_script": { + "inline": "_agg['commits'] = []" + }, + "map_script": { + "inline": "if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }" + }, + "combine_script": { + "inline": "sum = 0; for (c in _agg.commits) { sum += c }; return sum" + }, + "reduce_script": { + "inline": "sum = 0; for (a in _aggs) { sum += a }; return sum" + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .ScriptedMetric("sum_the_hard_way", sm => sm + .InitScript("_agg['commits'] = []") + .MapScript("if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }") + .CombineScript("sum = 0; for (c in _agg.commits) { sum += c }; return sum") + .ReduceScript("sum = 0; for (a in _aggs) { sum += a }; return sum") + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new ScriptedMetricAggregation("sum_the_hard_way") + { + InitScript = new InlineScript("_agg['commits'] = []"), + MapScript = new InlineScript("if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }"), + CombineScript = new InlineScript("sum = 0; for (c in _agg.commits) { sum += c }; return sum"), + ReduceScript = new InlineScript("sum = 0; for (a in _aggs) { sum += a }; return sum") + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var sumTheHardWay = response.Aggs.ScriptedMetric("sum_the_hard_way"); +sumTheHardWay.Should().NotBeNull(); +sumTheHardWay.Value().Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc new file mode 100644 index 00000000000..b99ccf3f998 --- /dev/null +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -0,0 +1,56 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_stats": { + "stats": { + "field": "numberOfCommits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Stats("commit_stats", st => st + .Field(p => p.NumberOfCommits) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new StatsAggregation("commit_stats", Field(p => p.NumberOfCommits)) +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitStats = response.Aggs.Stats("commit_stats"); +commitStats.Should().NotBeNull(); +commitStats.Average.Should().BeGreaterThan(0); +commitStats.Max.Should().BeGreaterThan(0); +commitStats.Min.Should().BeGreaterThan(0); +commitStats.Count.Should().BeGreaterThan(0); +commitStats.Sum.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc new file mode 100644 index 00000000000..a2b19e6876e --- /dev/null +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits_sum": { + "sum": { + "field": "numberOfCommits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Sum("commits_sum", sm => sm + .Field(p => p.NumberOfCommits) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new SumAggregation("commits_sum", Field(p => p.NumberOfCommits)) +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitsSum = response.Aggs.Sum("commits_sum"); +commitsSum.Should().NotBeNull(); +commitsSum.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc new file mode 100644 index 00000000000..fab343e98ec --- /dev/null +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -0,0 +1,168 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "states": { + "terms": { + "field": "state" + }, + "aggs": { + "top_state_hits": { + "top_hits": { + "sort": [ + { + "startedOn": { + "order": "desc" + } + } + ], + "_source": { + "include": [ + "name", + "startedOn" + ] + }, + "size": 1, + "version": true, + "explain": true, + "fielddata_fields": [ + "state", + "numberOfCommits" + ], + "highlight": { + "fields": { + "tags": {}, + "description": {} + } + }, + "script_fields": { + "commit_factor": { + "script": { + "inline": "doc['numberOfCommits'].value * 2" + } + } + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .Terms("states", t => t + .Field(p => p.State) + .Aggregations(aa => aa + .TopHits("top_state_hits", th => th + .Sort(srt => srt + .Field(p => p.StartedOn) + .Order(SortOrder.Descending) + ) + .Source(src => src + .Include(fs => fs + .Field(p => p.Name) + .Field(p => p.StartedOn) + ) + ) + .Size(1) + .Version() + .Explain() + .FielddataFields(fd => fd + .Field(p => p.State) + .Field(p => p.NumberOfCommits) + ) + .Highlight(h => h + .Fields( + hf => hf.Field(p => p.Tags), + hf => hf.Field(p => p.Description) + ) + ) + .ScriptFields(sfs => sfs + .ScriptField("commit_factor", sf => sf + .Inline("doc['numberOfCommits'].value * 2") + ) + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new TermsAggregation("states") + { + Field = Field(p => p.State), + Aggregations = new TopHitsAggregation("top_state_hits") + { + Sort = new List + { + { + new SortField { Field = Field(p => p.StartedOn), Order = SortOrder.Descending } + } + }, + Source = new SourceFilter + { + Include = new [] { "name", "startedOn" } + }, + Size = 1, + Version = true, + Explain = true, + FielddataFields = new [] { "state", "numberOfCommits" }, + Highlight = new Highlight + { + Fields = new Dictionary + { + { Field(p => p.Tags), new HighlightField() }, + { Field(p => p.Description), new HighlightField() } + } + }, + ScriptFields = new ScriptFields + { + { "commit_factor", new ScriptField { Script = new InlineScript("doc['numberOfCommits'].value * 2") } } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var states = response.Aggs.Terms("states"); +states.Should().NotBeNull(); +states.Buckets.Should().NotBeNullOrEmpty(); +state.Key.Should().NotBeNullOrEmpty(); +state.DocCount.Should().BeGreaterThan(0); +var topStateHits = state.TopHits("top_state_hits"); +topStateHits.Should().NotBeNull(); +topStateHits.Total.Should().BeGreaterThan(0); +var hits = topStateHits.Hits(); +hits.Should().NotBeNullOrEmpty(); +hits.All(h => h.Explanation != null).Should().BeTrue(); +hits.All(h => h.Version.HasValue).Should().BeTrue(); +hits.All(h => h.Fields.ValuesOf("state").Any()).Should().BeTrue(); +hits.All(h => h.Fields.ValuesOf("numberOfCommits").Any()).Should().BeTrue(); +hits.All(h => h.Fields.ValuesOf("commit_factor").Any()).Should().BeTrue(); +topStateHits.Documents().Should().NotBeEmpty(); +---- + diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc new file mode 100644 index 00000000000..b77112e6e96 --- /dev/null +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_count": { + "value_count": { + "field": "numberOfCommits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Aggregations(a => a + .ValueCount("commit_count", c => c + .Field(p => p.NumberOfCommits) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest +{ + Aggregations = new ValueCountAggregation("commit_count", Field(p => p.NumberOfCommits)) +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var commitCount = response.Aggs.ValueCount("commit_count"); +commitCount.Should().NotBeNull(); +commitCount.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc new file mode 100644 index 00000000000..d09bab56e48 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -0,0 +1,92 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "average_commits_per_month": { + "avg_bucket": { + "buckets_path": "projects_started_per_month>commits", + "gap_policy": "insert_zeros" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .AverageBucket("average_commits_per_month", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + .GapPolicy(GapPolicy.InsertZeros) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") +} +&& new AverageBucketAggregation("average_commits_per_month", "projects_started_per_month>commits") +{ + GapPolicy = GapPolicy.InsertZeros +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var averageCommits = response.Aggs.AverageBucket("average_commits_per_month"); +averageCommits.Should().NotBeNull(); +averageCommits.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc new file mode 100644 index 00000000000..1f6faa0c1f2 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -0,0 +1,140 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "stable_state": { + "filter": { + "term": { + "state": { + "value": "Stable" + } + } + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "stable_percentage": { + "bucket_script": { + "buckets_path": { + "totalCommits": "commits", + "stableCommits": "stable_state>commits" + }, + "script": { + "inline": "stableCommits / totalCommits * 100" + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .Filter("stable_state", f => f + .Filter(ff => ff + .Term(p => p.State, "Stable") + ) + .Aggregations(aaa => aaa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .BucketScript("stable_percentage", bs => bs + .BucketsPath(bp => bp + .Add("totalCommits", "commits") + .Add("stableCommits", "stable_state>commits") + ) + .Script("stableCommits / totalCommits * 100") + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new FilterAggregation("stable_state") + { + Filter = new TermQuery + { + Field = "state", + Value = "Stable" + }, + Aggregations = new SumAggregation("commits", "numberOfCommits") + } && + new BucketScriptAggregation("stable_percentage", new MultiBucketsPath + { + { "totalCommits", "commits" }, + { "stableCommits", "stable_state>commits" } + }) + { + Script = (InlineScript)"stableCommits / totalCommits * 100" + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var stablePercentage = item.BucketScript("stable_percentage"); +stablePercentage.Should().NotBeNull(); +stablePercentage.Value.Should().HaveValue(); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc new file mode 100644 index 00000000000..621d33e2cb1 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -0,0 +1,102 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_bucket_filter": { + "bucket_selector": { + "buckets_path": { + "totalCommits": "commits" + }, + "script": { + "inline": "totalCommits >= 500" + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .BucketSelector("commits_bucket_filter", bs => bs + .BucketsPath(bp => bp + .Add("totalCommits", "commits") + ) + .Script("totalCommits >= 500") + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new BucketSelectorAggregation("commits_bucket_filter", new MultiBucketsPath + { + { "totalCommits", "commits" }, + }) + { + Script = (InlineScript)"totalCommits >= 500" + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var commits = item.Sum("commits"); +commits.Should().NotBeNull(); +commits.Value.Should().BeGreaterOrEqualTo(500); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc new file mode 100644 index 00000000000..b9da5bad5a3 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -0,0 +1,88 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "cumulative_commits": { + "cumulative_sum": { + "buckets_path": "commits" + } + } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var commitsDerivative = item.Derivative("cumulative_commits"); +commitsDerivative.Should().NotBeNull(); +commitsDerivative.Value.Should().NotBe(null); +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .CumulativeSum("cumulative_commits", d => d + .BucketsPath("commits") + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new CumulativeSumAggregation("cumulative_commits", "commits") +} + } +---- + diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc new file mode 100644 index 00000000000..ddd5ccc9aa4 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -0,0 +1,88 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_derivative": { + "derivative": { + "buckets_path": "commits" + } + } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var commitsDerivative = item.Derivative("commits_derivative"); +commitsDerivative.Should().NotBeNull(); +commitsDerivative.Value.Should().NotBe(null); +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .Derivative("commits_derivative", d => d + .BucketsPath("commits") + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new DerivativeAggregation("commits_derivative", "commits") +} + } +---- + diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc new file mode 100644 index 00000000000..4ad3e31344f --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -0,0 +1,90 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "max_commits_per_month": { + "max_bucket": { + "buckets_path": "projects_started_per_month>commits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .MaxBucket("max_commits_per_month", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") +} +&& new MaxBucketAggregation("max_commits_per_month", "projects_started_per_month>commits") + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var maxCommits = response.Aggs.MaxBucket("max_commits_per_month"); +maxCommits.Should().NotBeNull(); +maxCommits.Value.Should().BeGreaterThan(0); +maxCommits.Keys.Should().NotBeNull(); +maxCommits.Keys.Count.Should().BeGreaterOrEqualTo(1); +key.Should().NotBeNull(); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc new file mode 100644 index 00000000000..c277c017ad1 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -0,0 +1,90 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "min_commits_per_month": { + "min_bucket": { + "buckets_path": "projects_started_per_month>commits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .MinBucket("min_commits_per_month", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") +} +&& new MinBucketAggregation("min_commits_per_month", "projects_started_per_month>commits") + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var minCommits = response.Aggs.MinBucket("min_commits_per_month"); +minCommits.Should().NotBeNull(); +minCommits.Value.Should().BeGreaterThan(0); +minCommits.Keys.Should().NotBeNull(); +minCommits.Keys.Count.Should().BeGreaterOrEqualTo(1); +key.Should().NotBeNullOrEmpty(); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc new file mode 100644 index 00000000000..7b8012c8fab --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -0,0 +1,103 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "model": "ewma", + "settings": { + "alpha": 0.3 + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Model(m => m + .Ewma(e => e + .Alpha(0.3f) + ) + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Model = new EwmaModel + { + Alpha = 0.3f, + } + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var movingAvg = item.MovingAverage("commits_moving_avg"); +movingAvg.Should().NotBeNull(); +movingAvg.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc new file mode 100644 index 00000000000..4daf10a16c1 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -0,0 +1,106 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "model": "holt", + "settings": { + "alpha": 0.5, + "beta": 0.5 + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Model(m => m + .HoltLinear(hl => hl + .Alpha(0.5f) + .Beta(0.5f) + ) + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Model = new HoltLinearModel + { + Alpha = 0.5f, + Beta = 0.5f, + } + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var movingAvg = item.MovingAverage("commits_moving_avg"); +movingAvg.Should().NotBeNull(); +movingAvg.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc new file mode 100644 index 00000000000..a5f03bfba41 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -0,0 +1,114 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "window": 60, + "model": "holt_winters", + "settings": { + "type": "mult", + "alpha": 0.5, + "beta": 0.5, + "gamma": 0.5, + "period": 30, + "pad": false + } + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Window(60) + .Model(m => m + .HoltWinters(hw => hw + .Type(HoltWintersType.Multiplicative) + .Alpha(0.5f) + .Beta(0.5f) + .Gamma(0.5f) + .Period(30) + .Pad(false) + ) + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Window = 60, + Model = new HoltWintersModel + { + Type = HoltWintersType.Multiplicative, + Alpha = 0.5f, + Beta = 0.5f, + Gamma = 0.5f, + Period = 30, + Pad = false + } + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc new file mode 100644 index 00000000000..2974260a8fc --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -0,0 +1,99 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "gap_policy": "insert_zeros", + "model": "linear", + "settings": {} + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .GapPolicy(GapPolicy.InsertZeros) + .Model(m => m + .Linear() + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + GapPolicy = GapPolicy.InsertZeros, + Model = new LinearModel() + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var movingAvg = item.MovingAverage("commits_moving_avg"); +movingAvg.Should().NotBeNull(); +movingAvg.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc new file mode 100644 index 00000000000..b5484c8e69b --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -0,0 +1,102 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "model": "simple", + "window": 30, + "predict": 10, + "settings": {} + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Window(30) + .Predict(10) + .Model(m => m + .Simple() + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Window = 30, + Predict = 10, + Model = new SimpleModel() + } +} + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var movingAvg = item.Sum("commits_moving_avg"); +movingAvg.Should().NotBeNull(); +movingAvg.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc new file mode 100644 index 00000000000..4e6a385dae0 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -0,0 +1,93 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "thirtieth_difference": { + "serial_diff": { + "buckets_path": "commits", + "lag": 30 + } + } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var commits = item.Sum("commits"); +commits.Should().NotBeNull(); +commits.Value.Should().NotBe(null); +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .SerialDifferencing("thirtieth_difference", d => d + .BucketsPath("commits") + .Lag(30) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new SerialDifferencingAggregation("thirtieth_difference", "commits") + { + Lag = 30 + } +} + } +---- + diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc new file mode 100644 index 00000000000..2b106baf854 --- /dev/null +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -0,0 +1,87 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "sum_of_commits": { + "sum_bucket": { + "buckets_path": "projects_started_per_month>commits" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s +.Size(0) +.Aggregations(a => a + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .SumBucket("sum_of_commits", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SearchRequest() + { +Size = 0, +Aggregations = new DateHistogramAggregation("projects_started_per_month") +{ + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") +} +&& new SumBucketAggregation("sum_of_commits", "projects_started_per_month>commits") + } +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); +projectsPerMonth.Should().NotBeNull(); +projectsPerMonth.Buckets.Should().NotBeNull(); +projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0); +var commitsSum = response.Aggs.SumBucket("sum_of_commits"); +commitsSum.Should().NotBeNull(); +commitsSum.Value.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index ba25185bc1f..0b7ac1d33b7 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -1,3 +1,5 @@ +:section-number: 10 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -20,7 +22,7 @@ want to use each. This is the json output for each example -[source,javascript] +[source,javascript,method-name="expectjson"] .Example json output ---- { @@ -51,7 +53,7 @@ This is the json output for each example The fluent lambda syntax is the most terse way to write aggregations. It benefits from types that are carried over to sub aggregations -[source,csharp] +[source,csharp,method-name="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -70,7 +72,7 @@ The object initializer syntax (OIS) is a one-to-one mapping with how aggregation have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one mapping, being dictionary based in C means it can grow exponentially in complexity rather quickly. -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -91,7 +93,7 @@ It also allows you to combine multiple aggregations using bitwise AND (`&&`) ope Compare the following example with the previous vanilla OIS syntax -[source,csharp] +[source,csharp,method-name="initializer"] ---- new SearchRequest { @@ -110,7 +112,7 @@ An advanced scenario may involve an existing collection of aggregation functions on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor (`childAggs` below) in turn, returning the descriptor after each function application. -[source,csharp] +[source,csharp,method-name="fluent"] ---- var aggregations = new List, IAggregationContainer>> //<1> { diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index 02a3fcf6394..8f258511877 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -1,3 +1,5 @@ +:section-number: 4.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -21,7 +23,7 @@ The simplest of all connection pools, this takes a single `Uri` and uses that to It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always ready to go. -[source,csharp] +[source,csharp,method-name="singlenode"] ---- var uri = new Uri("http://localhost:9201"); var pool = new SingleNodeConnectionPool(uri); @@ -32,14 +34,14 @@ node.Uri.Port.Should().Be(9201); This type of pool is hardwired to opt out of sniffing -[source,csharp] +[source,csharp,method-name="singlenode"] ---- pool.SupportsReseeding.Should().BeFalse(); ---- and pinging -[source,csharp] +[source,csharp,method-name="singlenode"] ---- pool.SupportsPinging.Should().BeFalse(); ---- @@ -47,7 +49,7 @@ pool.SupportsPinging.Should().BeFalse(); When you use the low ceremony `ElasticClient` constructor that takes a single `Uri`, We default to using `SingleNodeConnectionPool` -[source,csharp] +[source,csharp,method-name="singlenode"] ---- var client = new ElasticClient(uri); @@ -56,7 +58,7 @@ client.ConnectionSettings.ConnectionPool.Should().BeOfType new Uri("http://localhost:" + p)); ---- a connection pool can be seeded using an enumerable of `Uri`s -[source,csharp] +[source,csharp,method-name="static"] ---- var pool = new StaticConnectionPool(uris); ---- Or using an enumerable of `Node`s -[source,csharp] +[source,csharp,method-name="static"] ---- var nodes = uris.Select(u => new Node(u)); @@ -100,14 +102,14 @@ pool = new StaticConnectionPool(nodes); This type of pool is hardwired to opt out of sniffing -[source,csharp] +[source,csharp,method-name="static"] ---- pool.SupportsReseeding.Should().BeFalse(); ---- but supports pinging when enabled -[source,csharp] +[source,csharp,method-name="static"] ---- pool.SupportsPinging.Should().BeTrue(); ---- @@ -115,7 +117,7 @@ pool.SupportsPinging.Should().BeTrue(); To create a client using this static connection pool, pass the connection pool to the `ConnectionSettings` you pass to `ElasticClient` -[source,csharp] +[source,csharp,method-name="static"] ---- var client = new ElasticClient(new ConnectionSettings(pool)); @@ -127,14 +129,14 @@ client.ConnectionSettings.ConnectionPool.Should().BeOfType A subclass of `StaticConnectionPool` that allows itself to be reseeded at run time. It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. -[source,csharp] +[source,csharp,method-name="sniffing"] ---- var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ---- a connection pool can be seeded using an enumerable of `Uri` -[source,csharp] +[source,csharp,method-name="sniffing"] ---- var pool = new SniffingConnectionPool(uris); ---- @@ -144,7 +146,7 @@ A major benefit here is you can include known node roles when seeding and NEST can use this information to favour sniffing on master eligible nodes first and take master only nodes out of rotation for issuing client calls on. -[source,csharp] +[source,csharp,method-name="sniffing"] ---- var nodes = uris.Select(u=>new Node(u)); @@ -153,14 +155,14 @@ pool = new SniffingConnectionPool(nodes); This type of pool is hardwired to opt in to sniffing -[source,csharp] +[source,csharp,method-name="sniffing"] ---- pool.SupportsReseeding.Should().BeTrue(); ---- and pinging -[source,csharp] +[source,csharp,method-name="sniffing"] ---- pool.SupportsPinging.Should().BeTrue(); ---- @@ -168,7 +170,7 @@ pool.SupportsPinging.Should().BeTrue(); To create a client using the sniffing connection pool pass the connection pool to the `ConnectionSettings` you pass to `ElasticClient` -[source,csharp] +[source,csharp,method-name="sniffing"] ---- var client = new ElasticClient(new ConnectionSettings(pool)); diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index eb3ac9bdd24..3cb2ab0a16a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -1,3 +1,5 @@ +:section-number: 4.5 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -10,14 +12,14 @@ Not typically something you'll have to pass to the client but all calls to `Syst in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. -[source,csharp] +[source,csharp,method-name="defaultnowbehaviour"] ---- var dateTimeProvider = DateTimeProvider.Default; ---- dates are always returned in UTC -[source,csharp] +[source,csharp,method-name="defaultnowbehaviour"] ---- dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); ---- @@ -26,7 +28,7 @@ Another responsibility of this interface is to calculate the time a node has to based on the number of attempts to revive it. For very advanced use cases, this might be something of interest to provide a custom implementation for. -[source,csharp] +[source,csharp,method-name="deadtimeoutcalculation"] ---- var dateTimeProvider = DateTimeProvider.Default; ---- @@ -34,7 +36,7 @@ var dateTimeProvider = DateTimeProvider.Default; The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the default values for `timeout` and `maxTimeout` are -[source,csharp] +[source,csharp,method-name="deadtimeoutcalculation"] ---- var timeout = TimeSpan.FromMinutes(1); @@ -50,7 +52,7 @@ image::{imagesdir}/timeoutplot.png[dead timeout] The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. -[source,csharp] +[source,csharp,method-name="deadtimeoutcalculation"] ---- var timeouts = Enumerable.Range(0, 30) .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 2696401973a..34453fb9df7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -1,3 +1,5 @@ +:section-number: 4.4 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -10,7 +12,7 @@ A `Node` can be instantiated by passing it a `Uri` -[source,csharp] +[source,csharp,method-name="creating"] ---- var node = new Node(new Uri("http://localhost:9200")); @@ -20,7 +22,7 @@ node.Uri.Port.Should().Be(9200); By default master eligible and holds data is presumed to be true -[source,csharp] +[source,csharp,method-name="creating"] ---- node.MasterEligible.Should().BeTrue(); @@ -29,7 +31,7 @@ node.HoldsData.Should().BeTrue(); Is resurrected is true on first usage, hints to the transport that a ping might be useful -[source,csharp] +[source,csharp,method-name="creating"] ---- node.IsResurrected.Should().BeTrue(); ---- @@ -42,17 +44,18 @@ a known cluster topology. passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy -[source,csharp] +[source,csharp,method-name="buildingpaths"] ---- var node = new Node(new Uri("http://test.example/elasticsearch")); node.Uri.Port.Should().Be(80); + node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); ---- We force paths to end with a forward slash so that they can later be safely combined -[source,csharp] +[source,csharp,method-name="buildingpaths"] ---- var combinedPath = new Uri(node.Uri, "index/type/_search"); @@ -61,7 +64,7 @@ combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); which is exactly what the `CreatePath` method does on `Node` -[source,csharp] +[source,csharp,method-name="buildingpaths"] ---- combinedPath = node.CreatePath("index/type/_search"); @@ -70,33 +73,41 @@ combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); === Marking Nodes -[source,csharp] +[source,csharp,method-name="marknodes"] ---- var node = new Node(new Uri("http://localhost:9200")); + node.FailedAttempts.Should().Be(0); + node.IsAlive.Should().BeTrue(); ---- every time a node is marked dead the number of attempts should increase and the passed datetime should be exposed. -[source,csharp] +[source,csharp,method-name="marknodes"] ---- var deadUntil = DateTime.Now.AddMinutes(1); + node.MarkDead(deadUntil); + node.FailedAttempts.Should().Be(i + 1); + node.IsAlive.Should().BeFalse(); + node.DeadUntil.Should().Be(deadUntil); ---- however when marking a node alive, the `DeadUntil` property should be reset and `FailedAttempts` reset to 0 -[source,csharp] +[source,csharp,method-name="marknodes"] ---- node.MarkAlive(); node.FailedAttempts.Should().Be(0); + node.DeadUntil.Should().Be(default(DateTime)); + node.IsAlive.Should().BeTrue(); ---- @@ -104,17 +115,24 @@ node.IsAlive.Should().BeTrue(); Nodes are considered equal if they have the same endpoint, no matter what other metadata is associated -[source,csharp] +[source,csharp,method-name="equality"] ---- var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; var nodeAsMaster = new Node(new Uri("http://localhost:9200")) { MasterEligible = true }; + (node == nodeAsMaster).Should().BeTrue(); + (node != nodeAsMaster).Should().BeFalse(); + var uri = new Uri("http://localhost:9200"); + (node == uri).Should().BeTrue(); + var differentUri = new Uri("http://localhost:9201"); + (node != differentUri).Should().BeTrue(); + node.Should().Be(nodeAsMaster); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 7a0b0094768..093ef9b0613 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -1,3 +1,5 @@ +:section-number: 4.2 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -9,14 +11,14 @@ Every request is executed in the context of a `RequestPipeline` when using the default `ITransport` implementation. -[source,csharp] +[source,csharp,method-name="requestpipeline"] ---- var settings = TestClient.CreateSettings(); ---- When calling Request/RequestAsync on Transport the whole coordination of the request is deferred to a new instance in a `using` block. -[source,csharp] +[source,csharp,method-name="requestpipeline"] ---- var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); @@ -26,7 +28,7 @@ pipeline.GetType().Should().Implement(); However the transport does not instantiate `RequestPipeline` directly; it uses a pluggable `IRequestPipelineFactory` to create it -[source,csharp] +[source,csharp,method-name="requestpipeline"] ---- var requestPipelineFactory = new RequestPipelineFactory(); @@ -43,74 +45,108 @@ requestPipeline.GetType().Should().Implement(); you can pass your own `IRequestPipeline` implementation to the transport when instantiating a client allowing you to have requests executed on your own custom request pipeline -[source,csharp] +[source,csharp,method-name="requestpipeline"] ---- var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); +---- +[source,csharp,method-name="createpipeline"] +---- var pool = setupPool(new[] { TestClient.CreateNode(), TestClient.CreateNode(9201) }); + var settings = new ConnectionSettings(pool, TestClient.CreateConnection()); + settings = settingsSelector?.Invoke(settings) ?? settings; +---- + +[source,csharp,method-name="firstusagecheck"] +---- var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); + var staticPipeline = CreatePipeline(uris => new StaticConnectionPool(uris)); + var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris)); ---- Here we have setup three pipelines using three different connection pools, lets see how they behave -[source,csharp] +[source,csharp,method-name="firstusagecheck"] ---- singleNodePipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); staticPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); + sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeTrue(); ---- Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() You can however disable this on ConnectionSettings -[source,csharp] +[source,csharp,method-name="firstusagecheck"] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnStartup(false)); sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); +---- + +[source,csharp,method-name="sniffsonconnectionfailure"] +---- var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); + var staticPipeline = CreatePipeline(uris => new StaticConnectionPool(uris)); + var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris)); + singleNodePipeline.SniffsOnConnectionFailure.Should().BeFalse(); + staticPipeline.SniffsOnConnectionFailure.Should().BeFalse(); + sniffingPipeline.SniffsOnConnectionFailure.Should().BeTrue(); ---- Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() You can however disable this on ConnectionSettings -[source,csharp] +[source,csharp,method-name="sniffsonconnectionfailure"] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnConnectionFault(false)); sniffingPipeline.SniffsOnConnectionFailure.Should().BeFalse(); +---- + +[source,csharp,method-name="sniffsonstalecluster"] +---- var dateTime = new TestableDateTimeProvider(); + var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First(), dateTime), dateTimeProvider: dateTime); + var staticPipeline = CreatePipeline(uris => new StaticConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime); + var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime); + singleNodePipeline.SniffsOnStaleCluster.Should().BeFalse(); + staticPipeline.SniffsOnStaleCluster.Should().BeFalse(); + sniffingPipeline.SniffsOnStaleCluster.Should().BeTrue(); + singleNodePipeline.StaleClusterState.Should().BeFalse(); + staticPipeline.StaleClusterState.Should().BeFalse(); + sniffingPipeline.StaleClusterState.Should().BeFalse(); ---- go one hour into the future -[source,csharp] +[source,csharp,method-name="sniffsonstalecluster"] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- connection pools that do not support reseeding never go stale -[source,csharp] +[source,csharp,method-name="sniffsonstalecluster"] ---- singleNodePipeline.StaleClusterState.Should().BeFalse(); @@ -119,7 +155,7 @@ staticPipeline.StaleClusterState.Should().BeFalse(); the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source,csharp] +[source,csharp,method-name="sniffsonstalecluster"] ---- sniffingPipeline.StaleClusterState.Should().BeTrue(); ---- @@ -127,27 +163,33 @@ sniffingPipeline.StaleClusterState.Should().BeTrue(); A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout. See the <> for more details, here we assert that our request pipeline exposes this propertly -[source,csharp] +[source,csharp,method-name="istakingtoolong"] ---- var dateTime = new TestableDateTimeProvider(); + var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First(), dateTime), dateTimeProvider: dateTime); + var staticPipeline = CreatePipeline(uris => new StaticConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime); + var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime); + singleNodePipeline.IsTakingTooLong.Should().BeFalse(); + staticPipeline.IsTakingTooLong.Should().BeFalse(); + sniffingPipeline.IsTakingTooLong.Should().BeFalse(); ---- go one hour into the future -[source,csharp] +[source,csharp,method-name="istakingtoolong"] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- connection pools that do not support reseeding never go stale -[source,csharp] +[source,csharp,method-name="istakingtoolong"] ---- singleNodePipeline.IsTakingTooLong.Should().BeTrue(); @@ -156,21 +198,28 @@ staticPipeline.IsTakingTooLong.Should().BeTrue(); the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source,csharp] +[source,csharp,method-name="istakingtoolong"] ---- sniffingPipeline.IsTakingTooLong.Should().BeTrue(); ---- request pipeline exposes the DateTime it started, here we assert it started 2 hours in the past -[source,csharp] +[source,csharp,method-name="istakingtoolong"] ---- (dateTime.Now() - singleNodePipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); (dateTime.Now() - staticPipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); + (dateTime.Now() - sniffingPipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); +---- + +[source,csharp,method-name="setssniffpathusingtotimespan"] +---- var dateTime = new TestableDateTimeProvider(); + var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris, dateTimeProvider: dateTime), dateTimeProvider: dateTime) as RequestPipeline; + sniffingPipeline.SniffPath.Should().Be("_nodes/_all/settings?flat_settings&timeout=2s"); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index a41e550697c..f199c3f3dba 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -1,3 +1,5 @@ +:section-number: 4.3 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -17,14 +19,14 @@ This is the minimum `ITransport` needs to report back for the client to function e.g in the low level client, transport is instantiated like this: -[source,csharp] +[source,csharp,method-name="interfaceexplained"] ---- var lowLevelTransport = new Transport(new ConnectionConfiguration()); ---- and in the high level client, like this: -[source,csharp] +[source,csharp,method-name="interfaceexplained"] ---- var highlevelTransport = new Transport(new ConnectionSettings()); @@ -36,7 +38,7 @@ The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the d many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. If you feel this need, {github}/issues[please let us know] as we'd love to learn why you've go down this route! -[source,csharp] +[source,csharp,method-name="interfaceexplained"] ---- var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index ad1341342ad..6be7fc2d2d6 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -11,7 +11,7 @@ out the client as an UnexpectedElasticsearchClientException, regardless whether An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. -[source,csharp] +[source,csharp,method-name="unexpectedexceptionsbubbleout"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -47,7 +47,7 @@ in the pipeline the unexpected exception is not lost, here a call to 9200 fails It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we can still see the audit trail for the whole coordinated request. -[source,csharp] +[source,csharp,method-name="willfailoverknowconnectionexceptionbutnotunexpected"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -60,6 +60,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing()) ); + audit = await audit.TraceUnexpectedException( new ClientCall { { AuditEvent.BadResponse, 9200 }, @@ -72,8 +73,11 @@ audit = await audit.TraceUnexpectedException( e.InnerException.Message.Should().Be("boom!"); } ); + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); ---- @@ -81,7 +85,7 @@ An unexpected hard exception on ping and sniff is something we *do* try to revov Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. However the client call on 9201 throws a hard exception we can not recover from -[source,csharp] +[source,csharp,method-name="pingunexceptedexceptiondoesfailover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -91,7 +95,10 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .AllDefaults() ); +---- +[source,csharp,method-name="pingunexceptedexceptiondoesfailover"] +---- audit = await audit.TraceUnexpectedException( new ClientCall { { AuditEvent.PingFailure, 9200 }, diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 3984b6f7b24..74e3415f828 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -14,7 +14,7 @@ both a client that throws and one that returns an invalid response with an `.Ori The following are recoverable exceptions -[source,csharp] +[source,csharp,method-name="somepipelinefailuresarerecoverable"] ---- var recoverablExceptions = new[] { @@ -27,7 +27,7 @@ recoverablExceptions.Should().OnlyContain(e => e.Recoverable); and the unrecoverable exceptions -[source,csharp] +[source,csharp,method-name="somepipelinefailuresarerecoverable"] ---- var unrecoverableExceptions = new[] { @@ -45,7 +45,7 @@ unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); As an example, let's set up a 10 node cluster that will always succeed when pinged but will fail with a 401 response when making client calls -[source,csharp] +[source,csharp,method-name="badauthenticationisunrecoverable"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -59,7 +59,7 @@ var audit = new Auditor(() => Framework.Cluster Here we make a client call and determine that the first audit event was a successful ping, followed by a bad response as a result of a bad authentication response -[source,csharp] +[source,csharp,method-name="badauthenticationisunrecoverable"] ---- audit = await audit.TraceElasticsearchException( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 93afbaf7f6c..be82942f0b5 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -9,7 +9,7 @@ When using connection pooling and the pool has sufficient nodes a request will be retried if the call to a node throws an exception or returns a 502 or 503 -[source,csharp] +[source,csharp,method-name="exceptionfallsovertonextnode"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -30,7 +30,7 @@ audit = await audit.TraceCall( Will be treated as an error that requires retrying -[source,csharp] +[source,csharp,method-name="http502fallsover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -39,6 +39,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing()) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, @@ -51,7 +52,7 @@ audit = await audit.TraceCall( Will be treated as an error that requires retrying -[source,csharp] +[source,csharp,method-name="http503fallsover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -60,6 +61,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing()) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, @@ -70,7 +72,7 @@ audit = await audit.TraceCall( If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. -[source,csharp] +[source,csharp,method-name="httpteapotdoesnotfallover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -79,6 +81,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing()) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index b55737ef6d8..cf6eb2d24dd 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -10,7 +10,7 @@ By default retry as many times as we have nodes. However retries still respect t Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds -[source,csharp] +[source,csharp,method-name="defaultmaxisnumberofnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -38,7 +38,7 @@ audit = await audit.TraceCall( When you have a 100 node cluster you might want to ensure a fixed number of retries. Remember that the actual number of requests is initial attempt + set number of retries -[source,csharp] +[source,csharp,method-name="fixedmaximumnumberofretries"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -47,6 +47,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing().MaximumRetries(3)) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, @@ -62,7 +63,7 @@ In our previous test we simulated very fast failures, in the real world a call m Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted -[source,csharp] +[source,csharp,method-name="respectsoveralrequesttimeout"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -71,6 +72,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, @@ -85,7 +87,7 @@ Here we simulate calls taking 3 seconds, a request time out of 2 and an overall We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 wins over the configured request timeout -[source,csharp] +[source,csharp,method-name="respectsmaxretrytimeoutoverrequesttimeout"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -94,6 +96,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, @@ -108,7 +111,7 @@ audit = await audit.TraceCall( If your retry policy expands beyond available nodes we won't retry the same node twice -[source,csharp] +[source,csharp,method-name="retriesarelimitedbynodesinpool"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(2) @@ -117,6 +120,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 }, @@ -130,7 +134,7 @@ This makes setting any retry setting on a single node connection pool a NOOP, th Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. -[source,csharp] +[source,csharp,method-name="doesnotretryonsinglenodeconnectionpool"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -139,6 +143,7 @@ var audit = new Auditor(() => Framework.Cluster .SingleNodeConnection() .Settings(s => s.DisablePing().MaximumRetries(10)) ); + audit = await audit.TraceCall( new ClientCall { { BadResponse, 9200 } diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index defe38fe597..e0aa2ca4657 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -1,3 +1,5 @@ +:section-number: 5.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -12,7 +14,7 @@ This allows us to fail and fallover to a healthy node faster A cluster with 2 nodes where the second node fails on ping -[source,csharp] +[source,csharp,method-name="pingfailsfallsovertohealthynodewithoutping"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(2) @@ -30,7 +32,7 @@ It fails so we wrap over to node 9200 which we've already pinged Finally we assert that the connectionpool has one node that is marked as dead -[source,csharp] +[source,csharp,method-name="pingfailsfallsovertohealthynodewithoutping"] ---- await audit.TraceCalls( new ClientCall { @@ -51,7 +53,7 @@ new ClientCall { A cluster with 4 nodes where the second and third pings fail -[source,csharp] +[source,csharp,method-name="pingfailsfallsovermultipletimestohealthynode"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -71,7 +73,7 @@ we haven't used it before and it succeeds Finally we assert that the connectionpool has two nodes that are marked as dead -[source,csharp] +[source,csharp,method-name="pingfailsfallsovermultipletimestohealthynode"] ---- await audit.TraceCalls( new ClientCall { @@ -94,7 +96,7 @@ new ClientCall { A healthy cluster of 4 (min master nodes of 3 of course!) -[source,csharp] +[source,csharp,method-name="allnodesarepingedonlyonfirstuseprovidedtheyarehealthy"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 2d4113d346a..11226450cad 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -1,3 +1,5 @@ +:section-number: 5.2 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -9,7 +11,7 @@ When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK -[source,csharp] +[source,csharp,method-name="pingafterrevival"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(3) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 34a335e3942..49529e8620f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -1,3 +1,5 @@ +:section-number: 6.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -7,38 +9,42 @@ == Disabling sniffing and pinging on a request basis Even if you are using a sniffing connection pool thats set up to sniff on start/failure -and pinging enabled, you can opt out of this behaviour on a per request basis +and pinging enabled, you can opt out of this behaviour on a _per request_ basis. In our first test we set up a cluster that pings and sniffs on startup but we disable the sniffing on our first request so we only see the ping and the response -[source,csharp] +Let's set up the cluster and configure clients to **always** sniff on startup + +[source,csharp,method-name="disablesniff"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .ClientCalls(r => r.SucceedAlways()) .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) + .Settings(s => s.SniffOnStartup()) //<1> ); ---- +<1> sniff on startup -We disable sniffing so even though its our first call, we do not want to sniff on startup +Now We disable sniffing on the request so even though it's our first call, we do not want to sniff on startup -Instead the sniff on startup is deffered to the second call into the cluster that +Instead, the sniff on startup is deferred to the second call into the cluster that does not disable sniffing on a per request basis -And after that no sniff on startup will happen again +And after that no sniff on startup will happen again -[source,csharp] +[source,csharp,method-name="disablesniff"] ---- audit = await audit.TraceCalls( -new ClientCall(r=>r.DisableSniffing()) { - { PingSuccess, 9200 }, +new ClientCall(r => r.DisableSniffing()) //<1> + { + { PingSuccess, 9200 }, //<2> { HealthyResponse, 9200 } }, new ClientCall() { - { SniffOnStartup }, + { SniffOnStartup }, //<3> { SniffSuccess, 9200 }, { PingSuccess, 9200 }, { HealthyResponse, 9200 } @@ -49,7 +55,17 @@ new ClientCall() { HealthyResponse, 9201 } } ); +---- +<1> disable sniffing + +<2> first call is a successful ping + +<3> sniff on startup call happens here, on the second call +Now, let's disable pinging on the request + +[source,csharp,method-name="disableping"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .ClientCalls(r => r.SucceedAlways()) @@ -57,22 +73,37 @@ var audit = new Auditor(() => Framework.Cluster .Settings(s => s.SniffOnStartup()) ); audit = await audit.TraceCall( - new ClientCall(r=>r.DisablePing()) { + new ClientCall(r => r.DisablePing()) //<1> + { { SniffOnStartup }, - { SniffSuccess, 9200 }, + { SniffSuccess, 9200 }, //<2> { HealthyResponse, 9200 } } ); +---- +<1> disable ping + +<2> No ping after sniffing + +Finally, let's demonstrate disabling both sniff and ping on the request + +[source,csharp,method-name="disablesniffandping"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .ClientCalls(r => r.SucceedAlways()) .SniffingConnectionPool() .Settings(s => s.SniffOnStartup()) ); + audit = await audit.TraceCall( - new ClientCall(r=>r.DisableSniffing().DisablePing()) { - { HealthyResponse, 9200 } + new ClientCall(r=>r.DisableSniffing().DisablePing()) //<1> + { + { HealthyResponse, 9200 } //<2> } ); ---- +<1> diable ping and sniff + +<2> no ping or sniff before the call diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 1bd000560d4..3391d1a10ff 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -1,3 +1,5 @@ +:section-number: 6.2 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -12,7 +14,7 @@ we set up a 10 node cluster with a global time out of 20 seconds. Each call on a node takes 10 seconds. So we can only try this call on 2 nodes before the max request time out kills the client call. -[source,csharp] +[source,csharp,method-name="respectsrequesttimeoutoverride"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -26,7 +28,7 @@ var audit = new Auditor(() => Framework.Cluster On the second request we specify a request timeout override to 60 seconds We should now see more nodes being tried. -[source,csharp] +[source,csharp,method-name="respectsrequesttimeoutoverride"] ---- audit = await audit.TraceCalls( new ClientCall { @@ -56,7 +58,7 @@ we set up a 10 node cluster with a global time out of 20 seconds. Each call on a node takes 10 seconds. So we can only try this call on 2 nodes before the max request time out kills the client call. -[source,csharp] +[source,csharp,method-name="respectsconnecttimeoutoverride"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -73,7 +75,7 @@ calls always take 20, so we should see a single ping failure On the second request we set a request ping timeout override of 2seconds We should now see more nodes being tried before the request timeout is hit. -[source,csharp] +[source,csharp,method-name="respectsconnecttimeoutoverride"] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 1488ba9f0ad..0c46f4adeed 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -1,3 +1,5 @@ +:section-number: 6.3 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -6,7 +8,7 @@ == Allowed status codes -[source,csharp] +[source,csharp,method-name="canoverridebadresponse"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index c439bc6b562..c5b65f841d7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -1,3 +1,5 @@ +:section-number: 6.4 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -9,7 +11,7 @@ Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` request configuration. This will ignore the pool and not retry. -[source,csharp] +[source,csharp,method-name="onlycallsforcednode"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index e71e2b38242..6b646e3ed8d 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -1,3 +1,5 @@ +:section-number: 6.5 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -10,7 +12,7 @@ By default retry as many times as we have nodes. However retries still respect t Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds -[source,csharp] +[source,csharp,method-name="defaultmaxisnumberofnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -32,7 +34,7 @@ audit = await audit.TraceCall( When you have a 100 node cluster you might want to ensure a fixed number of retries. Remember that the actual number of requests is initial attempt + set number of retries -[source,csharp] +[source,csharp,method-name="fixedmaximumnumberofretries"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -41,6 +43,7 @@ var audit = new Auditor(() => Framework.Cluster .StaticConnectionPool() .Settings(s => s.DisablePing().MaximumRetries(5)) ); + audit = await audit.TraceCall( new ClientCall(r => r.MaxRetries(2)) { { BadResponse, 9200 }, @@ -55,7 +58,7 @@ This makes setting any retry setting on a single node connection pool a NOOP, th Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. -[source,csharp] +[source,csharp,method-name="doesnotretryonsinglenodeconnectionpool"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -64,6 +67,7 @@ var audit = new Auditor(() => Framework.Cluster .SingleNodeConnection() .Settings(s => s.DisablePing().MaximumRetries(10)) ); + audit = await audit.TraceCall( new ClientCall(r => r.MaxRetries(10)) { { BadResponse, 9200 } diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index bf9263b1b1c..0c2404cf360 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -4,16 +4,17 @@ :imagesdir: ../../../images -Round Robin +== Round Robin + Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. -== GetNext +=== GetNext -GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance +`GetNext` is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. -[source,csharp] +[source,csharp,method-name="eachviewstartsatnexpositionandwrapsover"] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); var staticPool = new StaticConnectionPool(uris, randomize: false); @@ -22,7 +23,7 @@ this.AssertCreateView(staticPool); this.AssertCreateView(sniffingPool); ---- -Here we have setup a static connection pool seeded with 10 nodes. We force randomizationOnStartup to false +Here we have setup a static connection pool seeded with 10 nodes. We force randomization OnStartup to false so that we can test the nodes being returned are int the order we expect them to. So what order we expect? Imagine the following: @@ -31,7 +32,7 @@ Thread B calls GetNext() second without a local cursor and therefor starts at 1. After this each thread should walk the nodes in successive order using their local cursor e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. -[source,csharp] +[source,csharp,method-name="assertcreateview"] ---- var startingPositions = Enumerable.Range(0, NumberOfNodes) .Select(i => pool.CreateView().First()) @@ -39,6 +40,7 @@ var startingPositions = Enumerable.Range(0, NumberOfNodes) .ToList(); var expectedOrder = Enumerable.Range(9200, NumberOfNodes); + startingPositions.Should().ContainInOrder(expectedOrder); ---- @@ -52,25 +54,28 @@ Lets up the ante: We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 comes 9200 again -[source,csharp] +[source,csharp,method-name="assertcreateview"] ---- var threadedStartPositions = new ConcurrentBag(); var threads = Enumerable.Range(0, 20) .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) .ToList(); + t.Start(); + t.Join(); ---- Each thread reported the first node it started off lets make sure we see each node twice as the first node because we started `NumberOfNodes * 2` threads -[source,csharp] +[source,csharp,method-name="assertcreateview"] ---- var grouped = threadedStartPositions.GroupBy(p => p).ToList(); grouped.Count().Should().Be(NumberOfNodes); + grouped.Select(p => p.Count()).Should().OnlyContain(p => p == 2); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 62b6711d247..92880fe37f5 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -14,20 +14,30 @@ GetNext is implemented in a lock free thread safe fashion, meaning each callee g over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. -[source,csharp] +[source,csharp,method-name="eachviewseesnextbutskipsthedeadnode"] ---- var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); + +seeds.First().MarkDead(DateTime.Now.AddDays(1)); + var pool = new StaticConnectionPool(seeds, randomize: false); + var node = pool.CreateView().First(); -node.Uri.Port.Should().Be(9200); -node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9201); + node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9202); +---- + +[source,csharp,method-name="eachviewskipsaheadwithone"] +---- var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); -seeds.First().MarkDead(DateTime.Now.AddDays(1)); var pool = new StaticConnectionPool(seeds, randomize: false); var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +node = pool.CreateView().First(); node.Uri.Port.Should().Be(9201); node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); @@ -35,44 +45,66 @@ node.Uri.Port.Should().Be(9202); After we marked the first node alive again, we expect it to be hit again -[source,csharp] +[source,csharp,method-name="eachviewseesnextbutskipsthedeadnode"] ---- seeds.First().MarkAlive(); var node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9201); + node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9202); + node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9200); +---- + +[source,csharp,method-name="viewseesresurrectednodes"] +---- var dateTimeProvider = new TestableDateTimeProvider(); + var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); + seeds.First().MarkDead(dateTimeProvider.Now().AddDays(1)); + var pool = new StaticConnectionPool(seeds, randomize: false, dateTimeProvider: dateTimeProvider); + var node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9201); + node = pool.CreateView().First(); + node.Uri.Port.Should().Be(9202); ---- If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected -[source,csharp] +[source,csharp,method-name="viewseesresurrectednodes"] ---- dateTimeProvider.ChangeTime(d => d.AddDays(2)); var n = pool.CreateView().First(); + n.Uri.Port.Should().Be(9201); + n = pool.CreateView().First(); + n.Uri.Port.Should().Be(9202); + n = pool.CreateView().First(); + n.Uri.Port.Should().Be(9200); + n.IsResurrected.Should().BeTrue(); ---- A cluster with 2 nodes where the second node fails on ping -[source,csharp] +[source,csharp,method-name="fallsoverdeadnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -93,7 +125,7 @@ Finally we assert that the connectionpool has one node that is marked as dead The next call goes to 9203 which fails so we should wrap over -[source,csharp] +[source,csharp,method-name="fallsoverdeadnodes"] ---- await audit.TraceCalls( new ClientCall { @@ -131,7 +163,7 @@ new ClientCall { A cluster with 2 nodes where the second node fails on ping -[source,csharp] +[source,csharp,method-name="picksadifferentnodeeachtimeanodeisdown"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -147,7 +179,7 @@ After all our registered nodes are marked dead we want to sample a single dead n each time to quickly see if the cluster is back up. We do not want to retry all 4 nodes -[source,csharp] +[source,csharp,method-name="picksadifferentnodeeachtimeanodeisdown"] ---- await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index 7d91649a11a..55bc511487e 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -4,25 +4,33 @@ :imagesdir: ../../../images -[source,csharp] +[source,csharp,method-name="staticpoolwithstandsconcurrentreadandwrites"] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); -var sniffingPool = new SniffingConnectionPool(uris, randomize: false); -Action callSniffing = () => this.AssertCreateView(sniffingPool); -callSniffing.ShouldNotThrow(); -var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); + var staticPool = new StaticConnectionPool(uris, randomize: false); + Action callStatic = () => this.AssertCreateView(staticPool); + callStatic.ShouldNotThrow(); ---- -[source,csharp] +[source,csharp,method-name="sniffingpoolwithstandsconcurrentreadandwrites"] +---- +var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); +var sniffingPool = new SniffingConnectionPool(uris, randomize: false); +Action callSniffing = () => this.AssertCreateView(sniffingPool); +callSniffing.ShouldNotThrow(); +---- + +[source,csharp,method-name="assertcreateview"] ---- var threads = Enumerable.Range(0, 50) .Select(i => CreateReadAndUpdateThread(pool)) .ToList(); t.Start(); + t.Join(); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index f22882c65f1..e1c14adbaa2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -1,3 +1,5 @@ +:section-number: 7.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -23,7 +25,7 @@ still fails once After this second failure on 9201 another sniff will be returned a cluster that no longer fails but looks completely different (9210-9212) we should be able to handle this -[source,csharp] +[source,csharp,method-name="doesasniffafterconnectionfailure"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(5) @@ -52,7 +54,7 @@ Our pool should now have three nodes We assert we do a sniff on the first master node in our updated cluster -[source,csharp] +[source,csharp,method-name="doesasniffafterconnectionfailure"] ---- audit = await audit.TraceCalls( new ClientCall { @@ -88,7 +90,7 @@ new ClientCall { Here we set up our cluster exactly the same as the previous setup Only we enable pinging (default is true) and make the ping fail -[source,csharp] +[source,csharp,method-name="doesasniffafterconnectionfailureonping"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(5) @@ -118,7 +120,7 @@ We assert we do a sniff on the first master node in our updated cluster 9210 was already pinged after the sniff returned the new nodes -[source,csharp] +[source,csharp,method-name="doesasniffafterconnectionfailureonping"] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index 43401a943b1..854dcf90a22 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -1,3 +1,5 @@ +:section-number: 7.2 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -11,7 +13,7 @@ In addition to sniffing on startup and sniffing on failures, sniffing periodical clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes but without sniffing periodically it will never find the nodes that have been added to help out with load -[source,csharp] +[source,csharp,method-name="asniffonstartuphappens"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -39,7 +41,7 @@ var audit = new Auditor(() => Framework.Cluster healty cluster all nodes return healthy responses -[source,csharp] +[source,csharp,method-name="asniffonstartuphappens"] ---- audit = await audit.TraceCalls( new ClientCall { { HealthyResponse, 9200 } }, @@ -62,14 +64,14 @@ audit = await audit.TraceCalls( Now let's forward the clock 31 minutes, our sniff lifespan should now go state and the first call should do a sniff which discovered we scaled up to a 100 nodes! -[source,csharp] +[source,csharp,method-name="asniffonstartuphappens"] ---- audit.ChangeTime(d => d.AddMinutes(31)); ---- a sniff is done first and it prefers the first node master node -[source,csharp] +[source,csharp,method-name="asniffonstartuphappens"] ---- audit = await audit.TraceCalls( new ClientCall { @@ -85,7 +87,7 @@ audit.ChangeTime(d => d.AddMinutes(31)); a sniff is done first and it prefers the first node master node -[source,csharp] +[source,csharp,method-name="asniffonstartuphappens"] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index f7dbee0f6c6..bd554d52b93 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -1,3 +1,5 @@ +:section-number: 7.3 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -8,7 +10,7 @@ Connection pools that return true for `SupportsReseeding` by default sniff on startup. -[source,csharp] +[source,csharp,method-name="asniffonstartuphappensonce"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -17,22 +19,7 @@ var audit = new Auditor(() => Framework.Cluster .SniffingConnectionPool() .AllDefaults() ); -await audit.TraceCall(new ClientCall - { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} -}); -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() -); + await audit.TraceCalls( new ClientCall { @@ -49,6 +36,10 @@ await audit.TraceCalls( { HealthyResponse, 9201} } ); +---- + +[source,csharp,method-name="sniffonstartuptakesnewclusterstate"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Sniff(s => s.Fails(Always)) @@ -56,6 +47,7 @@ var audit = new Auditor(() => Framework.Cluster .SniffingConnectionPool() .AllDefaults() ); + await audit.TraceCall(new ClientCall { { SniffOnStartup}, { SniffFailure, 9200}, @@ -64,6 +56,10 @@ await audit.TraceCall(new ClientCall { { PingSuccess, 9204}, { HealthyResponse, 9204} }); +---- + +[source,csharp,method-name="snifftriesallnodes"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Sniff(s => s.Fails(Always)) @@ -71,6 +67,7 @@ var audit = new Auditor(() => Framework.Cluster .SniffingConnectionPool() .AllDefaults() ); + await audit.TraceCall(new ClientCall { { SniffOnStartup}, { SniffFailure, 9200}, @@ -86,6 +83,10 @@ await audit.TraceCall(new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }); +---- + +[source,csharp,method-name="sniffprefersmasternodes"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(new[] { new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, @@ -96,12 +97,17 @@ var audit = new Auditor(() => Framework.Cluster .SniffingConnectionPool() .AllDefaults() ); + await audit.TraceCall(new ClientCall { { SniffOnStartup}, { SniffSuccess, 9202}, { PingSuccess, 9200}, { HealthyResponse, 9200} }); +---- + +[source,csharp,method-name="sniffprefersmasternodesbutstillfailsover"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(new[] { new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, @@ -113,6 +119,7 @@ var audit = new Auditor(() => Framework.Cluster .SniffingConnectionPool() .AllDefaults() ); + await audit.TraceCall(new ClientCall { { SniffOnStartup}, { SniffFailure, 9200}, @@ -123,3 +130,23 @@ await audit.TraceCall(new ClientCall { }); ---- +[source,csharp,method-name="asniffonstartuphappens"] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() +); +await audit.TraceCall(new ClientCall + { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} +}); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index bc0c4607560..e0ff37c5e36 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -1,3 +1,5 @@ +:section-number: 7.4 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -9,38 +11,8 @@ When we sniff the custer state we detect the role of the node whether its master eligible and holds data We use this information when selecting a node to perform an API call on. -[source,csharp] +[source,csharp,method-name="detectsdatanodes"] ---- -var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202) - .Succeeds(Always, Framework.Cluster.Nodes(8).MasterEligible(9200, 9201, 9202)) - ) - .SniffingConnectionPool() - .AllDefaults() -) -{ - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); - }, - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); - } -}; -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(10); -pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(8); -pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); -await audit.TraceStartup(); var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Sniff(s => s.Fails(Always)) @@ -65,13 +37,24 @@ var audit = new Auditor(() => Framework.Cluster pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); } }; + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); + await audit.TraceStartup(); +---- + +[source,csharp,method-name="detectsfqdn"] +---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) .Sniff(s => s.SucceedAlways() @@ -97,31 +80,104 @@ var audit = new Auditor(() => Framework.Cluster pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); } }; + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); + pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); + pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); + await audit.TraceStartup(); +---- + +[source,csharp,method-name="sniffpicksuproles"] +---- var node = SniffAndReturnNode(); + node.MasterEligible.Should().BeTrue(); + node.HoldsData.Should().BeFalse(); + node = await SniffAndReturnNodeAsync(); + node.MasterEligible.Should().BeTrue(); + node.HoldsData.Should().BeFalse(); +---- + +[source,csharp,method-name="sniffandreturnnode"] +---- var pipeline = CreatePipeline(); + pipeline.Sniff(); +---- + +[source,csharp,method-name="sniffandreturnnodeasync"] +---- var pipeline = CreatePipeline(); + await pipeline.SniffAsync(); +---- + +[source,csharp,method-name="createpipeline"] +---- this._settings = this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; + var pipeline = new RequestPipeline(this._settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); +---- + +[source,csharp,method-name="assertsniffresponse"] +---- var nodes = this._settings.ConnectionPool.Nodes; + nodes.Should().NotBeEmpty().And.HaveCount(1); + var node = nodes.First(); ---- +[source,csharp,method-name="detectsmasternodes"] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202) + .Succeeds(Always, Framework.Cluster.Nodes(8).MasterEligible(9200, 9201, 9202)) + ) + .SniffingConnectionPool() + .AllDefaults() +) +{ + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); + }, + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); + } +}; +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(10); +pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); +pool.Should().NotBeNull(); +pool.Nodes.Should().HaveCount(8); +pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); +await audit.TraceStartup(); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index 6f8e30786b7..fcde875a521 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -1,25 +1,58 @@ +:section-number: 4.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images -= Covariant Search Results +== Covariant Search Results NEST directly supports returning covariant result sets. -Meaning a result can be typed to an interface or baseclass +Meaning a result can be typed to an interface or base class but the actual instance type of the result can be that of the subclass directly -Let look at an example, imagine we want to search over multiple types that all implement +Let's look at an example; Imagine we want to search over multiple types that all implement `ISearchResult` +[source,csharp,method-name="unknown"] +---- +public interface ISearchResult +{ + string Name { get; set; } +} +---- + We have three implementations of `ISearchResult` namely `A`, `B` and `C` +[source,csharp,method-name="unknown"] +---- +public class A : ISearchResult +{ + public string Name { get; set; } + public int PropertyOnA { get; set; } +} + +public class B : ISearchResult +{ + public string Name { get; set; } + public int PropertyOnB { get; set; } +} + +public class C : ISearchResult +{ + public string Name { get; set; } + public int PropertyOnC { get; set; } +} +---- + +=== Using Types + The most straightforward way to search over multiple types is to type the response to the parent interface or base class -and pass the actual types we want to search over using `.Types()` +and pass the actual types we want to search over using `.Type()` -[source,csharp] +[source,csharp,method-name="usingtypes"] ---- var result = this._client.Search(s => s .Type(Types.Type(typeof(A), typeof(B), typeof(C))) @@ -27,13 +60,13 @@ var result = this._client.Search(s => s ); ---- -Nest will translate this to a search over /index/a,b,c/_search. -hits that have `"_type" : "a will be serialized to `A` and so forth +NEST will translate this to a search over `/index/a,b,c/_search`; +hits that have "_type" : "a` will be serialized to `A` and so forth Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp] +[source,csharp,method-name="usingtypes"] ---- result.IsValid.Should().BeTrue(); @@ -43,7 +76,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp] +[source,csharp,method-name="usingtypes"] ---- var aDocuments = result.Documents.OfType(); @@ -56,7 +89,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp] +[source,csharp,method-name="usingtypes"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -64,9 +97,11 @@ bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ---- +=== Using ConcreteTypeSelector + A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to -[source,csharp] +[source,csharp,method-name="usingconcretetypeselector"] ---- var result = this._client.Search(s => s .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) @@ -74,13 +109,16 @@ var result = this._client.Search(s => s ); ---- -here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` -and a typed `h` which represents the encapsulating hit. +here for each hit we'll call the delegate passed to ConcreteTypeSelector where + +* `d` is a representation of the `_source` exposed as a `dynamic` type + +* a typed `h` which represents the encapsulating hit of the source i.e. `Hit` Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp] +[source,csharp,method-name="usingconcretetypeselector"] ---- result.IsValid.Should().BeTrue(); @@ -90,46 +128,51 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp] +[source,csharp,method-name="usingconcretetypeselector"] ---- var aDocuments = result.Documents.OfType(); var bDocuments = result.Documents.OfType(); + var cDocuments = result.Documents.OfType(); + aDocuments.Count().Should().Be(25); + bDocuments.Count().Should().Be(25); + cDocuments.Count().Should().Be(50); ---- and assume that properties that only exist on the subclass itself are properly filled -[source,csharp] +[source,csharp,method-name="usingconcretetypeselector"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); + cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ---- Scroll also supports CovariantSearchResponses -Scroll() is a continuation of a previous Search() so Types() are lost. -You can hint the type types again using CovariantTypes() +The Scroll API is a continuation of the previous Search example so Types() are lost. +You can hint at the types using `.CovariantTypes()` -[source,csharp] +[source,csharp,method-name="usingcovarianttypesonscroll"] ---- var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) ); ---- -Nest will translate this to a search over /index/a,b,c/_search. -hits that have `"_type" : "a will be serialized to `A` and so forth +NEST will translate this to a search over `/index/a,b,c/_search`; +hits that have "_type" : "a` will be serialized to `A` and so forth Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp] +[source,csharp,method-name="usingcovarianttypesonscroll"] ---- result.IsValid.Should().BeTrue(); @@ -139,43 +182,51 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp] +[source,csharp,method-name="usingcovarianttypesonscroll"] ---- var aDocuments = result.Documents.OfType(); var bDocuments = result.Documents.OfType(); + var cDocuments = result.Documents.OfType(); + aDocuments.Count().Should().Be(25); + bDocuments.Count().Should().Be(25); + cDocuments.Count().Should().Be(50); ---- and assume that properties that only exist on the subclass itself are properly filled -[source,csharp] +[source,csharp,method-name="usingcovarianttypesonscroll"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); + cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ---- The more low level concrete type selector can also be specified on scroll -[source,csharp] +[source,csharp,method-name="usingconcretetypeselectoronscroll"] ---- var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) ); ---- -here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` -and a typed `h` which represents the encapsulating hit. +As before, within the delegate passed to `.ConcreteTypeSelector` + +* `d` is the `_source` typed as `dynamic` + +* `h` is the encapsulating typed hit Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp] +[source,csharp,method-name="usingconcretetypeselectoronscroll"] ---- result.IsValid.Should().BeTrue(); @@ -185,24 +236,29 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp] +[source,csharp,method-name="usingconcretetypeselectoronscroll"] ---- var aDocuments = result.Documents.OfType(); var bDocuments = result.Documents.OfType(); + var cDocuments = result.Documents.OfType(); + aDocuments.Count().Should().Be(25); + bDocuments.Count().Should().Be(25); + cDocuments.Count().Should().Be(50); ---- and assume that properties that only exist on the subclass itself are properly filled -[source,csharp] +[source,csharp,method-name="usingconcretetypeselectoronscroll"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); + cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc new file mode 100644 index 00000000000..454d61ebced --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -0,0 +1,126 @@ +:section-number: 2.4 + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== DocumentPaths + +Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes +and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path +to your document more succintly + +=== Creating new instances + +here we create a new document path based on Project with the id 1 + +[source,csharp,method-name="fromid"] +---- +IDocumentPath path = new DocumentPath(1); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect(1).WhenSerializing(path.Id); +---- + +You can still override the inferred index and type name + +[source,csharp,method-name="fromid"] +---- +path = new DocumentPath(1).Type("project1"); + +Expect("project1").WhenSerializing(path.Type); +path = new DocumentPath(1).Index("project1"); +Expect("project1").WhenSerializing(path.Index); +---- + +and there is also a static way to describe such paths + +[source,csharp,method-name="fromid"] +---- +path = DocumentPath.Id(1); + +Expect("project").WhenSerializing(path.Index); +Expect("project").WhenSerializing(path.Type); +Expect(1).WhenSerializing(path.Id); +---- + +=== Creating from a document type instance + +if you have an instance of your document you can use it as well generate document paths + +[source,csharp,method-name="fromobject"] +---- +var project = new Project { Name = "hello-world" }; +---- + +here we create a new document path based on the instance of `Project`, project + +[source,csharp,method-name="fromobject"] +---- +IDocumentPath path = new DocumentPath(project); + +Expect("project").WhenSerializing(path.Index); + +Expect("project").WhenSerializing(path.Type); + +Expect("hello-world").WhenSerializing(path.Id); +---- + +You can still override the inferred index and type name + +[source,csharp,method-name="fromobject"] +---- +path = new DocumentPath(project).Type("project1"); + +Expect("project1").WhenSerializing(path.Type); + +path = new DocumentPath(project).Index("project1"); + +Expect("project1").WhenSerializing(path.Index); +---- + +and again, there is also a static way to describe such paths + +[source,csharp,method-name="fromobject"] +---- +path = DocumentPath.Id(project); + +Expect("project").WhenSerializing(path.Index); + +Expect("project").WhenSerializing(path.Type); + +Expect("hello-world").WhenSerializing(path.Id); + +DocumentPath p = project; +---- + +=== An example with requests + +[source,csharp,method-name="usingwithrequests"] +---- +var project = new Project { Name = "hello-world" }; +---- + +we can see an example of how `DocumentPath` helps your describe your requests more tersely + +[source,csharp,method-name="usingwithrequests"] +---- +var request = new IndexRequest(2) { Document = project }; + +request = new IndexRequest(project) { }; +---- + +when comparing with the full blown constructor and passing document manually, +`DocumentPath`'s benefits become apparent. + +[source,csharp,method-name="usingwithrequests"] +---- +request = new IndexRequest(IndexName.From(), TypeName.From(), 2) +{ + Document = project +}; +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc new file mode 100644 index 00000000000..6eacd91488b --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -0,0 +1,460 @@ +:section-number: 2.1 + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Strongly typed Field Access + +Several places in the elasticsearch API expect the path to a field from your original source document as a string. +NEST allows you to use C expressions to strongly type these field path strings. + +These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: + +Using the constructor directly is possible but rather involved + +[source,csharp,method-name="usingconstructors"] +---- +var fieldString = new Field { Name = "name" }; +---- + +especially when using C expressions since these can not be simply new'ed + +[source,csharp,method-name="usingconstructors"] +---- +Expression> expression = p => p.Name; + +var fieldExpression = Field.Create(expression); +Expect("name") + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); +---- + +Therefore you can also implicitly convert strings and expressions to `Field`s + +[source,csharp,method-name="implicitconversion"] +---- +Field fieldString = "name"; +---- + +but for expressions this is still rather involved + +[source,csharp,method-name="implicitconversion"] +---- +Expression> expression = p => p.Name; + +Field fieldExpression = expression; + +Expect("name") + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); +---- + +to ease creating `Field`s from expressions there is a static Property class you can use + +[source,csharp,method-name="usingstaticpropertyfield"] +---- +Field fieldString = "name"; +---- + +but for expressions this is still rather involved + +[source,csharp,method-name="usingstaticpropertyfield"] +---- +var fieldExpression = Infer.Field(p => p.Name); +---- + +this can be even shortened even further using static imports in c 6 i.e. + `using static Nest.Static;` + +[source,csharp,method-name="usingstaticpropertyfield"] +---- +fieldExpression = Field(p => p.Name); +---- + +Now this is much much terser then our first example using the constructor! + +[source,csharp,method-name="usingstaticpropertyfield"] +---- +Expect("name") + .WhenSerializing(fieldString) + .WhenSerializing(fieldExpression); +---- + +By default, NEST will camel-case all field names to be more _javascript-y_ + +using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior + +[source,csharp,method-name="defaultfieldnameinferrer"] +---- +var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); + +setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); +---- + +However string are *always* passed along verbatim + +[source,csharp,method-name="defaultfieldnameinferrer"] +---- +setup.Expect("NaMe").WhenSerializing("NaMe"); +---- + +if you want the same behavior for expressions simply do nothing in the default inferrer + +[source,csharp,method-name="defaultfieldnameinferrer"] +---- +setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); + +setup.Expect("Name").WhenSerializing(Field(p => p.Name)); +---- + +=== Complex field name expressions + +You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); +---- + +When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); +---- + +NOTE: Similarly, LINQ's `.First()` method also works +remember these are expressions and not actual code that will be executed + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); + +Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); + +Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); +---- + +An indexer on a dictionary is assumed to describe a property name + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); + +Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); +---- + +A cool feature here is that we'll evaluate variables passed to an indexer + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +var variable = "var"; + +Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); + +Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); +---- + +If you are using elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow +you to analyze a string in a number of different ways, these _"virtual" sub fields +do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that +should be mapped. + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); + +Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); + +Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); + +Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); + +Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); + +Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); +---- + +You can even chain `.Suffix()` calls to any depth! + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); +---- + +Variables passed to suffix will be evaluated as well + +[source,csharp,method-name="complexfieldnameexpressions"] +---- +var suffix = "unanalyzed"; + +Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); + +Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); +---- + +Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix +to a list of fields. + +Here we have a list of expressions + +[source,csharp,method-name="appendingsuffixtoexpressions"] +---- +var expressions = new List>> +{ + p => p.Name, + p => p.Description, + p => p.CuratedTags.First().Name, + p => p.LeadDeveloper.FirstName +}; +---- + +and we want to append the suffix "raw" to each + +[source,csharp,method-name="appendingsuffixtoexpressions"] +---- +var fieldExpressions = + expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); + +Expect("name.raw").WhenSerializing(fieldExpressions[0]); + +Expect("description.raw").WhenSerializing(fieldExpressions[1]); + +Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); + +Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); +---- + +=== Annotations + +When using NEST's property attributes you can specify a new name for the properties + +[source,csharp,method-name="unknown"] +---- +public class BuiltIn +{ + [String(Name = "naam")] + public string Name { get; set; } +} +---- + +[source,csharp,method-name="builtinannotiatons"] +---- +Expect("naam").WhenSerializing(Field(p => p.Name)); +---- + +Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. +Here we ask the default `JsonNetSerializer` to resolve a property name and it takes +the `JsonPropertyAttribute` into account + +[source,csharp,method-name="unknown"] +---- +public class SerializerSpecific +{ + [JsonProperty("nameInJson")] + public string Name { get; set; } +} +---- + +[source,csharp,method-name="serializerspecificannotations"] +---- +Expect("nameInJson").WhenSerializing(Field(p => p.Name)); +---- + +If both a NEST property attribute and a serializer specific attribute are present on a property, +NEST takes precedence + +[source,csharp,method-name="unknown"] +---- +public class Both +{ + [String(Name = "naam")] + [JsonProperty("nameInJson")] + public string Name { get; set; } +} +---- + +[source,csharp,method-name="nestattributetakesprecedence"] +---- +Expect("naam").WhenSerializing(Field(p => p.Name)); + +Expect(new +{ + naam = "Martijn Laarman" +}).WhenSerializing(new Both { Name = "Martijn Laarman" }); +---- + +Resolution of field names is cached per connection settings instance. To demonstrate, +take the following simple POCOs + +[source,csharp,method-name="unknown"] +---- +class A { public C C { get; set; } } + +class B { public C C { get; set; } } + +class C { public string Name { get; set; } } +---- + +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +---- +var connectionSettings = TestClient.CreateSettings(forceInMemory: true); + +var client = new ElasticClient(connectionSettings); + +var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); + +var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); +---- + +Here we have to similary shaped expressions on coming from A and on from B +that will resolve to the same field name, as expected + +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +---- +fieldNameOnA.Should().Be("c.name"); + +fieldNameOnB.Should().Be("c.name"); +---- + +now we create a new connectionsettings with a remap for C on class A to `d` +now when we resolve the field path for A will be different + +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +---- +var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s + .InferMappingFor(m => m + .Rename(p => p.C, "d") + ) +); + +var newClient = new ElasticClient(newConnectionSettings); + +fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); + +fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); + +fieldNameOnA.Should().Be("d.name"); + +fieldNameOnB.Should().Be("c.name"); +---- + +however we didn't break inferrence on the first client instance using its separate connectionsettings + +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +---- +fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); + +fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); + +fieldNameOnA.Should().Be("c.name"); + +fieldNameOnB.Should().Be("c.name"); +---- + +To wrap up, the precedence in which field names are inferred is: + +. A hard rename of the property on connection settings using `.Rename()` + +. A NEST property mapping + +. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. + +. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases + +The following example class will demonstrate this precedence + +[source,csharp,method-name="unknown"] +---- +class Precedence +{ + // Even though this property has a NEST property mapping and a JsonProperty attribute, + // We are going to provide a hard rename for it on ConnectionSettings later that should win. + [String(Name = "renamedIgnoresNest")] + [JsonProperty("renamedIgnoresJsonProperty")] + public string RenamedOnConnectionSettings { get; set; } + + // This property has both a NEST attribute and a JsonProperty, NEST should win. + [String(Name = "nestAtt")] + [JsonProperty("jsonProp")] + public string NestAttribute { get; set; } + + // We should take the json property into account by itself + [JsonProperty("jsonProp")] + public string JsonProperty { get; set; } + + // This property we are going to special case in our custom serializer to resolve to ask + [JsonProperty("dontaskme")] + public string AskSerializer { get; set; } + + // We are going to register a DefaultFieldNameInferrer on ConnectionSettings + // that will uppercase all properties. + public string DefaultFieldNameInferrer { get; set; } +} +---- + +Here we create a custom serializer that renames any property named `AskSerializer` to `ask` + +[source,csharp,method-name="unknown"] +---- +class CustomSerializer : JsonNetSerializer +{ + public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } + + public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) + { + return memberInfo.Name == nameof(Precedence.AskSerializer) + ? new PropertyMapping { Name = "ask" } + : base.CreatePropertyMapping(memberInfo); + } +} +---- + +here we provide an explicit rename of a property on connectionsettings using `.Rename()` +and all properties that are not mapped verbatim should be uppercased + +[source,csharp,method-name="precedenceisasexpected"] +---- +var usingSettings = WithConnectionSettings(s => s + + .InferMappingFor(m => m + .Rename(p => p.RenamedOnConnectionSettings, "renamed") + ) + .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) +).WithSerializer(s => new CustomSerializer(s)); + +usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); + +usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); + +usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); + +usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); + +usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); +---- + +The same naming rules also apply when indexing a document + +[source,csharp,method-name="precedenceisasexpected"] +---- +usingSettings.Expect(new [] +{ + "ask", + "DEFAULTFIELDNAMEINFERRER", + "jsonProp", + "nestAtt", + "renamed" +}).AsPropertiesOf(new Precedence +{ + RenamedOnConnectionSettings = "renamed on connection settings", + NestAttribute = "using a nest attribute", + JsonProperty = "the default serializer resolves json property attributes", + AskSerializer = "serializer fiddled with this one", + DefaultFieldNameInferrer = "shouting much?" +}); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc new file mode 100644 index 00000000000..fb85a375f6d --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -0,0 +1,135 @@ +:section-number: 2.3 + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Id Inference + +=== Implicit Conversions + +Several places in the Elasticsearch API expect an `Id` object to be passed. +This is a special box type that you can implicitly convert to from the following types + +* `Int32` + +* `Int64` + +* `String` + +* `Guid` + +Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` + +[source,csharp,method-name="canimplicitlyconverttoid"] +---- +Id idFromInt = 1; +Id idFromLong = 2L; +Id idFromString = "hello-world"; +Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); +Expect(1).WhenSerializing(idFromInt); +Expect(2).WhenSerializing(idFromLong); +Expect("hello-world").WhenSerializing(idFromString); +Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); +---- + +=== Inferring from a Type + +Sometimes a method takes an object and we need an Id from that object to build up a path. +There is no implicit conversion from any object to Id but we can call `Id.From`. + +Imagine your codebase has the following type that we want to index into Elasticsearch + +[source,csharp,method-name="unknown"] +---- +class MyDTO +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } +} +---- + +By default NEST will try to find a property called `Id` on the class using reflection +and create a cached fast func delegate based on the properties getter + +[source,csharp,method-name="cangetidfromdocument"] +---- +var dto = new MyDTO +{ + Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), + Name = "x", + OtherName = "y" +}; + +Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); +---- + +Using the connection settings you can specify a different property that NEST should use to infer the document Id. +Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property + +[source,csharp,method-name="cangetidfromdocument"] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.Name) + ) +).Expect("x").WhenInferringIdOn(dto); +---- + +IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. + +Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance +with different inference rules + +[source,csharp,method-name="cangetidfromdocument"] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) +).Expect("y").WhenInferringIdOn(dto); +---- + +=== Using the `ElasticsearchType` attribute + +Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` +to the name of the property that should be used for the document id + +[source,csharp,method-name="unknown"] +---- +[ElasticsearchType(IdProperty = nameof(Name))] +class MyOtherDTO +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } +} +---- + +Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` + +[source,csharp,method-name="cangetidfromattribute"] +---- +var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; + +Expect("x").WhenInferringIdOn(dto); +---- + +=== Using Mapping inference on `ConnectionSettings` + +This attribute *is* cached statically/globally, however an inference rule on the `ConnectionSettings` for the type will +still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance +that will infer the document id from the property `OtherName`: + +[source,csharp,method-name="cangetidfromattribute"] +---- +WithConnectionSettings(x => x + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) +).Expect("y").WhenInferringIdOn(dto); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc new file mode 100644 index 00000000000..3fbdb39838b --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -0,0 +1,56 @@ +:section-number: 2.5 + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Indices paths + +Some API's in elasticsearch take one or many index name or a special "all" marker to send the request to all the indices +In nest this is encoded using `Indices` + +Several types implicitly convert to `Indices` + +[source,csharp,method-name="implicitconversionfromstring"] +---- +Nest.Indices singleIndexFromString = "name"; +Nest.Indices multipleIndicesFromString = "name1, name2"; +Nest.Indices allFromString = "_all"; +Nest.Indices allWithOthersFromString = "_all, name2"; +singleIndexFromString.Match( + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(1).And.Contain("name") +); +multipleIndicesFromString.Match( + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(2).And.Contain("name2") +); +allFromString.Match( + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() +); +allWithOthersFromString.Match( + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() +); +---- + +to ease creating Field's from expressions there is a static Property class you can use + +[source,csharp,method-name="usingstaticpropertyfield"] +---- +var all = Nest.Indices.All; + +var many = Nest.Indices.Index("name1", "name2"); + +var manyTyped = Nest.Indices.Index().And(); + +var singleTyped = Nest.Indices.Index(); + +var singleString = Nest.Indices.Index("name1"); + +var invalidSingleString = Nest.Indices.Index("name1, name2"); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc new file mode 100644 index 00000000000..421cbf92b5b --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -0,0 +1,37 @@ +:section-number: 2.2 + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +== Property Names + +Property names resolve to the last token. An example using the `.Suffix()` extension + +[source,csharp,method-name="propertynamesareresolvedtolasttokenusingsuffix"] +---- +Expression> expression = p => p.Name.Suffix("raw"); +Expect("raw").WhenSerializing(expression); +---- + +And an example using the `.ApplySuffix()` extension on lambda expressions + +[source,csharp,method-name="propertynamesareresolvedtolasttokenusingapplysuffix"] +---- +Expression> expression = p => p.Name; + +expression.AppendSuffix("raw"); + +Expect("raw").WhenSerializing(expression); +---- + +Property names cannot contain a `.` in order to prevent the potential for collision with a field that +may have {ref_current}/_multi_fields.html[`multi_fields`] + +[source,csharp,method-name="stringscontainingdotsisanexception"] +---- +Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc index aea54b7736f..454d61ebced 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc @@ -1,20 +1,22 @@ +:section-number: 2.4 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images -= DocumentPaths +== DocumentPaths -Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes -and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path +Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes +and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path to your document more succintly -== Creating new instances +=== Creating new instances here we create a new document path based on Project with the id 1 -[source,csharp] +[source,csharp,method-name="fromid"] ---- IDocumentPath path = new DocumentPath(1); @@ -25,7 +27,7 @@ Expect(1).WhenSerializing(path.Id); You can still override the inferred index and type name -[source,csharp] +[source,csharp,method-name="fromid"] ---- path = new DocumentPath(1).Type("project1"); @@ -34,9 +36,9 @@ path = new DocumentPath(1).Index("project1"); Expect("project1").WhenSerializing(path.Index); ---- -there is also a static way to describe such paths +and there is also a static way to describe such paths -[source,csharp] +[source,csharp,method-name="fromid"] ---- path = DocumentPath.Id(1); @@ -45,63 +47,76 @@ Expect("project").WhenSerializing(path.Type); Expect(1).WhenSerializing(path.Id); ---- -== Creating from a document type instance +=== Creating from a document type instance if you have an instance of your document you can use it as well generate document paths -[source,csharp] +[source,csharp,method-name="fromobject"] ---- var project = new Project { Name = "hello-world" }; ---- here we create a new document path based on the instance of `Project`, project -[source,csharp] +[source,csharp,method-name="fromobject"] ---- IDocumentPath path = new DocumentPath(project); Expect("project").WhenSerializing(path.Index); + Expect("project").WhenSerializing(path.Type); + Expect("hello-world").WhenSerializing(path.Id); ---- You can still override the inferred index and type name -[source,csharp] +[source,csharp,method-name="fromobject"] ---- path = new DocumentPath(project).Type("project1"); Expect("project1").WhenSerializing(path.Type); + path = new DocumentPath(project).Index("project1"); + Expect("project1").WhenSerializing(path.Index); ---- -there is also a static way to describe such paths +and again, there is also a static way to describe such paths -[source,csharp] +[source,csharp,method-name="fromobject"] ---- path = DocumentPath.Id(project); Expect("project").WhenSerializing(path.Index); + Expect("project").WhenSerializing(path.Type); + Expect("hello-world").WhenSerializing(path.Id); + DocumentPath p = project; +---- + +=== An example with requests + +[source,csharp,method-name="usingwithrequests"] +---- var project = new Project { Name = "hello-world" }; ---- -Here we can see and example how DocumentPath helps your describe your requests more tersely +we can see an example of how `DocumentPath` helps your describe your requests more tersely -[source,csharp] +[source,csharp,method-name="usingwithrequests"] ---- var request = new IndexRequest(2) { Document = project }; request = new IndexRequest(project) { }; ---- -when comparing with the full blown constructor and passing document manually +when comparing with the full blown constructor and passing document manually, `DocumentPath`'s benefits become apparent. -[source,csharp] +[source,csharp,method-name="usingwithrequests"] ---- request = new IndexRequest(IndexName.From(), TypeName.From(), 2) { diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc index 456615dd0b6..6eacd91488b 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc @@ -1,10 +1,12 @@ +:section-number: 2.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images -= Strongly typed field access +== Strongly typed Field Access Several places in the elasticsearch API expect the path to a field from your original source document as a string. NEST allows you to use C expressions to strongly type these field path strings. @@ -13,14 +15,14 @@ These expressions are assigned to a type called `Field` and there are several wa Using the constructor directly is possible but rather involved -[source,csharp] +[source,csharp,method-name="usingconstructors"] ---- var fieldString = new Field { Name = "name" }; ---- especially when using C expressions since these can not be simply new'ed -[source,csharp] +[source,csharp,method-name="usingconstructors"] ---- Expression> expression = p => p.Name; @@ -32,18 +34,19 @@ Expect("name") Therefore you can also implicitly convert strings and expressions to `Field`s -[source,csharp] +[source,csharp,method-name="implicitconversion"] ---- Field fieldString = "name"; ---- but for expressions this is still rather involved -[source,csharp] +[source,csharp,method-name="implicitconversion"] ---- Expression> expression = p => p.Name; Field fieldExpression = expression; + Expect("name") .WhenSerializing(fieldExpression) .WhenSerializing(fieldString); @@ -51,14 +54,14 @@ Expect("name") to ease creating `Field`s from expressions there is a static Property class you can use -[source,csharp] +[source,csharp,method-name="usingstaticpropertyfield"] ---- Field fieldString = "name"; ---- but for expressions this is still rather involved -[source,csharp] +[source,csharp,method-name="usingstaticpropertyfield"] ---- var fieldExpression = Infer.Field(p => p.Name); ---- @@ -66,14 +69,14 @@ var fieldExpression = Infer.Field(p => p.Name); this can be even shortened even further using static imports in c 6 i.e. `using static Nest.Static;` -[source,csharp] +[source,csharp,method-name="usingstaticpropertyfield"] ---- fieldExpression = Field(p => p.Name); ---- Now this is much much terser then our first example using the constructor! -[source,csharp] +[source,csharp,method-name="usingstaticpropertyfield"] ---- Expect("name") .WhenSerializing(fieldString) @@ -84,7 +87,7 @@ By default, NEST will camel-case all field names to be more _javascript-y_ using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior -[source,csharp] +[source,csharp,method-name="defaultfieldnameinferrer"] ---- var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); @@ -93,32 +96,32 @@ setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); However string are *always* passed along verbatim -[source,csharp] +[source,csharp,method-name="defaultfieldnameinferrer"] ---- setup.Expect("NaMe").WhenSerializing("NaMe"); ---- if you want the same behavior for expressions simply do nothing in the default inferrer -[source,csharp] +[source,csharp,method-name="defaultfieldnameinferrer"] ---- setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); setup.Expect("Name").WhenSerializing(Field(p => p.Name)); ---- -== Complex field name expressions +=== Complex field name expressions You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ---- When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ---- @@ -126,17 +129,18 @@ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); NOTE: Similarly, LINQ's `.First()` method also works remember these are expressions and not actual code that will be executed -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); + Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); ---- An indexer on a dictionary is assumed to describe a property name -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); @@ -145,46 +149,50 @@ Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metad A cool feature here is that we'll evaluate variables passed to an indexer -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- var variable = "var"; Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); + Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ---- -:multifieldlink: https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html - -If you are using elasticearch's {multifieldlink}[multi_fields], which you really should as they allow +If you are using elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow you to analyze a string in a number of different ways, these _"virtual" sub fields do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that should be mapped. -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); + Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); + Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); + Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); + Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); ---- You can even chain `.Suffix()` calls to any depth! -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ---- Variables passed to suffix will be evaluated as well -[source,csharp] +[source,csharp,method-name="complexfieldnameexpressions"] ---- var suffix = "unanalyzed"; Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); + Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); ---- @@ -193,7 +201,7 @@ to a list of fields. Here we have a list of expressions -[source,csharp] +[source,csharp,method-name="appendingsuffixtoexpressions"] ---- var expressions = new List>> { @@ -206,29 +214,35 @@ var expressions = new List>> and we want to append the suffix "raw" to each -[source,csharp] +[source,csharp,method-name="appendingsuffixtoexpressions"] ---- var fieldExpressions = expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); Expect("name.raw").WhenSerializing(fieldExpressions[0]); + Expect("description.raw").WhenSerializing(fieldExpressions[1]); + Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); + Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); ---- -== Annotations +=== Annotations When using NEST's property attributes you can specify a new name for the properties -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class BuiltIn { [String(Name = "naam")] public string Name { get; set; } } +---- +[source,csharp,method-name="builtinannotiatons"] +---- Expect("naam").WhenSerializing(Field(p => p.Name)); ---- @@ -236,21 +250,24 @@ Starting with NEST 2.x we also ask the serializer if it can resolve the property Here we ask the default `JsonNetSerializer` to resolve a property name and it takes the `JsonPropertyAttribute` into account -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class SerializerSpecific { [JsonProperty("nameInJson")] public string Name { get; set; } } +---- +[source,csharp,method-name="serializerspecificannotations"] +---- Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ---- If both a NEST property attribute and a serializer specific attribute are present on a property, NEST takes precedence -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class Both { @@ -258,8 +275,12 @@ public class Both [JsonProperty("nameInJson")] public string Name { get; set; } } +---- +[source,csharp,method-name="nestattributetakesprecedence"] +---- Expect("naam").WhenSerializing(Field(p => p.Name)); + Expect(new { naam = "Martijn Laarman" @@ -269,24 +290,30 @@ Expect(new Resolution of field names is cached per connection settings instance. To demonstrate, take the following simple POCOs -[source,csharp] +[source,csharp,method-name="unknown"] ---- class A { public C C { get; set; } } class B { public C C { get; set; } } class C { public string Name { get; set; } } +---- +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +---- var connectionSettings = TestClient.CreateSettings(forceInMemory: true); + var client = new ElasticClient(connectionSettings); + var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); + var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); ---- Here we have to similary shaped expressions on coming from A and on from B that will resolve to the same field name, as expected -[source,csharp] +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ---- fieldNameOnA.Should().Be("c.name"); @@ -296,7 +323,7 @@ fieldNameOnB.Should().Be("c.name"); now we create a new connectionsettings with a remap for C on class A to `d` now when we resolve the field path for A will be different -[source,csharp] +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ---- var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s .InferMappingFor(m => m @@ -305,20 +332,26 @@ var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modif ); var newClient = new ElasticClient(newConnectionSettings); + fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); + fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); + fieldNameOnA.Should().Be("d.name"); + fieldNameOnB.Should().Be("c.name"); ---- however we didn't break inferrence on the first client instance using its separate connectionsettings -[source,csharp] +[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ---- fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); + fieldNameOnA.Should().Be("c.name"); + fieldNameOnB.Should().Be("c.name"); ---- @@ -334,7 +367,7 @@ To wrap up, the precedence in which field names are inferred is: The following example class will demonstrate this precedence -[source,csharp] +[source,csharp,method-name="unknown"] ---- class Precedence { @@ -365,7 +398,7 @@ class Precedence Here we create a custom serializer that renames any property named `AskSerializer` to `ask` -[source,csharp] +[source,csharp,method-name="unknown"] ---- class CustomSerializer : JsonNetSerializer { @@ -383,7 +416,7 @@ class CustomSerializer : JsonNetSerializer here we provide an explicit rename of a property on connectionsettings using `.Rename()` and all properties that are not mapped verbatim should be uppercased -[source,csharp] +[source,csharp,method-name="precedenceisasexpected"] ---- var usingSettings = WithConnectionSettings(s => s @@ -394,15 +427,19 @@ var usingSettings = WithConnectionSettings(s => s ).WithSerializer(s => new CustomSerializer(s)); usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); + usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); + usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); + usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); + usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); ---- The same naming rules also apply when indexing a document -[source,csharp] +[source,csharp,method-name="precedenceisasexpected"] ---- usingSettings.Expect(new [] { diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc index f0e6b6f369b..fb85a375f6d 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc @@ -1,3 +1,5 @@ +:section-number: 2.3 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -21,7 +23,7 @@ This is a special box type that you can implicitly convert to from the following Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` -[source,csharp] +[source,csharp,method-name="canimplicitlyconverttoid"] ---- Id idFromInt = 1; Id idFromLong = 2L; @@ -40,7 +42,7 @@ There is no implicit conversion from any object to Id but we can call `Id.From`. Imagine your codebase has the following type that we want to index into Elasticsearch -[source,csharp] +[source,csharp,method-name="unknown"] ---- class MyDTO { @@ -53,7 +55,7 @@ class MyDTO By default NEST will try to find a property called `Id` on the class using reflection and create a cached fast func delegate based on the properties getter -[source,csharp] +[source,csharp,method-name="cangetidfromdocument"] ---- var dto = new MyDTO { @@ -68,7 +70,7 @@ Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); Using the connection settings you can specify a different property that NEST should use to infer the document Id. Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property -[source,csharp] +[source,csharp,method-name="cangetidfromdocument"] ---- WithConnectionSettings(x => x .InferMappingFor(m => m @@ -79,10 +81,10 @@ WithConnectionSettings(x => x IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. - Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance - with different inference rules +Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance +with different inference rules -[source,csharp] +[source,csharp,method-name="cangetidfromdocument"] ---- WithConnectionSettings(x => x .InferMappingFor(m => m @@ -96,7 +98,7 @@ WithConnectionSettings(x => x Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` to the name of the property that should be used for the document id -[source,csharp] +[source,csharp,method-name="unknown"] ---- [ElasticsearchType(IdProperty = nameof(Name))] class MyOtherDTO @@ -109,7 +111,7 @@ class MyOtherDTO Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` -[source,csharp] +[source,csharp,method-name="cangetidfromattribute"] ---- var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; @@ -122,7 +124,7 @@ This attribute *is* cached statically/globally, however an inference rule on the still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance that will infer the document id from the property `OtherName`: -[source,csharp] +[source,csharp,method-name="cangetidfromattribute"] ---- WithConnectionSettings(x => x .InferMappingFor(m => m diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc index 586c106ca00..3fbdb39838b 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc @@ -1,17 +1,19 @@ +:section-number: 2.5 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images -= Indices paths +== Indices paths Some API's in elasticsearch take one or many index name or a special "all" marker to send the request to all the indices In nest this is encoded using `Indices` Several types implicitly convert to `Indices` -[source,csharp] +[source,csharp,method-name="implicitconversionfromstring"] ---- Nest.Indices singleIndexFromString = "name"; Nest.Indices multipleIndicesFromString = "name1, name2"; @@ -37,14 +39,18 @@ allWithOthersFromString.Match( to ease creating Field's from expressions there is a static Property class you can use -[source,csharp] +[source,csharp,method-name="usingstaticpropertyfield"] ---- var all = Nest.Indices.All; var many = Nest.Indices.Index("name1", "name2"); + var manyTyped = Nest.Indices.Index().And(); + var singleTyped = Nest.Indices.Index(); + var singleString = Nest.Indices.Index("name1"); + var invalidSingleString = Nest.Indices.Index("name1, name2"); ---- diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc index 75708f8f3e4..421cbf92b5b 100644 --- a/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc @@ -1,12 +1,16 @@ +:section-number: 2.2 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images +== Property Names + Property names resolve to the last token. An example using the `.Suffix()` extension -[source,csharp] +[source,csharp,method-name="propertynamesareresolvedtolasttokenusingsuffix"] ---- Expression> expression = p => p.Name.Suffix("raw"); Expect("raw").WhenSerializing(expression); @@ -14,17 +18,19 @@ Expect("raw").WhenSerializing(expression); And an example using the `.ApplySuffix()` extension on lambda expressions -[source,csharp] +[source,csharp,method-name="propertynamesareresolvedtolasttokenusingapplysuffix"] ---- Expression> expression = p => p.Name; + expression.AppendSuffix("raw"); + Expect("raw").WhenSerializing(expression); ---- Property names cannot contain a `.` in order to prevent the potential for collision with a field that -may have https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html[`multi_fields`] +may have {ref_current}/_multi_fields.html[`multi_fields`] -[source,csharp] +[source,csharp,method-name="stringscontainingdotsisanexception"] ---- Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); ---- diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index 51354e9a7b7..693b7905767 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -1,3 +1,5 @@ +:section-number: 3.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -16,7 +18,7 @@ For these examples, we'll define two POCOS, `Company`, which has a name and a collection of Employees, and `Employee` which has various properties of different types, and itself has a collection of `Employee` types. -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class Company { @@ -41,7 +43,7 @@ public class Employee To create a mapping for our Company type, we can use the fluent API and map each property explicitly -[source,csharp] +[source,csharp,method-name="mappingmanually"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -74,7 +76,7 @@ This is all fine and dandy and useful for some use cases however in most cases this can become verbose and wieldy. The majority of the time you simply just want to map *all* the properties of a POCO in a single go. -[source,csharp] +[source,csharp,method-name="mappingmanually"] ---- var expected = new { @@ -120,7 +122,7 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work -[source,csharp] +[source,csharp,method-name="usingautomap"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -143,7 +145,7 @@ In this example, * Employees as an object and the remaining string properties as strings. -[source,csharp] +[source,csharp,method-name="usingautomap"] ---- var expected = new { @@ -246,7 +248,7 @@ Here we are using AutoMap() to automatically map our company type, but then we'r overriding our employee property and making it a `nested` type, since by default, AutoMap() will infer objects as `object`. -[source,csharp] +[source,csharp,method-name="overridingautomappedproperties"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -284,6 +286,7 @@ var expected = new } } }; + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- @@ -293,7 +296,7 @@ It is also possible to define your mappings using attributes on your POCOS. Whe use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. Here we define the same two types but this time using attributes. -[source,csharp] +[source,csharp,method-name="unknown"] ---- [ElasticsearchType(Name = "company")] public class CompanyWithAttributes @@ -334,13 +337,14 @@ public class EmployeeWithAttributes Then map the types by calling `.AutoMap()` -[source,csharp] +[source,csharp,method-name="usingautomapwithattributes"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms .Map(m => m.AutoMap()) .Map(m => m.AutoMap()) ); + var expected = new { mappings = new @@ -472,6 +476,7 @@ var expected = new } } }; + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- @@ -479,7 +484,7 @@ Just as we were able to override the inferred properties in our earlier example, mappings also take precedence over attributes. Therefore we can also override any mappings applied via any attributes defined on the POCO -[source,csharp] +[source,csharp,method-name="overridingautomappedattributes"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -523,6 +528,7 @@ var descriptor = new CreateIndexDescriptor("myindex") ) ) ); + var expected = new { mappings = new @@ -635,6 +641,7 @@ var expected = new } } }; + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- @@ -651,7 +658,7 @@ Properties on a POCO can be ignored in a few ways: This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` -[source,csharp] +[source,csharp,method-name="unknown"] ---- [ElasticsearchType(Name = "company")] public class CompanyWithAttributesAndPropertiesToIgnore @@ -670,7 +677,7 @@ public class CompanyWithAttributesAndPropertiesToIgnore All of the properties except `Name` have been ignored in the mapping -[source,csharp] +[source,csharp,method-name="ignoringproperties"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -695,11 +702,13 @@ var expected = new } } }; + var settings = WithConnectionSettings(s => s .InferMappingFor(i => i .Ignore(p => p.AnotherPropertyToIgnore) ) ); + settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- @@ -717,7 +726,7 @@ the need to do this, so you can control the recursion depth of `.AutoMap()`. Let's introduce a very simple class, `A`, which itself has a property Child of type `A`. -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class A { @@ -727,7 +736,7 @@ public class A By default, `.AutoMap()` only goes as far as depth 1 -[source,csharp] +[source,csharp,method-name="controllingrecursiondepth"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -737,7 +746,7 @@ var descriptor = new CreateIndexDescriptor("myindex") Thus we do not map properties on the second occurrence of our Child property -[source,csharp] +[source,csharp,method-name="controllingrecursiondepth"] ---- var expected = new { @@ -762,7 +771,7 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); Now lets specify a maxRecursion of 3 -[source,csharp] +[source,csharp,method-name="controllingrecursiondepth"] ---- var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -772,7 +781,7 @@ var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") `.AutoMap()` has now mapped three levels of our Child property -[source,csharp] +[source,csharp,method-name="controllingrecursiondepth"] ---- var expectedWithMaxRecursion = new { @@ -826,7 +835,7 @@ does nothing and acts as a blank canvas for you to implement your own visiting m For instance, lets create a custom visitor that disables doc values for numeric and boolean types. (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor { @@ -846,7 +855,7 @@ public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor Now we can pass an instance of our custom visitor to `.AutoMap()` -[source,csharp] +[source,csharp,method-name="usingacustompropertyvisitor"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -859,7 +868,7 @@ and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBoo it will apply the transformation defined in each `Visit()` respectively, which in this example disables {ref_current}/doc-values.html[doc values]. -[source,csharp] +[source,csharp,method-name="usingacustompropertyvisitor"] ---- var expected = new { @@ -906,18 +915,22 @@ You can even take the visitor approach a step further, and instead of visiting o directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types to an Elasticsearch string (`IStringProperty`). -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); } +---- +[source,csharp,method-name="usingacustompropertyvisitoronpropertyinfo"] +---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms .Map(m => m.AutoMap(new EverythingIsAStringPropertyVisitor())) ); + var expected = new { mappings = new diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index abffb6a6b9c..bfddd8158ea 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -1,15 +1,22 @@ +:section-number: 1.1 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../images -= Choosing the right connection strategy +== Connecting + +Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. + +=== Choosing the right Connection Strategy -[source,csharp] +If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` + +[source,csharp,method-name="instantiateusingalldefaults"] ---- var client = new ElasticLowLevelClient(); -var tokenizers = new TokenizersDescriptor(); ---- If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then @@ -17,36 +24,43 @@ you will need to pass in some instance of `IConnectionConfigurationValues`. The easiest way to do this is: -[source,csharp] +[source,csharp,method-name="instantiatingasinglenodeclient"] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); + var config = new ConnectionConfiguration(node); + var client = new ElasticLowLevelClient(config); ---- -This however is still a non-failover connection. Meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. +This will still be a non-failover connection, meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. -[source,csharp] +[source,csharp,method-name="instantiatingaconnectionpoolclient"] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); + var connectionPool = new SniffingConnectionPool(new[] { node }); + var config = new ConnectionConfiguration(connectionPool); + var client = new ElasticLowLevelClient(config); ---- Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. -Be sure to read more about [Connection Pooling and Cluster Failover here](/elasticsearch-net/cluster-failover.html) +Be sure to read more about <<../connection-pooling/connection-pooling, Connection Pooling and Cluster Failover here>>. -== Options +=== Configuration Options Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: -[source,csharp] +[source,csharp,method-name="specifyingclientoptions"] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); + var connectionPool = new SniffingConnectionPool(new[] { node }); + var config = new ConnectionConfiguration(connectionPool) .DisableDirectStreaming() .BasicAuthentication("user", "pass") @@ -55,75 +69,79 @@ var config = new ConnectionConfiguration(connectionPool) The following is a list of available connection configuration options: -[source,csharp] +[source,csharp,method-name="availableoptions"] ---- var client = new ElasticLowLevelClient(); ---- -Disable automatic proxy detection. Defaults to true. +`DisableAutomaticProxyDetection`: Disable automatic proxy detection. Defaults to true. -Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured -to allow this. See the [http module settings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html) for more info). +`EnableHttpCompression`: Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. +See the {ref_current}/modules-http.html[http module settings] for more info). By default responses are deserialized off stream to the object you tell it to. For debugging purposes it can be very useful to keep a copy of the raw response on the result object. -[source,csharp] +[source,csharp,method-name="availableoptions"] ---- var config = new ConnectionConfiguration() - .DisableAutomaticProxyDetection() .EnableHttpCompression() .DisableDirectStreaming() var result = client.Search>(new { size = 12 }); -var raw = result.ResponseBodyInBytes; ---- -This will only have a value if the client configuration has ExposeRawResponse set +This will only have a value if the client configuration has `DisableDirectStreaming` set + +[source,csharp,method-name="availableoptions"] +---- +var raw = result.ResponseBodyInBytes; +---- Please note that this only make sense if you need a mapped response and the raw response at the same time. If you need a `string` or `byte[]` response simply call: -[source,csharp] +[source,csharp,method-name="availableoptions"] ---- var stringResult = client.Search(new { }); ---- -Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. +* `GlobalQueryStringParameters`: Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. -Sets proxy information on the connection. +* `Proxy`: Sets proxy information on the connection. +* `RequestTimeout`: Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts -(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx). +(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). +* `ThrowExceptions` As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw exceptions. -There are three category of exceptions thay may be thrown: +There are three category of exceptions that may be thrown: -1) ElasticsearchClientException: These are known exceptions, either an exception that occurred in the request pipeline +. **ElasticsearchClientException**: These are known exceptions, either an exception that occurred in the request pipeline (such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property on the response will contain the the actual error that was returned. The inner exception will always contain the root causing exception. -2) UnexpectedElasticsearchClientException: These are unknown exceptions, for instance a response from Elasticsearch not -properly deserialized. These are usually bugs and should be reported. This excpetion also inherits from ElasticsearchClientException +. **UnexpectedElasticsearchClientException**: These are unknown exceptions, for instance a response from Elasticsearch not +properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. -3) Development time exceptions: These are CLR exceptions like ArgumentException, NullArgumentException etc... that are thrown +. **Development time exceptions**: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown when an API in the client is misused. These should not be handled as you want to know about them during development. -Forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well +* `PrettyJson`: forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well -Sets the HTTP basic authentication credentials to specify with all requests. +* `BasicAuthentication(username, password)`: sets the HTTP basic authentication credentials to specify with all requests. -[source,csharp] +[source,csharp,method-name="availableoptions"] ---- config = config - //endhide .GlobalQueryStringParameters(new NameValueCollection()) .Proxy(new Uri("http://myproxy"), "username", "pass") .RequestTimeout(TimeSpan.FromSeconds(4)) @@ -132,42 +150,54 @@ config = config .BasicAuthentication("username", "password") ---- -**Note:** This can alternatively be specified on the node URI directly: +NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: -[source,csharp] +[source,csharp,method-name="availableoptions"] ---- var uri = new Uri("http://username:password@localhost:9200"); var settings = new ConnectionConfiguration(uri); ---- - ...but may become tedious when using connection pooling with multiple nodes. +...but this may become tedious when using connection pooling with multiple nodes. + +=== `OnRequestCompleted` You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. If you have complex logging needs this is a good place to add that in. -[source,csharp] +[source,csharp,method-name="onrequestcompletediscalled"] ---- var counter = 0; + var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); + var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) .OnRequestCompleted(r => counter++); + var client = new ElasticClient(settings); + client.RootNodeInfo(); + counter.Should().Be(1); + client.RootNodeInfoAsync(); + counter.Should().Be(2); ---- -An example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like +[[complex-logging]] +Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` -[source,csharp] +[source,csharp,method-name="usingonrequestcompletedforlogging"] ---- var list = new List(); + var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) //<1> .DisableDirectStreaming() .OnRequestCompleted(response => { @@ -196,30 +226,40 @@ var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) $"{new string('-', 30)}\n"); } }); + list.Add( $"{response.HttpMethod} {response.Uri} \n" + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); + list.Add($"{response.HttpMethod} {response.Uri}"); + list.Add($"Status: {response.HttpStatusCode}\n" + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + $"{new string('-', 30)}\n"); + list.Add($"Status: {response.HttpStatusCode}\n" + $"{new string('-', 30)}\n"); + var client = new ElasticClient(settings); + var syncResponse = client.Search(s => s .Scroll("2m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); + list.Count.Should().Be(2); + var asyncResponse = await client.SearchAsync(s => s .Scroll("2m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); + list.Count.Should().Be(4); + list.ShouldAllBeEquivalentTo(new [] { "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", @@ -228,36 +268,37 @@ list.ShouldAllBeEquivalentTo(new [] "Status: 200\n------------------------------\n" }); ---- +<1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` to make the actual request -== Configuring SSL +=== Configuring SSL SSL must be configured outside of the client using .NET's -[ServicePointManager](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx) -class and setting the [ServerCertificateValidationCallback](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx) +http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] +class and setting the http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx[ServerCertificateValidationCallback] property. The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: -[source,csharp] +[source,csharp,method-name="configuringssl"] ---- ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; ---- -However, this will accept all requests from the AppDomain to untrusted SSL sites, -therefore we recommend doing some minimal introspection on the passed in certificate. +However, this will accept **all** requests from the AppDomain to untrusted SSL sites, +therefore **we recommend doing some minimal introspection on the passed in certificate.** -== Overriding default Json.NET behavior +=== Overriding default Json.NET behavior Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful -Create a subclass of the `JsonNetSerializer` +Create a subclass of the `JsonNetSerializer` Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` You can inject contract resolved converters by implementing the ContractConverters property This can be much faster then registering them on JsonSerializerSettings.Converters -[source,csharp] +[source,csharp,method-name="unknown"] ---- public class MyJsonNetSerializer : JsonNetSerializer { @@ -265,30 +306,38 @@ public class MyJsonNetSerializer : JsonNetSerializer public int CallToModify { get; set; } = 0; protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; public int CallToContractConverter { get; set; } = 0; - protected override IList> ContractConverters => new List>() + protected override IList> ContractConverters => new List> { - { t => { + t => { CallToContractConverter++; return null; - } } + } }; } ---- -You can then register a factory on ConnectionSettings to create an instance of your subclass instead. -This is called once per instance of ConnectionSettings. +You can then register a factory on `ConnectionSettings` to create an instance of your subclass instead. +This is **_called once per instance_** of ConnectionSettings. -[source,csharp] +[source,csharp,method-name="modifyjsonserializersettingsiscalled"] ---- var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); + var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); + var client = new ElasticClient(settings); + client.RootNodeInfo(); + client.RootNodeInfo(); + var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; + serializer.CallToModify.Should().BeGreaterThan(0); + serializer.SerializeToString(new Project { }); + serializer.CallToContractConverter.Should().BeGreaterThan(0); ---- diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 2a748ce8831..6e3700b2cda 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -1,3 +1,5 @@ +:section-number: 1.2 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -8,18 +10,22 @@ If you are using an IOC container its always useful to know the best practices around the lifetime of your objects -In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe -so sharing this instance over threads is ok. +In general we advise folks to register their ElasticClient instances as singletons. The client is thread safe +so sharing an instance between threads is fine. Zooming in however the actual moving part that benefits the most from being static for most of the duration of your -application is ConnectionSettings. Caches are per ConnectionSettings. +application is `ConnectionSettings`; caches are __per__ `ConnectionSettings`. + +In some applications it could make perfect sense to have multiple singleton `ElasticClient`'s registered with different +connection settings. e.g if you have 2 functionally isolated Elasticsearch clusters. -In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different -connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. +NOTE: Due to the semantic versioning of NEST and the alignment of versions to Elasticsearch, all instances of `ElasticClient` and thus +Elasticsearch that are connected to must be on the same major version i.e. it is not possible to have both an `ElasticClient` to connect to +Elasticsearch 1.x and 2.x in the same application as the former would require NEST 1.x and the latter, NEST 2.x. Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types -[source,csharp] +[source,csharp,method-name="unknown"] ---- class AConnectionSettings : ConnectionSettings { @@ -59,7 +65,7 @@ class AConnection : InMemoryConnection `ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` -[source,csharp] +[source,csharp,method-name="initialdisposestate"] ---- var connection = new AConnection(); var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); @@ -69,15 +75,20 @@ connectionPool.IsDisposed.Should().BeFalse(); connection.IsDisposed.Should().BeFalse(); ---- -Disposing the ConnectionSettings will dispose the `IConnectionPool` and `IConnection` it has a hold of +Disposing `ConnectionSettings` will dispose the `IConnectionPool` and `IConnection` it has a hold of -[source,csharp] +[source,csharp,method-name="disposingsettingsdisposesmovingparts"] ---- var connection = new AConnection(); + var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); + var settings = new AConnectionSettings(connectionPool, connection); + settings.IsDisposed.Should().BeTrue(); + connectionPool.IsDisposed.Should().BeTrue(); + connection.IsDisposed.Should().BeTrue(); ---- diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index e52a6e02b06..bba14d4cf53 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -1,18 +1,31 @@ +:section-number: 1.3 + :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../images -= Post data +== Post data +The low level client allows you to post a `string` or `byte[]` array directly. On top of this if you pass a collection of `strings` or `objects` they will be serialized in Elasticsearch's special bulk/multi format. -Even though the argument for postData on the low level client takes a PostData +Even though the argument for `PostData` on the low level client takes a `PostData` You can rely on C implicit conversion to abstract the notion of PostData completely. -You can implicitly convert from the following types. +You can implicitly convert from the following types + +* `string` + +* `byte[]` + +* collection of `string` + +* collection of `object` -[source,csharp] +* `object` + +[source,csharp,method-name="implicitconversions"] ---- var fromString = ImplicitlyConvertsFrom(@string); @@ -22,12 +35,22 @@ var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); var fromObject = ImplicitlyConvertsFrom(@object); ---- -postData Bytes will always be set if it originated from a byte +PostData bytes will always be set if it originated from a byte -[source,csharp] +[source,csharp,method-name="implicitconversions"] ---- fromByteArray.WrittenBytes.Should().BeSameAs(bytes); +---- +[source,csharp,method-name="writescorrectlyusingbothlowandhighlevelsettings"] +---- +await this.AssertOn(new ConnectionSettings()); + +await this.AssertOn(new ConnectionConfiguration()); +---- + +[source,csharp,method-name="implicitconversions"] +---- fromString.Type.Should().Be(PostType.LiteralString); fromByteArray.Type.Should().Be(PostType.ByteArray); fromListOfString.Type.Should().Be(PostType.EnumerableOfString); @@ -43,74 +66,92 @@ fromByteArray.Type.Should().Be(PostType.ByteArray); fromListOfString.Type.Should().Be(PostType.EnumerableOfString); fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); fromObject.Type.Should().Be(PostType.Serializable); -await this.AssertOn(new ConnectionSettings()); -await this.AssertOn(new ConnectionConfiguration()); ---- Although each implicitly types behaves slightly differently -[source,csharp] +[source,csharp,method-name="asserton"] ---- -await Post(()=>@string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); +await Post(() => @string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); -await Post(()=>bytes, writes: bytes, storesBytes: true, settings: settings); +await Post(() => bytes, writes: bytes, storesBytes: true, settings: settings); ---- When passing a list of strings we assume its a list of valid serialized json that we join with newlinefeeds making sure there is a trailing linefeed -[source,csharp] +[source,csharp,method-name="asserton"] ---- -await Post(()=>listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); +await Post(() => listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); ---- When passing a list of object we assume its a list of objects we need to serialize individually to json and join with newlinefeeds aking sure there is a trailing linefeed -[source,csharp] +[source,csharp,method-name="asserton"] ---- -await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); +await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); ---- In all other cases postdata is serialized as is. -[source,csharp] +[source,csharp,method-name="asserton"] ---- -await Post(()=>@object, writes: objectJson, storesBytes: false, settings: settings); +await Post(() => @object, writes: objectJson, storesBytes: false, settings: settings); ---- If you want to maintain a copy of the request that went out use the following settings -[source,csharp] +[source,csharp,method-name="asserton"] ---- settings = new ConnectionSettings().DisableDirectStreaming(); ---- by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream -so we can get a hold of the serialized bytes +so we can get hold of the serialized bytes -[source,csharp] +[source,csharp,method-name="asserton"] ---- -await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); +await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); ---- this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` -[source,csharp] +[source,csharp,method-name="asserton"] +---- +await Post(() => @object, writes: objectJson, storesBytes: true, settings: settings); ---- -await Post(()=>@object, writes: objectJson, storesBytes: true, settings: settings); +[source,csharp,method-name="post"] +---- PostAssert(postData(), writes, storesBytes, settings); + await PostAssertAsync(postData(), writes, storesBytes, settings); +---- + +[source,csharp,method-name="postassert"] +---- postData.Write(ms, settings); + var sentBytes = ms.ToArray(); + sentBytes.Should().Equal(writes); + postData.WrittenBytes.Should().NotBeNull(); + postData.WrittenBytes.Should().BeNull(); +---- + +[source,csharp,method-name="postassertasync"] +---- await postData.WriteAsync(ms, settings); + var sentBytes = ms.ToArray(); + sentBytes.Should().Equal(writes); + postData.WrittenBytes.Should().NotBeNull(); + postData.WrittenBytes.Should().BeNull(); ---- diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 84d5902210c..5d88340a2a3 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -6,7 +6,7 @@ Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface -[source,csharp] +[source,csharp,method-name="descriptorshavetobemarkedwithidescriptor"] ---- var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() @@ -20,12 +20,13 @@ descriptors.Should().BeEmpty(); Methods taking a func should have that func return an interface -[source,csharp] +[source,csharp,method-name="selectorsreturninterface"] ---- var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) select t; + var selectorMethods = from d in descriptors from m in d.GetMethods() @@ -51,6 +52,7 @@ var selectorMethods = let lastArgIsNotInterface = !secondFuncArg.IsInterface() where lastArgIsNotInterface select $"{m.Name} on {m.DeclaringType.Name}"; + selectorMethods.Should().BeEmpty(); ---- diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index 7edaffb58e8..b951bd93294 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -4,40 +4,57 @@ :imagesdir: ../images -[source,csharp] +[source,csharp,method-name="consistentinitializerparameternames"] ---- -var fluentParametersNotNamedSelector = - from m in typeof (IElasticClient).GetMethods() - from p in m.GetParameters() - where p.ParameterType.BaseType() == typeof (MulticastDelegate) - where !p.Name.Equals("selector") - select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'selector' but has a name of '{p.Name}'"; -fluentParametersNotNamedSelector.Should().BeEmpty(); var requestParametersNotNamedRequest = from m in typeof(IElasticClient).GetMethods() from p in m.GetParameters() where typeof(IRequest).IsAssignableFrom(p.ParameterType) where !p.Name.Equals("request") select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'request' but has a name of '{p.Name}'"; + requestParametersNotNamedRequest.Should().BeEmpty(); +---- + +[source,csharp,method-name="initializerrequestsarenotoptional"] +---- var requestParameters = (from m in typeof(IElasticClient).GetMethods() from p in m.GetParameters() where typeof(IRequest).IsAssignableFrom(p.ParameterType) select p).ToList(); + requestParameter.HasDefaultValue.Should().BeFalse(); +---- + +[source,csharp,method-name="concreteclientoptionalparametersmatchinterfaceclient"] +---- var concreteMethodParametersDoNotMatchInterface = new List(); + var interfaceMap = typeof(ElasticClient).GetInterfaceMap(typeof(IElasticClient)); + var indexOfInterfaceMethod = Array.IndexOf(interfaceMap.InterfaceMethods, interfaceMethodInfo); + var concreteMethod = interfaceMap.TargetMethods[indexOfInterfaceMethod]; + var concreteParameters = concreteMethod.GetParameters(); + var interfaceParameters = interfaceMethodInfo.GetParameters(); + var parameterInfo = concreteParameters[i]; + var interfaceParameter = interfaceParameters[i]; + parameterInfo.Name.Should().Be(interfaceParameter.Name); + concreteMethodParametersDoNotMatchInterface.Add( $"'{interfaceParameter.Name}' parameter on concrete implementation of '{nameof(ElasticClient)}.{interfaceMethodInfo.Name}' to {(interfaceParameter.HasDefaultValue ? string.Empty : "NOT")} be optional"); + concreteMethodParametersDoNotMatchInterface.Should().BeEmpty(); +---- + +[source,csharp,method-name="consistentoptionalparametersforsyncandasyncmethods"] +---- var methodGroups = from methodInfo in typeof(IElasticClient).GetMethods() where @@ -48,16 +65,33 @@ var methodGroups = let method = new MethodWithRequestParameter(methodInfo) group method by method.Name into methodGroup select methodGroup; + var parameters = asyncMethod.MethodInfo.GetParameters(); + var syncMethod = methodGroup.First(g => !g.IsAsync && g.MethodType == asyncMethod.MethodType && g.MethodInfo.GetParameters().Length == parameters.Length && (!asyncMethod.MethodInfo.IsGenericMethod || g.MethodInfo.GetGenericArguments().Length == asyncMethod.MethodInfo.GetGenericArguments().Length)); + asyncMethod.Parameter.HasDefaultValue.Should().Be(syncMethod.Parameter.HasDefaultValue, $"sync and async versions of {asyncMethod.MethodType} '{nameof(ElasticClient)}{methodGroup.Key}' should match"); +---- +[source,csharp,method-name="consistentfluentparameternames"] +---- +var fluentParametersNotNamedSelector = + from m in typeof (IElasticClient).GetMethods() + from p in m.GetParameters() + where p.ParameterType.BaseType() == typeof (MulticastDelegate) + where !p.Name.Equals("selector") + select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'selector' but has a name of '{p.Name}'"; +fluentParametersNotNamedSelector.Should().BeEmpty(); +---- + +[source,csharp,method-name="unknown"] +---- private class MethodWithRequestParameter { public string Name { get; } diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 47ca8b2afa4..348a52b8370 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -12,7 +12,7 @@ NEST uses the following naming conventions (with _some_ exceptions). Abstract class names should end with a `Base` suffix -[source,csharp] +[source,csharp,method-name="abstractclassnamesendwithbase"] ---- var exceptions = new[] { @@ -28,15 +28,17 @@ abstractClasses.Should().BeEmpty(); Class names that end with `Base` suffix are abstract -[source,csharp] +[source,csharp,method-name="classnamecontainsbaseshouldbeabstract"] ---- var exceptions = new[] { typeof(DateMath) }; + var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() .Where(t => t.IsClass() && !exceptions.Contains(t)) .Where(t => t.Name.Split('`')[0].EndsWith("Base")) .Where(t => !t.IsAbstractClass()) .Select(t => t.Name.Split('`')[0]) .ToList(); + baseClassesNotAbstract.Should().BeEmpty(); ---- @@ -44,28 +46,32 @@ baseClassesNotAbstract.Should().BeEmpty(); Request class names should end with `Request` -[source,csharp] +[source,csharp,method-name="requestclassnamesendwithrequest"] ---- var types = typeof(IRequest).Assembly().GetTypes(); + var requests = types .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) .Select(t => t.Name.Split('`')[0]) .ToList(); + requests.Should().BeEmpty(); ---- Response class names should end with `Response` -[source,csharp] +[source,csharp,method-name="responseclassnamesendwithresponse"] ---- var types = typeof(IRequest).Assembly().GetTypes(); + var responses = types .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) .Select(t => t.Name.Split('`')[0]) .ToList(); + responses.Should().BeEmpty(); ---- @@ -74,7 +80,7 @@ e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => There are a few exceptions to this rule, most notably the `Cat` prefixed requests and the `Exists` requests. -[source,csharp] +[source,csharp,method-name="paritybetweenrequestsandresponses"] ---- var exceptions = new[] //<1> { @@ -112,7 +118,9 @@ var exceptions = new[] //<1> typeof(IndicesShardStoresRequest), typeof(RenderSearchTemplateRequest) }; + var types = typeof(IRequest).Assembly().GetTypes(); + var requests = new HashSet(types .Where(t => t.IsClass() && @@ -122,9 +130,11 @@ var requests = new HashSet(types && !exceptions.Contains(t)) .Select(t => t.Name.Split('`')[0].Replace("Request", "")) ); + var responses = types .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) .Select(t => t.Name.Split('`')[0].Replace("Response", "")); + requests.Except(responses).Should().BeEmpty(); ---- <1> _Exceptions to the rule_ diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index d0ea04540ee..ebc00ab80d1 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -4,35 +4,57 @@ :imagesdir: ../images -[source,csharp] +[source,csharp,method-name="staticqueryexposesall"] ---- -var properties = from p in QueryProperties - let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) - where a.Count() != 1 - select p; -properties.Should().BeEmpty(); var staticProperties = from p in typeof(Query<>).GetMethods() let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name select name; + var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name); + staticProperties.Distinct().Should().Contain(placeHolders.Distinct()); +---- + +[source,csharp,method-name="fluentdescriptorexposesall"] +---- var fluentMethods = from p in typeof(QueryContainerDescriptor<>).GetMethods() let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name select name; + var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name); + fluentMethods.Distinct().Should().Contain(placeHolders.Distinct()); +---- + +[source,csharp,method-name="visitorvisitsall"] +---- var skipQueryImplementations = new[] { typeof(IFieldNameQuery), typeof(IFuzzyQuery<,>), typeof(IConditionlessQuery) }; + var queries = typeof(IQuery).Assembly().ExportedTypes .Where(t => t.IsInterface() && typeof(IQuery).IsAssignableFrom(t)) .Where(t => !skipQueryImplementations.Contains(t)) .ToList(); + queries.Should().NotBeEmpty(); + var visitMethods = typeof(IQueryVisitor).GetMethods().Where(m => m.Name == "Visit"); + visitMethods.Should().NotBeEmpty(); + var missingTypes = from q in queries let visitMethod = visitMethods.FirstOrDefault(m => m.GetParameters().First().ParameterType == q) where visitMethod == null select q; + missingTypes.Should().BeEmpty(); ---- +[source,csharp,method-name="interfacepropertiesmustbemarkedexplicitly"] +---- +var properties = from p in QueryProperties + let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) + where a.Count() != 1 + select p; +properties.Should().BeEmpty(); +---- + diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index 31d535904bc..73b686ca5ff 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -6,7 +6,7 @@ Our Json.NET contract resolver picks up attributes set on the interface -[source,csharp] +[source,csharp,method-name="seesinterfaceproperties"] ---- var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(pool, new InMemoryConnection()); diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index c2fd6b6f53e..ec684ae595c 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -29,13 +29,15 @@ The units supported are as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. -Be sure to read the elasticsearch documentation {ref_current}/mapping-date-format.htmldate-math[on this subject here] +:datemath: {ref_current}/common-options.html#date-math + +Be sure to read the elasticsearch documentation {datemath}[on this subject here] === Simple Expressions You can create simple expressions using any of the static methods on `DateMath` -[source,csharp] +[source,csharp,method-name="simpleexpressions"] ---- Expect("now").WhenSerializing(Nest.DateMath.Now); @@ -44,21 +46,21 @@ Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTim strings implicitly convert to `DateMath` -[source,csharp] +[source,csharp,method-name="simpleexpressions"] ---- Expect("now").WhenSerializing("now"); ---- but are lenient to bad math expressions -[source,csharp] +[source,csharp,method-name="simpleexpressions"] ---- var nonsense = "now||*asdaqwe"; ---- the resulting date math will assume the whole string is the anchor -[source,csharp] +[source,csharp,method-name="simpleexpressions"] ---- Expect(nonsense).WhenSerializing(nonsense) .Result(dateMath => ((IDateMath)dateMath) @@ -71,14 +73,14 @@ Expect(nonsense).WhenSerializing(nonsense) `DateTime` also implicitly convert to simple date math expressions -[source,csharp] +[source,csharp,method-name="simpleexpressions"] ---- var date = new DateTime(2015, 05, 05); ---- the anchor will be an actual `DateTime`, even after a serialization/deserialization round trip -[source,csharp] +[source,csharp,method-name="simpleexpressions"] ---- Expect("2015-05-05T00:00:00").WhenSerializing(date) .Result(dateMath => ((IDateMath)dateMath) @@ -93,21 +95,21 @@ Expect("2015-05-05T00:00:00").WhenSerializing(date) Ranges can be chained on to simple expressions -[source,csharp] +[source,csharp,method-name="complexexpressions"] ---- Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); ---- Including multiple operations -[source,csharp] +[source,csharp,method-name="complexexpressions"] ---- Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); ---- A rounding value can be chained to the end of the expression, after which no more ranges can be appended -[source,csharp] +[source,csharp,method-name="complexexpressions"] ---- Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); ---- @@ -115,7 +117,7 @@ Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeS When anchoring dates, a `||` needs to be appended as clear separator between the anchor and ranges. Again, multiple ranges can be chained -[source,csharp] +[source,csharp,method-name="complexexpressions"] ---- Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); ---- diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index 749db99bc69..fa1fdd4df2c 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -17,7 +17,7 @@ NEST uses `Time` to strongly type this and there are several ways to construct o The most straight forward way to construct a `Time` is through its constructor -[source,csharp] +[source,csharp,method-name="constructor"] ---- var unitString = new Time("2d"); var unitComposed = new Time(2, Nest.TimeUnit.Day); @@ -37,7 +37,7 @@ When serializing Time constructed from the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` -[source,csharp] +[source,csharp,method-name="constructor"] ---- Expect("2d") .WhenSerializing(unitString) @@ -48,7 +48,7 @@ Expect("2d") The `Milliseconds` property on `Time` is calculated even when not using the constructor that takes a double -[source,csharp] +[source,csharp,method-name="constructor"] ---- unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); @@ -61,45 +61,66 @@ unitString.Milliseconds.Should().Be(1000*60*60*24*2); Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` -[source,csharp] +[source,csharp,method-name="implicitconversion"] ---- Time oneAndHalfYear = "1.5y"; + Time twoWeeks = TimeSpan.FromDays(14); + Time twoDays = 1000*60*60*24*2; + Expect("1.5y").WhenSerializing(oneAndHalfYear); + Expect("2w").WhenSerializing(twoWeeks); + Expect("2d").WhenSerializing(twoDays); +---- + +[source,csharp,method-name="equalityandcomparable"] +---- Time oneAndHalfYear = "1.5y"; + Time twoWeeks = TimeSpan.FromDays(14); + Time twoDays = 1000*60*60*24*2; ---- Again, the `Milliseconds` property is calculated on `Time`, allowing you to do comparisons -[source,csharp] +[source,csharp,method-name="equalityandcomparable"] ---- oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); twoWeeks.Milliseconds.Should().BeGreaterThan(1); + oneAndHalfYear.Should().BeGreaterThan(twoWeeks); + (oneAndHalfYear > twoWeeks).Should().BeTrue(); + (oneAndHalfYear >= twoWeeks).Should().BeTrue(); + (twoDays >= new Time("2d")).Should().BeTrue(); + twoDays.Should().BeLessThan(twoWeeks); + (twoDays < twoWeeks).Should().BeTrue(); + (twoDays <= twoWeeks).Should().BeTrue(); + (twoDays <= new Time("2d")).Should().BeTrue(); ---- And assert equality -[source,csharp] +[source,csharp,method-name="equalityandcomparable"] ---- twoDays.Should().Be(new Time("2d")); (twoDays == new Time("2d")).Should().BeTrue(); + (twoDays != new Time("2.1d")).Should().BeTrue(); + (new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue(); ---- @@ -108,18 +129,26 @@ twoDays.Should().Be(new Time("2d")); Time units are specified as a union of either a `DateInterval` or `Time`, both of which implicitly convert to the `Union` of these two. -[source,csharp] +[source,csharp,method-name="usinginterval"] ---- Expect("month").WhenSerializing>(DateInterval.Month); Expect("day").WhenSerializing>(DateInterval.Day); + Expect("hour").WhenSerializing>(DateInterval.Hour); + Expect("minute").WhenSerializing>(DateInterval.Minute); + Expect("quarter").WhenSerializing>(DateInterval.Quarter); + Expect("second").WhenSerializing>(DateInterval.Second); + Expect("week").WhenSerializing>(DateInterval.Week); + Expect("year").WhenSerializing>(DateInterval.Year); + Expect("2d").WhenSerializing>((Time)"2d"); + Expect("1.16w").WhenSerializing>((Time)TimeSpan.FromDays(8.1)); ---- diff --git a/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc b/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc index c44ca22247a..093060e75e6 100644 --- a/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc +++ b/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc @@ -4,7 +4,113 @@ :imagesdir: ../../../images -[source,csharp] +[source,javascript,method-name="expectjson"] +.Example json output +---- +[ + { + "index": { + "_type": "project", + "_id": "Durgan LLC" + } + }, + { + "name": "Koch, Collier and Mohr", + "state": "BellyUp", + "startedOn": "2015-01-01T00:00:00", + "lastActivity": "0001-01-01T00:00:00", + "leadDeveloper": { + "gender": "Male", + "id": 0, + "firstName": "Martijn", + "lastName": "Laarman" + }, + "location": { + "lat": 42.1523, + "lon": -80.321 + } + }, + { + "update": { + "_type": "project", + "_id": "Durgan LLC" + } + }, + { + "doc": { + "leadDeveloper": { + "firstName": "martijn" + } + } + }, + { + "create": { + "_type": "project", + "_id": "Durgan LLC1" + } + }, + { + "name": "Koch, Collier and Mohr", + "state": "BellyUp", + "startedOn": "2015-01-01T00:00:00", + "lastActivity": "0001-01-01T00:00:00", + "leadDeveloper": { + "gender": "Male", + "id": 0, + "firstName": "Martijn", + "lastName": "Laarman" + }, + "location": { + "lat": 42.1523, + "lon": -80.321 + } + }, + { + "delete": { + "_type": "project", + "_id": "Durgan LLC1" + } + } +] +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +d => d +.Index(CallIsolatedValue) +.Index(b => b.Document(Project.Instance)) +.Update(b => b.Doc(new { leadDeveloper = new { firstName = "martijn" } }).Id(Project.Instance.Name)) +.Create(b => b.Document(Project.Instance).Id(Project.Instance.Name + "1")) +.Delete(b=>b.Id(Project.Instance.Name + "1")) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new BulkRequest(CallIsolatedValue) +{ + Operations = new List + { + new BulkIndexOperation(Project.Instance), + new BulkUpdateOperation(Project.Instance) + { + Doc = new { leadDeveloper = new { firstName = "martijn" } } + }, + new BulkCreateOperation(Project.Instance) + { + Id = Project.Instance.Name + "1" + }, + new BulkDeleteOperation(Project.Instance.Name + "1"), + } +} +---- + +=== Handling Responses + +[source,csharp,method-name="expectresponse"] ---- response.Took.Should().BeGreaterThan(0); response.Errors.Should().BeFalse(); @@ -19,31 +125,7 @@ item.IsValid.Should().BeTrue(); item.Shards.Should().NotBeNull(); item.Shards.Total.Should().BeGreaterThan(0); item.Shards.Successful.Should().BeGreaterThan(0); -var p1 = this.Client.Source(Project.Instance.Name, p=>p.Index(CallIsolatedValue)); +var p1 = this.Client.Source(Project.Instance.Name, p => p.Index(CallIsolatedValue)); p1.LeadDeveloper.FirstName.Should().Be("martijn"); - -d => d -.Index(CallIsolatedValue) -.Index(b => b.Document(Project.Instance)) -.Update(b => b.Doc(new { leadDeveloper = new { firstName = "martijn" } }).Id(Project.Instance.Name)) -.Create(b => b.Document(Project.Instance).Id(Project.Instance.Name + "1")) -.Delete(b=>b.Id(Project.Instance.Name + "1")) - -new BulkRequest(CallIsolatedValue) - { -Operations = new List -{ - new BulkIndexOperation(Project.Instance), - new BulkUpdateOperation(Project.Instance) - { - Doc = new { leadDeveloper = new { firstName = "martijn" } } - }, - new BulkCreateOperation(Project.Instance) - { - Id = Project.Instance.Name + "1" - }, - new BulkDeleteOperation(Project.Instance.Name + "1"), -} - } ---- diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 694413cee35..5888beec998 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -1,39 +1,37 @@ [[elasticsearch-net-reference]] -= Elasticsearch.Net and NEST documentation:.NET Elasticsearch clients += Elasticsearch.Net and NEST, the .NET Elasticsearch clients include::intro.asciidoc[] -include::aggregations/bucket/children/children-aggregation-mapping.asciidoc[] +include::client-concepts/low-level/connecting.asciidoc[] -include::aggregations/bucket/children/children-aggregation-usage.asciidoc[] +include::client-concepts/low-level/lifetimes.asciidoc[] -include::aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] +include::client-concepts/low-level/post-data.asciidoc[] -include::aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] +include::client-concepts/high-level/inference/field-inference.asciidoc[] -include::aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] +include::client-concepts/high-level/inference/property-inference.asciidoc[] -include::aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] +include::client-concepts/high-level/inference/ids-inference.asciidoc[] -include::aggregations/writing-aggregations.asciidoc[] +include::client-concepts/high-level/inference/document-paths.asciidoc[] -include::client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc[] +include::client-concepts/high-level/inference/indices-paths.asciidoc[] -include::client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc[] +include::client-concepts/high-level/mapping/auto-map.asciidoc[] -include::client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc[] +include::client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc[] + +include::client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc[] include::client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc[] include::client-concepts/connection-pooling/building-blocks/transports.asciidoc[] -include::client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc[] - -include::client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc[] - -include::client-concepts/connection-pooling/failover/falling-over.asciidoc[] +include::client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc[] -include::client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc[] +include::client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc[] include::client-concepts/connection-pooling/pinging/first-usage.asciidoc[] @@ -49,12 +47,6 @@ include::client-concepts/connection-pooling/request-overrides/respects-force-nod include::client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc[] -include::client-concepts/connection-pooling/round-robin/round-robin.asciidoc[] - -include::client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc[] - -include::client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc[] - include::client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc[] include::client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc[] @@ -63,25 +55,111 @@ include::client-concepts/connection-pooling/sniffing/on-startup.asciidoc[] include::client-concepts/connection-pooling/sniffing/role-detection.asciidoc[] -include::client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc[] +include::aggregations/writing-aggregations.asciidoc[] -include::client-concepts/high-level/inferrence/document-paths.asciidoc[] +include::aggregations/bucket/children/children-aggregation-mapping.asciidoc[] -include::client-concepts/high-level/inferrence/field-inference.asciidoc[] +include::aggregations/bucket/children/children-aggregation-usage.asciidoc[] -include::client-concepts/high-level/inferrence/ids-inference.asciidoc[] +include::aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] -include::client-concepts/high-level/inferrence/indices-paths.asciidoc[] +include::aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] -include::client-concepts/high-level/inferrence/property-inference.asciidoc[] +include::aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] -include::client-concepts/high-level/mapping/auto-map.asciidoc[] +include::aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] -include::client-concepts/low-level/connecting.asciidoc[] +include::aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc[] -include::client-concepts/low-level/lifetimes.asciidoc[] +include::aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc[] -include::client-concepts/low-level/post-data.asciidoc[] +include::aggregations/bucket/global/global-aggregation-usage.asciidoc[] + +include::aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc[] + +include::aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc[] + +include::aggregations/bucket/missing/missing-aggregation-usage.asciidoc[] + +include::aggregations/bucket/nested/nested-aggregation-usage.asciidoc[] + +include::aggregations/bucket/range/range-aggregation-usage.asciidoc[] + +include::aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc[] + +include::aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc[] + +include::aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc[] + +include::aggregations/bucket/terms/terms-aggregation-usage.asciidoc[] + +include::aggregations/metric/average/average-aggregation-usage.asciidoc[] + +include::aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc[] + +include::aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc[] + +include::aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc[] + +include::aggregations/metric/max/max-aggregation-usage.asciidoc[] + +include::aggregations/metric/min/min-aggregation-usage.asciidoc[] + +include::aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc[] + +include::aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc[] + +include::aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc[] + +include::aggregations/metric/stats/stats-aggregation-usage.asciidoc[] + +include::aggregations/metric/sum/sum-aggregation-usage.asciidoc[] + +include::aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc[] + +include::aggregations/metric/value-count/value-count-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc[] + +include::client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc[] + +include::client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc[] + +include::client-concepts/connection-pooling/failover/falling-over.asciidoc[] + +include::client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc[] + +include::client-concepts/connection-pooling/round-robin/round-robin.asciidoc[] + +include::client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc[] + +include::client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc[] include::code-standards/descriptors.asciidoc[] @@ -105,3 +183,5 @@ include::query-dsl/compound/and/and-query-usage.asciidoc[] include::query-dsl/geo/distance/distance-units.asciidoc[] +include::search/suggesters/suggest-api.asciidoc[] + diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index f79f8c83c0a..8ada21048bc 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -9,7 +9,7 @@ Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses -[source,csharp] +[source,csharp,method-name="verboseway"] ---- var searchResults = this.Client.Search(s => s .Query(q => q @@ -34,7 +34,7 @@ image::{imagesdir}/hadouken-indentation.jpg[dead indent] For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. The previous example now becomes the following with the fluent API -[source,csharp] +[source,csharp,method-name="usingoperator"] ---- var searchResults = this.Client.Search(s => s .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) @@ -43,7 +43,7 @@ var searchResults = this.Client.Search(s => s or, using the object initializer syntax -[source,csharp] +[source,csharp,method-name="usingoperator"] ---- searchResults = this.Client.Search(new SearchRequest { @@ -98,7 +98,7 @@ bool |___term .... -[source,csharp] +[source,csharp,method-name="joinsmustwithmustnot"] ---- Assert( q => q.Query() && q.Query() && q.Query() && !q.Query(), @@ -108,7 +108,9 @@ Assert( c.Bool.Must.Should().HaveCount(3); c.Bool.MustNot.Should().HaveCount(1); }); + c.Bool.Must.Should().HaveCount(3); + c.Bool.MustNot.Should().HaveCount(1); ---- @@ -154,13 +156,21 @@ Here we demonstrate that two locked `bool` queries are not combined neither are two `bool` queries where either the left or the right query is locked -[source,csharp] +[source,csharp,method-name="assertdoesnotjoinontolockedbool"] ---- c.Bool.Should.Should().HaveCount(2); + var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); + nestedBool.Bool.Should.Should().HaveCount(1); + nestedBool.Bool.Name.Should().Be(firstName); +---- + +[source,csharp,method-name="assert"] +---- assert(fluent.InvokeQuery(new QueryContainerDescriptor())); + assert((QueryContainer)ois); ---- diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index 774177daa51..177cc9aa865 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript] +[source,javascript,method-name="queryjson"] .Example json output ---- { @@ -27,7 +27,9 @@ } ---- -[source,csharp] +=== Object Initializer Syntax Example + +[source,csharp,method-name="queryinitializer"] ---- new AndQuery() { diff --git a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc index e368f74ddf2..5a81f873703 100644 --- a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc @@ -18,7 +18,7 @@ NEST uses `Distance` to strongly type distance units and there are several ways The most straight forward way to construct a `Distance` is through its constructor -[source,csharp] +[source,csharp,method-name="constructor"] ---- var unitComposed = new Nest.Distance(25); var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); @@ -26,7 +26,7 @@ var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); `Distance` serializes to a string composed of a factor and distance unit -[source,csharp] +[source,csharp,method-name="constructor"] ---- Expect("25.0m") .WhenSerializing(unitComposed) @@ -38,10 +38,12 @@ Expect("25.0m") Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. If no `DistanceUnit` is specified, the default distance unit is meters -[source,csharp] +[source,csharp,method-name="implicitconversion"] ---- Nest.Distance distanceString = "25"; + Nest.Distance distanceStringWithUnits = "25m"; + Expect(new Nest.Distance(25)) .WhenSerializing(distanceString) .WhenSerializing(distanceStringWithUnits); @@ -55,28 +57,28 @@ A number of distance units are supported, from millimeters to nautical miles `mm` (Millimeters) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); ---- `cm` (Centimeters) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); ---- `m` (Meters) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); ---- `km` (Kilometers) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); ---- @@ -85,35 +87,35 @@ Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)) `in` (Inches) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); ---- `ft` (Feet) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); ---- `yd` (Yards) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); ---- `mi` (Miles) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); ---- `nmi` or `NM` (Nautical Miles) -[source,csharp] +[source,csharp,method-name="usingdifferentunits"] ---- Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); ---- diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc new file mode 100644 index 00000000000..cf28136a0b2 --- /dev/null +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -0,0 +1,226 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +== Suggest API + +[source,javascript,method-name="expectjson"] +.Example json output +---- +{ + "my-completion-suggest": { + "completion": { + "analyzer": "simple", + "context": { + "color": "red" + }, + "field": "suggest", + "fuzzy": { + "fuzziness": "AUTO", + "min_length": 1, + "prefix_length": 2, + "transpositions": true, + "unicode_aware": false + }, + "shard_size": 7, + "size": 8 + }, + "text": "Durgan LLC" + }, + "my-phrase-suggest": { + "phrase": { + "collate": { + "query": { + "inline": "{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}", + "params": { + "field_name": "title" + } + }, + "prune": true + }, + "confidence": 10.1, + "direct_generator": [ + { + "field": "description" + } + ], + "field": "name", + "gram_size": 1, + "real_word_error_likelihood": 0.5 + }, + "text": "hello world" + }, + "my-term-suggest": { + "term": { + "analyzer": "standard", + "field": "name", + "max_edits": 1, + "max_inspections": 2, + "max_term_freq": 3.0, + "min_doc_freq": 4.0, + "min_word_len": 5, + "prefix_len": 6, + "shard_size": 7, + "size": 8, + "suggest_mode": "always" + }, + "text": "hello world" + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method-name="fluent"] +---- +s => s + .Term("my-term-suggest", t => t + .MaxEdits(1) + .MaxInspections(2) + .MaxTermFrequency(3) + .MinDocFrequency(4) + .MinWordLength(5) + .PrefixLength(6) + .SuggestMode(SuggestMode.Always) + .Analyzer("standard") + .Field(p => p.Name) + .ShardSize(7) + .Size(8) + .Text("hello world") + ) + .Completion("my-completion-suggest", c => c + .Context(ctx => ctx + .Add("color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()) + ) + .Fuzzy(f => f + .Fuzziness(Fuzziness.Auto) + .MinLength(1) + .PrefixLength(2) + .Transpositions() + .UnicodeAware(false) + ) + .Analyzer("simple") + .Field(p => p.Suggest) + .ShardSize(7) + .Size(8) + .Text(Project.Instance.Name) + ) + .Phrase("my-phrase-suggest", ph => ph + .Collate(c => c + .Query(q => q + .Inline("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + .Params(p => p.Add("field_name", "title")) + ) + .Prune() + ) + .Confidence(10.1) + .DirectGenerator(d => d + .Field(p => p.Description) + ) + .GramSize(1) + .Field(p => p.Name) + .Text("hello world") + .RealWordErrorLikelihood(0.5) + ) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method-name="initializer"] +---- +new SuggestRequest +{ + Suggest = new SuggestContainer + { + { "my-term-suggest", new SuggestBucket + { + Text = "hello world", + Term = new TermSuggester + { + MaxEdits = 1, + MaxInspections = 2, + MaxTermFrequency = 3, + MinDocFrequency = 4, + MinWordLen = 5, + PrefixLen = 6, + SuggestMode = SuggestMode.Always, + Analyzer = "standard", + Field = Field(p=>p.Name), + ShardSize = 7, + Size = 8 + } + } }, + { "my-completion-suggest", new SuggestBucket + { + Text = Project.Instance.Name, + Completion = new CompletionSuggester + { + Context = new Dictionary { { "color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First() } }, + Fuzzy = new FuzzySuggester + { + Fuzziness = Fuzziness.Auto, + MinLength = 1, + PrefixLength = 2, + Transpositions = true, + UnicodeAware = false + }, + Analyzer = "simple", + Field = Field(p=>p.Suggest), + ShardSize = 7, + Size = 8 + } + } }, + { "my-phrase-suggest", new SuggestBucket + { + Text = "hello world", + Phrase = new PhraseSuggester + { + Collate = new PhraseSuggestCollate + { + Query = new InlineScript("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + { + Params = new Dictionary + { + { "field_name", "title" } + } + }, + Prune = true + }, + Confidence = 10.1, + DirectGenerator = new List + { + new DirectGenerator { Field = "description" } + }, + GramSize = 1, + Field = "name", + RealWordErrorLikelihood = 0.5 + } + } }, + } +} +---- + +=== Handling Responses + +Get the suggestions for a suggester by indexing into +the `.Suggestions` on the response + +[source,csharp,method-name="expectresponse"] +---- +var myCompletionSuggest = response.Suggestions["my-completion-suggest"]; + +myCompletionSuggest.Should().NotBeNull(); +var suggest = myCompletionSuggest.First(); +suggest.Text.Should().Be(Project.Instance.Name); +suggest.Length.Should().BeGreaterThan(0); +var option = suggest.Options.First(); +option.Text.Should().NotBeNullOrEmpty(); +option.Score.Should().BeGreaterThan(0); +var payload = option.Payload(); +payload.Should().NotBeNull(); +payload.Name.Should().Be(Project.Instance.Name); +payload.State.Should().NotBeNull(); +---- + diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs index 605a6ed69c9..32cb480f930 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs @@ -12,24 +12,38 @@ namespace Nest.Litterateur.AsciiDoc public class AddAttributeEntriesVisitor : NoopVisitor { private readonly FileInfo _destination; - + private bool _topLevel = true; private static readonly Dictionary Ids = new Dictionary(); + private Document _newDocument; public AddAttributeEntriesVisitor(FileInfo destination) { _destination = destination; } + public Document Convert(Document document) + { + document.Accept(this); + return _newDocument; + } + public override void Visit(Document document) { + _newDocument = new Document(); + + foreach (var attributeEntry in document.Attributes) + { + _newDocument.Attributes.Add(attributeEntry); + } + if (!document.Attributes.Any(a => a.Name == "ref_current")) { - document.Attributes.Add(new AttributeEntry("ref_current", "https://www.elastic.co/guide/en/elasticsearch/reference/current")); + _newDocument.Attributes.Add(new AttributeEntry("ref_current", "https://www.elastic.co/guide/en/elasticsearch/reference/current")); } if (!document.Attributes.Any(a => a.Name == "github")) { - document.Attributes.Add(new AttributeEntry("github", "https://github.com/elastic/elasticsearch-net")); + _newDocument.Attributes.Add(new AttributeEntry("github", "https://github.com/elastic/elasticsearch-net")); } if (!document.Attributes.Any(a => a.Name == "imagesdir")) @@ -40,12 +54,77 @@ public override void Visit(Document document) var count = difference.Count(c => c == '\\'); var imagesDir = string.Join(string.Empty, Enumerable.Repeat("../", count)); - document.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}")); + _newDocument.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}")); } base.Visit(document); } + public override void Visit(IList elements) + { + if (_topLevel) + { + _topLevel = false; + for (int index = 0; index < elements.Count; index++) + { + var element = elements[index]; + var source = element as Source; + + if (source != null) + { + // remove empty source blocks + if (string.IsNullOrWhiteSpace(source.Text)) + { + continue; + } + + // check that the previous element is a SectionTitle and if not, add one + var lastSourceBlock = _newDocument.Elements.LastOrDefault(e => e is Source); + var lastSectionTitle = _newDocument.Elements.OfType().LastOrDefault(e => e.Level == 3); + if (lastSourceBlock != null && lastSectionTitle != null) + { + var lastSectionTitleIndex = _newDocument.Elements.IndexOf(lastSectionTitle); + var lastSourceBlockIndex = _newDocument.Elements.IndexOf(lastSourceBlock); + if (lastSectionTitleIndex > lastSourceBlockIndex) + { + _newDocument.Elements.Add(element); + continue; + } + } + + var method = source.Attributes.OfType() + .FirstOrDefault(a => a.Name == "method-name"); + + if (method == null) + { + _newDocument.Elements.Add(element); + continue; + } + + switch (method.Value) + { + case "fluent": + case "queryfluent": + _newDocument.Elements.Add(new SectionTitle("Fluent DSL Example", 3)); + break; + case "initializer": + case "queryinitializer": + _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); + break; + case "expectresponse": + _newDocument.Elements.Add(new SectionTitle("Handling Responses", 3)); + break; + } + + } + + _newDocument.Elements.Add(element); + } + } + + base.Visit(elements); + } + public override void Visit(Source source) { if (source.Attributes.Count > 1 && diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs index 34c2beb7362..b629758114f 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs @@ -7,12 +7,12 @@ namespace Nest.Litterateur.Documentation.Blocks { public class CodeBlock : IDocumentationBlock { - public CodeBlock(string lineOfCode, int lineNumber, Language language, string propertyName = null) + public CodeBlock(string lineOfCode, int lineNumber, Language language, string propertyName) { Value = ExtractCallOutsFromText(lineOfCode); LineNumber = lineNumber; Language = language; - PropertyName = propertyName; + PropertyName = propertyName?.ToLowerInvariant(); } public List CallOuts { get; } = new List(); diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index db306d4a66c..561865986c8 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -30,7 +30,9 @@ private string RenderBlocksToDocumentation(IEnumerable bloc var lastBlockWasCodeBlock = false; var callouts = new List(); Language? language = null; - RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock, ref callouts, ref language); + string propertyOrMethodName = null; + + RenderBlocksToDocumentation(blocks, builder, ref lastBlockWasCodeBlock, ref callouts, ref language, ref propertyOrMethodName); if (lastBlockWasCodeBlock) { builder.AppendLine("----"); @@ -47,7 +49,8 @@ private void RenderBlocksToDocumentation( StringBuilder builder, ref bool lastBlockWasCodeBlock, ref List callouts, - ref Language? language) + ref Language? language, + ref string propertyOrMethodName) { foreach (var block in blocks) { @@ -75,7 +78,7 @@ private void RenderBlocksToDocumentation( var codeBlock = (CodeBlock)block; // don't write different language code blocks in the same delimited source block - if (lastBlockWasCodeBlock && codeBlock.Language != language) + if (lastBlockWasCodeBlock && (codeBlock.Language != language || codeBlock.PropertyName != propertyOrMethodName)) { lastBlockWasCodeBlock = false; builder.AppendLine("----"); @@ -92,8 +95,8 @@ private void RenderBlocksToDocumentation( if (!lastBlockWasCodeBlock) { - builder.AppendLine($"[source, {codeBlock.Language.ToString().ToLowerInvariant()}]"); - builder.AppendLine("----"); + builder.AppendLine($"[source,{codeBlock.Language.ToString().ToLowerInvariant()},method-name=\"{codeBlock.PropertyName ?? "unknown"}\"]"); + builder.AppendLine("----"); } else { @@ -106,11 +109,12 @@ private void RenderBlocksToDocumentation( callouts.AddRange(codeBlock.CallOuts); lastBlockWasCodeBlock = true; language = codeBlock.Language; + propertyOrMethodName = codeBlock.PropertyName; } else if (block is CombinedBlock) { var mergedBlocks = MergeAdjacentCodeBlocks(((CombinedBlock)block).Blocks); - RenderBlocksToDocumentation(mergedBlocks, builder, ref lastBlockWasCodeBlock, ref callouts, ref language); + RenderBlocksToDocumentation(mergedBlocks, builder, ref lastBlockWasCodeBlock, ref callouts, ref language, ref propertyOrMethodName); } } } @@ -122,6 +126,7 @@ private List MergeAdjacentCodeBlocks(IEnumerable collapseCallouts = null; int lineNumber = 0; Language? language = null; + string propertyOrMethodName = null; foreach (var b in unmergedBlocks) { @@ -129,7 +134,7 @@ private List MergeAdjacentCodeBlocks(IEnumerable MergeAdjacentCodeBlocks(IEnumerable(); var codeBlock = (CodeBlock)b; - if (language != null && codeBlock.Language != language) + + if ((language != null && codeBlock.Language != language) || + (propertyOrMethodName != null && codeBlock.PropertyName != propertyOrMethodName)) { blocks.Add(codeBlock); continue; } language = codeBlock.Language; + propertyOrMethodName = codeBlock.PropertyName; collapseCodeBlocks.Add(codeBlock.Value); collapseCallouts.AddRange(codeBlock.CallOuts); @@ -163,7 +171,7 @@ private List MergeAdjacentCodeBlocks(IEnumerable Substitutions = new Dictionary { { "FixedDate", "new DateTime(2015, 06, 06, 12, 01, 02, 123)" }, - { "FirstNameToFind", "\"pierce\"" } + { "FirstNameToFind", "\"pierce\"" }, + { "Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()", "\"red\"" }, + { "Project.Instance.Name", "\"Durgan LLC\"" }, + { "Project.InstanceAnonymous", "new {name = \"Koch, Collier and Mohr\", state = \"BellyUp\",startedOn = " + + "\"2015-01-01T00:00:00\",lastActivity = \"0001-01-01T00:00:00\",leadDeveloper = " + + "new { gender = \"Male\", id = 0, firstName = \"Martijn\", lastName = \"Laarman\" }," + + "location = new { lat = 42.1523, lon = -80.321 }}" }, }; public static bool TryGetJsonForAnonymousType(this string anonymousTypeString, out string json) diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs index 6d2799cc300..98ab9270d82 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/CodeWithDocumentationWalker.cs @@ -23,7 +23,7 @@ class CodeWithDocumentationWalker : CSharpSyntaxWalker { private bool _firstVisit = true; private string _code; - private readonly string _propertyName; + private readonly string _propertyOrMethodName; public int ClassDepth { get; } @@ -39,12 +39,12 @@ class CodeWithDocumentationWalker : CSharpSyntaxWalker /// /// the depth of the class /// line number used for sorting - /// the name of the property that we are walking - public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null, string propertyName = null) : base(SyntaxWalkerDepth.StructuredTrivia) + /// the name of the property that we are walking + public CodeWithDocumentationWalker(int classDepth = 1, int? lineNumber = null, string propertyOrMethodName = null) : base(SyntaxWalkerDepth.StructuredTrivia) { ClassDepth = classDepth; _lineNumberOverride = lineNumber; - _propertyName = propertyName; + _propertyOrMethodName = propertyOrMethodName; } public override void Visit(SyntaxNode node) @@ -59,7 +59,7 @@ public override void Visit(SyntaxNode node) _code = _code.RemoveNumberOfLeadingTabsAfterNewline(repeatedTabs); #if !DOTNETCORE - if (_propertyName == "ExpectJson" || _propertyName == "QueryJson") + if (_propertyOrMethodName == "ExpectJson" || _propertyOrMethodName == "QueryJson") { // try to get the json for the anonymous type. // Only supports system types and Json.Net LINQ objects e.g. JObject @@ -80,12 +80,12 @@ public override void Visit(SyntaxNode node) var nodeLine = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var line = _lineNumberOverride ?? nodeLine; - var codeBlocks = ParseCodeBlocks(_code, line, language, _propertyName); + var codeBlocks = ParseCodeBlocks(_code, line, language, _propertyOrMethodName); base.Visit(node); - var nodeHasLeadingTriva = node.HasLeadingTrivia && node.GetLeadingTrivia() - .Any(c => c.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia); + var nodeHasLeadingTriva = node.HasLeadingTrivia && + node.GetLeadingTrivia().Any(c => c.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia); var blocks = codeBlocks.Intertwine(this.TextBlocks, swap: nodeHasLeadingTriva); this.Blocks.Add(new CombinedBlock(blocks, line)); return; @@ -109,7 +109,7 @@ public override void VisitBlock(BlockSyntax node) var nodeLine = formattedStatement.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var line = _lineNumberOverride ?? nodeLine; - var codeBlocks = ParseCodeBlocks(_code, line, Language.CSharp, _propertyName); + var codeBlocks = ParseCodeBlocks(_code, line, Language.CSharp, _propertyOrMethodName); this.Blocks.AddRange(codeBlocks); } diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index f924eb79294..72f1408c481 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -11,15 +11,39 @@ namespace Nest.Litterateur.Walkers { class DocumentationFileWalker : CSharpSyntaxWalker { + private static readonly string[] PropertyNamesOfInterest = + { + "ExpectJson", + "QueryJson", + "Fluent", + "Initializer", + "QueryFluent", + "QueryInitializer" + }; + + private string _propertyOrMethodName; + public DocumentationFileWalker() : base(SyntaxWalkerDepth.StructuredTrivia) { } - private string _propertyName; private int ClassDepth { get; set; } + public int InterfaceDepth { get; set; } private bool InsideMultiLineDocumentation { get; set; } private bool InsideAutoIncludeMethodBlock { get; set; } private bool InsideFluentOrInitializerExample { get; set; } public List Blocks { get; } = new List(); + public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node) + { + if (node.ChildNodes().All(childNode => childNode is PropertyDeclarationSyntax || childNode is AttributeListSyntax)) + { + // simple nested interface + var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; + var walker = new CodeWithDocumentationWalker(0, line); + walker.Visit(node); + this.Blocks.AddRange(walker.Blocks); + } + } + public override void VisitClassDeclaration(ClassDeclarationSyntax node) { ++ClassDepth; @@ -40,7 +64,7 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) var methods = node.ChildNodes().OfType(); if (!methods.Any(m => m.AttributeLists.SelectMany(a => a.Attributes).Any())) { - // nested class with methods that are not unit or integration tests e.g. example PropertyVisitor + // nested class with methods that are not unit or integration tests e.g. example PropertyVisitor in Automap.doc.cs var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; var walker = new CodeWithDocumentationWalker(ClassDepth - 2, line); walker.Visit(node); @@ -52,18 +76,8 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { - var propertyName = node.Identifier.Text; - if (propertyName == "ExpectJson" || propertyName == "QueryJson") - { - _propertyName = propertyName; - this.InsideFluentOrInitializerExample = true; - base.VisitPropertyDeclaration(node); - this.InsideFluentOrInitializerExample = false; - } - else if (propertyName == "Fluent" || - propertyName == "Initializer" || - propertyName == "QueryFluent" || - propertyName == "QueryInitializer") + _propertyOrMethodName = node.Identifier.Text; + if (PropertyNamesOfInterest.Contains(_propertyOrMethodName)) { // TODO: Look to get the generic types for the call so that we can prettify the fluent and OIS calls in docs e.g. client.Search({Call}); // var genericArguments = node.DescendantNodes().OfType().FirstOrDefault(); @@ -73,15 +87,10 @@ public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) // arguments.AddRange(genericArguments.TypeArgumentList.Arguments); // } - _propertyName = propertyName; this.InsideFluentOrInitializerExample = true; base.VisitPropertyDeclaration(node); this.InsideFluentOrInitializerExample = false; } - else - { - _propertyName = null; - } } public override void VisitArrowExpressionClause(ArrowExpressionClauseSyntax node) @@ -90,7 +99,7 @@ public override void VisitArrowExpressionClause(ArrowExpressionClauseSyntax node var syntaxNode = node?.ChildNodes()?.LastOrDefault()?.WithAdditionalAnnotations(); if (syntaxNode == null) return; var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyOrMethodName); walker.Visit(syntaxNode); this.Blocks.AddRange(walker.Blocks); } @@ -101,7 +110,7 @@ public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) var syntaxNode = node?.ChildNodes()?.LastOrDefault()?.WithAdditionalAnnotations() as BlockSyntax; if (syntaxNode == null) return; var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; - var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyOrMethodName); walker.VisitBlock(syntaxNode); this.Blocks.AddRange(walker.Blocks); } @@ -109,6 +118,7 @@ public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { if (this.ClassDepth == 1) this.InsideAutoIncludeMethodBlock = true; + _propertyOrMethodName = node.Identifier.Text; base.VisitMethodDeclaration(node); this.InsideAutoIncludeMethodBlock = false; } @@ -121,7 +131,7 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) var allchildren = node.DescendantNodesAndTokens(descendIntoTrivia: true); if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) { - var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyOrMethodName); walker.Visit(node.WithAdditionalAnnotations()); this.Blocks.AddRange(walker.Blocks); return; @@ -129,7 +139,7 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) base.VisitExpressionStatement(node); var code = node.WithoutLeadingTrivia().ToFullString(); code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); - this.Blocks.Add(new CodeBlock(code, line, Language.CSharp)); + this.Blocks.Add(new CodeBlock(code, line, Language.CSharp, _propertyOrMethodName)); } else base.VisitExpressionStatement(node); @@ -143,14 +153,14 @@ public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyn var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) { - var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyName); + var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyOrMethodName); walker.Visit(node.WithAdditionalAnnotations()); this.Blocks.AddRange(walker.Blocks); return; } var code = node.WithoutLeadingTrivia().ToFullString(); code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); - this.Blocks.Add(new CodeBlock(code, line, Language.CSharp)); + this.Blocks.Add(new CodeBlock(code, line, Language.CSharp, _propertyOrMethodName)); } base.VisitLocalDeclarationStatement(node); } diff --git a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs index 2cf614b95bc..29d492bc46a 100644 --- a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs +++ b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs @@ -47,7 +47,6 @@ public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba } }; - /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filters("projects_by_state", agg => agg @@ -64,7 +63,6 @@ public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba ) ); - /** Object Initializer Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -140,7 +138,6 @@ public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } }; - /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filters("projects_by_state", agg => agg @@ -156,7 +153,6 @@ public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { ) ); - /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -165,18 +161,21 @@ public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { OtherBucket = true, Filters = new List { - Query.Term(p=>p.State, StateOfBeing.BellyUp) , - Query.Term(p=>p.State, StateOfBeing.Stable) , - Query.Term(p=>p.State, StateOfBeing.VeryActive) + Query.Term(p=>p.State, StateOfBeing.BellyUp) , + Query.Term(p=>p.State, StateOfBeing.Stable) , + Query.Term(p=>p.State, StateOfBeing.VeryActive) }, Aggregations = - new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } + new TermsAggregation("project_tags") + { + Field = Field(p => p.CuratedTags.First().Name) + } } }; protected override void ExpectResponse(ISearchResponse response) { - /** + /** === Handling Responses * Using the `.Agg` aggregation helper we can fetch our aggregation results easily * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() */ diff --git a/src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.doc.cs similarity index 96% rename from src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.doc.cs index 5d0ade378c2..dce2f25f00b 100644 --- a/src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.doc.cs @@ -20,7 +20,7 @@ public IpRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba { ip_range = new { - field = Field(p => p.LeadDeveloper.IPAddress), + field = "leadDeveloper.iPAddress", ranges = new object[] { new { to = "10.0.0.5" }, diff --git a/src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.doc.cs similarity index 97% rename from src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.doc.cs index 3d5a405572c..491b95ed639 100644 --- a/src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.doc.cs @@ -21,7 +21,7 @@ public RangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base { range = new { - field = Field(p => p.NumberOfCommits), + field = "numberOfCommits", ranges = new object[] { new { to = 100.0 }, diff --git a/src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.doc.cs similarity index 98% rename from src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.doc.cs index c848cd88e7b..b375feaf0d7 100644 --- a/src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.doc.cs @@ -40,7 +40,7 @@ public ReverseNestedAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage { terms = new { - field = Field(p => p.Name) + field = "name" } } } diff --git a/src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.doc.cs similarity index 97% rename from src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.doc.cs index 9c56525d42e..9ad94445552 100644 --- a/src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public SignificantTermsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage us { significant_terms = new { - field = Field(p => p.Name), + field = "name", min_doc_count = 10, mutual_information = new { diff --git a/src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.doc.cs similarity index 98% rename from src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.cs rename to src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.doc.cs index cdb7bb5082a..227917ddf8d 100644 --- a/src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.doc.cs @@ -24,7 +24,7 @@ public TermsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base }, terms = new { - field = Field(p => p.State), + field = "state", min_doc_count = 2, size = 5, shard_size = 100, diff --git a/src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.doc.cs similarity index 95% rename from src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.doc.cs index 4f7d4f29670..bf7f41a07a8 100644 --- a/src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.doc.cs @@ -12,6 +12,9 @@ public class AverageAggregationUsageTests : AggregationUsageTestBase { public AverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } + /// + /// + /// protected override object ExpectJson => new { aggs = new @@ -24,7 +27,7 @@ public AverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba }, avg = new { - field = Field(p => p.NumberOfCommits), + field = "numberOfCommits", missing = 10.0, script = new { diff --git a/src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.doc.cs similarity index 96% rename from src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.doc.cs index ccdd2b391ac..b77cf6816b3 100644 --- a/src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public CardinalityAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) { cardinality = new { - field = Field(p => p.State), + field = "state", precision_threshold = 100 } } diff --git a/src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.doc.cs similarity index 96% rename from src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.doc.cs index eddd5140909..f20c7de7d0b 100644 --- a/src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public ExtendedStatsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage { extended_stats = new { - field = Field(p => p.NumberOfCommits) + field = "numberOfCommits" } } } diff --git a/src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.doc.cs similarity index 97% rename from src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.doc.cs index f5c90d1b911..03062bb15e9 100644 --- a/src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public GeoBoundsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : { geo_bounds = new { - field = Field(p => p.Location), + field = "location", wrap_longitude = true } } diff --git a/src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.doc.cs similarity index 95% rename from src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.doc.cs index 750d2b0b375..eebc4719a86 100644 --- a/src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public MaxAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i { max = new { - field = Field(p => p.NumberOfCommits) + field = "numberOfCommits" } } } diff --git a/src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.doc.cs similarity index 95% rename from src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.doc.cs index effd8911f3d..f915e938ff6 100644 --- a/src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public MinAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i { min = new { - field = Field(p => p.NumberOfCommits) + field = "numberOfCommits" } } } diff --git a/src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.doc.cs similarity index 97% rename from src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.doc.cs index 0fc35aa96ef..1137a591914 100644 --- a/src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.doc.cs @@ -20,7 +20,7 @@ public PercentileRanksAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usa { percentile_ranks = new { - field = Field(p => p.NumberOfCommits), + field = "numberOfCommits", values = new [] { 15.0, 30.0 }, tdigest = new { diff --git a/src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.doc.cs similarity index 97% rename from src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.doc.cs index b5084517d02..36e886201fd 100644 --- a/src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public PercentilesAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) { percentiles = new { - field = Field(p => p.NumberOfCommits), + field = "numberOfCommits", percents = new[] { 95.0, 99.0, 99.9 }, hdr = new { diff --git a/src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.doc.cs similarity index 96% rename from src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.doc.cs index bab79f5e989..dfd29d1694c 100644 --- a/src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public StatsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base { stats = new { - field = Field(p => p.NumberOfCommits) + field = "numberOfCommits" } } } diff --git a/src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.doc.cs similarity index 95% rename from src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.doc.cs index 706d3a7e54e..de2bfd84d57 100644 --- a/src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public SumAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i { sum = new { - field = Field(p => p.NumberOfCommits) + field = "numberOfCommits" } } } diff --git a/src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.doc.cs similarity index 96% rename from src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.doc.cs index d6113ea5837..9c3c59a60cf 100644 --- a/src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.doc.cs @@ -21,7 +21,7 @@ public TopHitsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba { terms = new { - field = Field(p => p.State), + field = "state", }, aggs = new { @@ -41,12 +41,12 @@ public TopHitsAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba }, _source = new { - include = new string[] { "name", "startedOn" } + include = new [] { "name", "startedOn" } }, size = 1, version = true, explain = true, - fielddata_fields = new string[] { "state", "numberOfCommits" }, + fielddata_fields = new [] { "state", "numberOfCommits" }, highlight = new { fields = new diff --git a/src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.cs b/src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.doc.cs similarity index 95% rename from src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.cs rename to src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.doc.cs index a646b488260..675b6a61b51 100644 --- a/src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.doc.cs @@ -19,7 +19,7 @@ public ValueCountAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : { value_count = new { - field = Field(p => p.NumberOfCommits) + field = "numberOfCommits" } } } diff --git a/src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.cs b/src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.doc.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.cs rename to src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.doc.cs diff --git a/src/Tests/Aggregations/WritingAggregations.doc.cs b/src/Tests/Aggregations/WritingAggregations.doc.cs index 045966b62db..aced4b4f8de 100644 --- a/src/Tests/Aggregations/WritingAggregations.doc.cs +++ b/src/Tests/Aggregations/WritingAggregations.doc.cs @@ -8,7 +8,8 @@ namespace Tests.Aggregations { - /** == Aggregations + /** :section-number: 10 + * == Aggregations * * Aggregations are arguably one of the most powerful features of Elasticsearch. * NEST allows you to write your aggregations using diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs index 8544afdefee..2cf8634877a 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs @@ -9,7 +9,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class ConnectionPooling { - /** == Connection Pooling + /** :section-number: 4.1 + * == Connection Pooling * Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which * NEST can use to issue client calls on. There are 3 types of connection pool * diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs index 31fd3a66960..efe95886e0d 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class DateTimeProviders { - /** == Date time providers + /** :section-number: 4.5 + * == Date time providers * * Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` * in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs index 38bba015513..2bc8899333f 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/KeepingTrackOfNodes.Doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks public class KeepingTrackOfNodes { - /** == Keeping track of nodes + /** :section-number: 4.4 + * == Keeping track of nodes * */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs index 71d4ef46bc8..67383907390 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { - /** == Request Pipeline + /** :section-number: 4.2 + * == Request Pipeline * Every request is executed in the context of a `RequestPipeline` when using the * default `ITransport` implementation. */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs index d4064216c7f..d22f4cc0f61 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class Transports { - /** == Transports + /** :section-number: 4.3 + * == Transports * * The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple and * it's ultimately responsible from translating a client call to a response. diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs index b45e7f72c9a..54770bc14d9 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs @@ -11,7 +11,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.Pinging { public class FirstUsage { - /** == Pinging - First Usage + /** :section-number: 5.1 + * == Pinging - First Usage * * Pinging is enabled by default for the Static & Sniffing connection pool. * This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs index cef68dd016a..da080504367 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/Revival.doc.cs @@ -11,7 +11,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.Pinging { public class Revival { - /** == Pinging - Revival + /** :section-number: 5.2 + * == Pinging - Revival * * When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping * before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs index 575d6d24ed1..41178df046e 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/DisableSniffPingPerRequest.doc.cs @@ -8,10 +8,11 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class DisableSniffPingPerRequest { - /** == Disabling sniffing and pinging on a request basis + /** :section-number: 6.1 + * == Disabling sniffing and pinging on a request basis * * Even if you are using a sniffing connection pool thats set up to sniff on start/failure - * and pinging enabled, you can opt out of this behaviour on a per request basis + * and pinging enabled, you can opt out of this behaviour on a _per request_ basis. * * In our first test we set up a cluster that pings and sniffs on startup * but we disable the sniffing on our first request so we only see the ping and the response @@ -19,35 +20,33 @@ public class DisableSniffPingPerRequest [U] public async Task DisableSniff() { + /** Let's set up the cluster and configure clients to **always** sniff on startup */ var audit = new Auditor(() => Framework.Cluster .Nodes(10) .ClientCalls(r => r.SucceedAlways()) .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) - ); + .Settings(s => s.SniffOnStartup()) // <1> sniff on startup + ); + audit = await audit.TraceCalls( - /** - * We disable sniffing so even though its our first call, we do not want to sniff on startup - */ - new ClientCall(r=>r.DisableSniffing()) { - { PingSuccess, 9200 }, + /** Now We disable sniffing on the request so even though it's our first call, we do not want to sniff on startup */ + new ClientCall(r => r.DisableSniffing()) // <1> disable sniffing + { + { PingSuccess, 9200 }, // <2> first call is a successful ping { HealthyResponse, 9200 } }, - /** - * Instead the sniff on startup is deffered to the second call into the cluster that + /** Instead, the sniff on startup is deferred to the second call into the cluster that * does not disable sniffing on a per request basis */ new ClientCall() { - { SniffOnStartup }, + { SniffOnStartup }, // <3> sniff on startup call happens here, on the second call { SniffSuccess, 9200 }, { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, - /** - * And after that no sniff on startup will happen again - */ + /** And after that no sniff on startup will happen again */ new ClientCall() { { PingSuccess, 9201 }, @@ -56,6 +55,7 @@ [U] public async Task DisableSniff() ); } + /** Now, let's disable pinging on the request */ [U] public async Task DisablePing() { var audit = new Auditor(() => Framework.Cluster @@ -66,14 +66,16 @@ [U] public async Task DisablePing() ); audit = await audit.TraceCall( - new ClientCall(r=>r.DisablePing()) { + new ClientCall(r => r.DisablePing()) // <1> disable ping + { { SniffOnStartup }, - { SniffSuccess, 9200 }, + { SniffSuccess, 9200 }, // <2> No ping after sniffing { HealthyResponse, 9200 } } ); } + /** Finally, let's demonstrate disabling both sniff and ping on the request */ [U] public async Task DisableSniffAndPing() { var audit = new Auditor(() => Framework.Cluster @@ -84,8 +86,9 @@ [U] public async Task DisableSniffAndPing() ); audit = await audit.TraceCall( - new ClientCall(r=>r.DisableSniffing().DisablePing()) { - { HealthyResponse, 9200 } + new ClientCall(r=>r.DisableSniffing().DisablePing()) // <1> diable ping and sniff + { + { HealthyResponse, 9200 } // <2> no ping or sniff before the call } ); } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs index 447b5f430e8..cd1ca1fdec1 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RequestTimeoutsOverrides.doc.cs @@ -7,7 +7,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class RequestTimeoutsOverrides { - /** == Request Timeouts + /** :section-number: 6.2 + * == Request Timeouts * * While you can specify Request time out globally you can override this per request too */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs index aba2328ac53..d327c0f6bea 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsAllowedStatusCode.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class RespectsAllowedStatusCode { - /** == Allowed status codes + /** :section-number: 6.3 + * == Allowed status codes */ [U] diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs index 3095f90f84c..ee59976b003 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsForceNode.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class RespectsForceNode { - /** == Forcing nodes + /** :section-number: 6.4 + * == Forcing nodes * Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` * request configuration. This will ignore the pool and not retry. */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs index c4db54d687f..82a58527b94 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RequestOverrides/RespectsMaxRetryOverrides.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.RequestOverrides { public class RespectsMaxRetryOverrides { - /** == Maximum Retries + /** :section-number: 6.5 + * == Maximum Retries * * By default retry as many times as we have nodes. However retries still respect the request timeout. * Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can diff --git a/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.cs index 7f20bcca692..8483672b142 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/RoundRobin/RoundRobin.doc.cs @@ -11,16 +11,15 @@ namespace Tests.ClientConcepts.ConnectionPooling.RoundRobin { public class RoundRobin { - /** Round Robin + /** == Round Robin * Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. */ - /** == GetNext - * GetNext is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance + /** === GetNext + * `GetNext` is implemented in a lock free thread safe fashion, meaning each callee gets returned its own cursor to advance * over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without * suffering from noisy neighboors advancing a global cursor. */ - protected int NumberOfNodes = 10; [U] public void EachViewStartsAtNexPositionAndWrapsOver() @@ -36,7 +35,7 @@ [U] public void EachViewStartsAtNexPositionAndWrapsOver() public void AssertCreateView(IConnectionPool pool) { /** - * Here we have setup a static connection pool seeded with 10 nodes. We force randomizationOnStartup to false + * Here we have setup a static connection pool seeded with 10 nodes. We force randomization OnStartup to false * so that we can test the nodes being returned are int the order we expect them to. * So what order we expect? Imagine the following: * diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs index c1f52b4f2d0..017709e6bd6 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnConnectionFailure.doc.cs @@ -9,7 +9,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.Sniffing { public class OnConnectionFailure { - /** == Sniffing on connection failure + /** :section-number: 7.1 + * == Sniffing on connection failure * * Sniffing on connection is enabled by default when using a connection pool that allows reseeding. * The only IConnectionPool we ship that allows this is the SniffingConnectionPool. diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.cs index 3076e6f1aa1..9eb9a53c2ad 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStaleClusterState.doc.cs @@ -10,7 +10,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.Sniffing { public class OnStaleClusterState { - /** == Sniffing periodically + /** :section-number: 7.2 + * == Sniffing periodically * * Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. * In addition to sniffing on startup and sniffing on failures, sniffing periodically can benefit scenerio's where diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.cs index 6223fa14a91..7abb85d5c1e 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/OnStartup.doc.cs @@ -10,7 +10,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.Sniffing { public class OnStartupSniffing { - /** == Sniffing on startup + /** :section-number: 7.3 + * == Sniffing on startup * * Connection pools that return true for `SupportsReseeding` by default sniff on startup. */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.cs index c5e0a99df11..720d4a512be 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/RoleDetection.doc.cs @@ -13,12 +13,13 @@ namespace Tests.ClientConcepts.ConnectionPooling.Sniffing { public class RoleDetection - { - /** == Sniffing role detection + { + /** :section-number: 7.4 + * == Sniffing role detection * * When we sniff the custer state we detect the role of the node whether its master eligible and holds data * We use this information when selecting a node to perform an API call on. - */ + */ [U, SuppressMessage("AsyncUsage", "AsyncFixer001:Unnecessary async/await usage", Justification = "Its a test")] public async Task DetectsMasterNodes() { diff --git a/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs b/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs index 2a0ff0f766e..57100865841 100644 --- a/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs @@ -6,59 +6,60 @@ namespace Tests.ClientConcepts.HighLevel.CovariantHits { - /** # Covariant Search Results - * - * NEST directly supports returning covariant result sets. - * Meaning a result can be typed to an interface or baseclass - * but the actual instance type of the result can be that of the subclass directly - * - * Let look at an example, imagine we want to search over multiple types that all implement - * `ISearchResult` - * - */ - public interface ISearchResult + public class CovariantSearchResults { - string Name { get; set; } - } + /** :section-number: 4.1 + * == Covariant Search Results + * + * NEST directly supports returning covariant result sets. + * Meaning a result can be typed to an interface or base class + * but the actual instance type of the result can be that of the subclass directly + * + * Let's look at an example; Imagine we want to search over multiple types that all implement + * `ISearchResult` + */ + public interface ISearchResult + { + string Name { get; set; } + } - /** - * We have three implementations of `ISearchResult` namely `A`, `B` and `C` - */ + /** + * We have three implementations of `ISearchResult` namely `A`, `B` and `C` + */ + public class A : ISearchResult + { + public string Name { get; set; } + public int PropertyOnA { get; set; } + } - public class A : ISearchResult - { - public string Name { get; set; } - public int PropertyOnA { get; set; } - } + public class B : ISearchResult + { + public string Name { get; set; } + public int PropertyOnB { get; set; } + } - public class B : ISearchResult - { - public string Name { get; set; } - public int PropertyOnB { get; set; } - } + public class C : ISearchResult + { + public string Name { get; set; } + public int PropertyOnC { get; set; } + } - public class C : ISearchResult - { - public string Name { get; set; } - public int PropertyOnC { get; set; } - } - public class CovariantSearchResults - { - private IElasticClient _client = TestClient.GetFixedReturnClient(CovariantSearchResultMock.Json); + private readonly IElasticClient _client = TestClient.GetFixedReturnClient(CovariantSearchResultMock.Json); + [U] public void UsingTypes() { - /** + /** === Using Types * The most straightforward way to search over multiple types is to * type the response to the parent interface or base class - * and pass the actual types we want to search over using `.Types()` + * and pass the actual types we want to search over using `.Type()` */ var result = this._client.Search(s => s .Type(Types.Type(typeof(A), typeof(B), typeof(C))) .Size(100) ); /** - * Nest will translate this to a search over /index/a,b,c/_search. + * NEST will translate this to a search over `/index/a,b,c/_search`; * hits that have `"_type" : "a"` will be serialized to `A` and so forth */ @@ -91,7 +92,7 @@ [U] public void UsingTypes() [U] public void UsingConcreteTypeSelector() { - /** + /** === Using ConcreteTypeSelector * A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to */ var result = this._client.Search(s => s @@ -100,8 +101,9 @@ [U] public void UsingConcreteTypeSelector() ); /** - * here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` - * and a typed `h` which represents the encapsulating hit. + * here for each hit we'll call the delegate passed to `ConcreteTypeSelector where + * - `d` is a representation of the `_source` exposed as a `dynamic` type + * - a typed `h` which represents the encapsulating hit of the source i.e. `Hit` */ /** @@ -137,14 +139,14 @@ [U] public void UsingConcreteTypeSelector() [U] public void UsingCovariantTypesOnScroll() { /** - * Scroll() is a continuation of a previous Search() so Types() are lost. - * You can hint the type types again using CovariantTypes() + * The Scroll API is a continuation of the previous Search example so Types() are lost. + * You can hint at the types using `.CovariantTypes()` */ var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) ); /** - * Nest will translate this to a search over /index/a,b,c/_search. + * NEST will translate this to a search over `/index/a,b,c/_search`; * hits that have `"_type" : "a"` will be serialized to `A` and so forth */ @@ -185,8 +187,9 @@ [U] public void UsingConcreteTypeSelectorOnScroll() ); /** - * here for each hit we'll call the delegate with `d` which a dynamic representation of the `_source` - * and a typed `h` which represents the encapsulating hit. + * As before, within the delegate passed to `.ConcreteTypeSelector` + * - `d` is the `_source` typed as `dynamic` + * - `h` is the encapsulating typed hit */ /** diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs similarity index 77% rename from src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs index 553e174dbcc..c6dd613f02c 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/DocumentPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs @@ -7,14 +7,15 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class DocumentPaths { - /** = DocumentPaths + /** :section-number: 2.4 + * == DocumentPaths * - * Many API's in elasticsearch describe a path to a document. In NEST besides generating a constructor that takes - * and Index, Type and Id seperately we also generate a constructor taking a DocumentPath that allows you to describe the path + * Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes + * and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path * to your document more succintly */ - /** == Creating new instances */ + /** === Creating new instances */ [U] public void FromId() { /** here we create a new document path based on Project with the id 1 */ @@ -30,14 +31,14 @@ [U] public void FromId() path = new DocumentPath(1).Index("project1"); Expect("project1").WhenSerializing(path.Index); - /** there is also a static way to describe such paths */ + /** and there is also a static way to describe such paths */ path = DocumentPath.Id(1); Expect("project").WhenSerializing(path.Index); Expect("project").WhenSerializing(path.Type); Expect(1).WhenSerializing(path.Id); } - /** == Creating from a document type instance + /** === Creating from a document type instance * if you have an instance of your document you can use it as well generate document paths */ [U] public void FromObject() @@ -57,7 +58,7 @@ [U] public void FromObject() path = new DocumentPath(project).Index("project1"); Expect("project1").WhenSerializing(path.Index); - /** there is also a static way to describe such paths */ + /** and again, there is also a static way to describe such paths */ path = DocumentPath.Id(project); Expect("project").WhenSerializing(path.Index); Expect("project").WhenSerializing(path.Type); @@ -66,15 +67,17 @@ [U] public void FromObject() DocumentPath p = project; } + /** === An example with requests */ [U] public void UsingWithRequests() { + /* Given the following CLR type that describes a document */ var project = new Project { Name = "hello-world" }; - /** Here we can see and example how DocumentPath helps your describe your requests more tersely */ + /** we can see an example of how `DocumentPath` helps your describe your requests more tersely */ var request = new IndexRequest(2) { Document = project }; request = new IndexRequest(project) { }; - /** when comparing with the full blown constructor and passing document manually + /** when comparing with the full blown constructor and passing document manually, * `DocumentPath`'s benefits become apparent. */ request = new IndexRequest(IndexName.From(), TypeName.From(), 2) diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/FeaturesInference.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs similarity index 51% rename from src/Tests/ClientConcepts/HighLevel/Inferrence/FeaturesInference.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs index 4dcaa3b9b20..e10103d928a 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/FeaturesInference.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs @@ -8,14 +8,15 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FeaturesInference { - /** # Features - * Some urls in Elasticsearch take a {feature} enum - * RouteValues in NEST are represented as classes implementing IUrlParameter - * Since enums can not implement interfaces in C# this route param is represented using the Features class that can - * be implicitly converted to from the Feature enum + /** :section-number: 2.6 + * == Features + * Some URIs in Elasticsearch take a `Feature` enum. + * Within NEST, route values on the URI are represented as classes that implement an interface, `IUrlParameter`. + * Since enums _cannot_ implement interfaces in C#, a route parameter that would be of type `Feature` is represented using the `Features` class that + * the `Feature` enum implicitly converts to. */ - /** Using the constructor directly is possible but rather involved */ + /** Using the `Features` constructor directly is possible but rather involved */ [U] public void Serializes() { Features fieldString = Feature.Mappings | Feature.Aliases; @@ -26,9 +27,9 @@ [U] public void Serializes() [U] public void ImplicitConversion() { - /** + /** === Implicit conversion * Here we new an GET index elasticsearch request whichs takes Indices and Features. - * Notice how we can use the Feature enum directly. + * Notice how we can use the `Feature` enum directly. */ var request = new GetIndexRequest(All, Feature.Settings | Feature.Warmers); } diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs similarity index 97% rename from src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs index bd5b9a4804a..d727a41612f 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs @@ -19,7 +19,8 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FieldInferrence { - /** = Strongly typed field access + /** :section-number: 2.1 + * == Strongly typed Field Access * * Several places in the elasticsearch API expect the path to a field from your original source document as a string. * NEST allows you to use C# expressions to strongly type these field path strings. @@ -94,7 +95,7 @@ public void DefaultFieldNameInferrer() setup.Expect("Name").WhenSerializing(Field(p => p.Name)); } - /** == Complex field name expressions */ + /** === Complex field name expressions */ [U] public void ComplexFieldNameExpressions() { @@ -119,8 +120,8 @@ public void ComplexFieldNameExpressions() Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); - /** :multifieldlink: https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html - * If you are using elasticearch's {multifieldlink}[multi_fields], which you really should as they allow + /** + * If you are using elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow * you to analyze a string in a number of different ways, these _"virtual"_ sub fields * do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that * should be mapped. @@ -169,7 +170,7 @@ public void AppendingSuffixToExpressions() Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); } - /** == Annotations + /** === Annotations * * When using NEST's property attributes you can specify a new name for the properties */ diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs similarity index 95% rename from src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs index 8243a90532c..ea89238e9f8 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/IdsInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs @@ -7,7 +7,8 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IdsInference { - /** == Id Inference + /** :section-number: 2.3 + * == Id Inference * * === Implicit Conversions * @@ -73,8 +74,8 @@ [U] public void CanGetIdFromDocument() /** IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. * - * Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance - * with different inference rules + * Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance + * with different inference rules */ WithConnectionSettings(x => x .InferMappingFor(m => m diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs similarity index 97% rename from src/Tests/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs index 3bd8fa97bcb..099ae95dfc7 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/IndicesPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs @@ -6,7 +6,8 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IndicesPaths { - /** # Indices paths + /** :section-number: 2.5 + * == Indices paths * * Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices * In nest this is encoded using `Indices` diff --git a/src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs similarity index 91% rename from src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs index e3311395958..29cb08ba7a3 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inferrence/PropertyInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs @@ -8,6 +8,8 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence.PropertyNames { + /** :section-number: 2.2 + * == Property Names */ public class PropertyNames { /** @@ -31,7 +33,7 @@ public void PropertyNamesAreResolvedToLastTokenUsingApplySuffix() } /** Property names cannot contain a `.` in order to prevent the potential for collision with a field that - * may have https://www.elastic.co/guide/en/elasticsearch/reference/current/_multi_fields.html[`multi_fields`] + * may have {ref_current}/_multi_fields.html[`multi_fields`] */ [U] public void StringsContainingDotsIsAnException() { diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index 9ece5afdb8d..5c8a1c3f8f9 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.HighLevel.Mapping { - /**== Auto mapping properties + /** :section-number: 3.1 + * == Auto mapping properties * * When creating a mapping (either when creating an index or via the put mapping API), * NEST offers a feature called AutoMap(), which will automagically infer the correct diff --git a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs index b45a2e27664..45d60788dd9 100644 --- a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs @@ -15,26 +15,25 @@ namespace Tests.ClientConcepts.LowLevel { public class Connecting { - /** # Connecting - * Connecting to *Elasticsearch* with `Elasticsearch.Net` is quite easy but has a few toggles and options worth knowing. + /** :section-number: 1.1 + * == Connecting + * Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. * - * # Choosing the right connection strategy + * [[connection-strategies]] + * === Choosing the right Connection Strategy * If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` */ - public void InstantiateUsingAllDefaults() { var client = new ElasticLowLevelClient(); - var tokenizers = new TokenizersDescriptor(); - } + /** * If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then * you will need to pass in some instance of `IConnectionConfigurationValues`. * * The easiest way to do this is: */ - public void InstantiatingASingleNodeClient() { var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -43,11 +42,10 @@ public void InstantiatingASingleNodeClient() } /** - * This however is still a non-failover connection. Meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. + * This will still be a non-failover connection, meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. * * To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. */ - public void InstantiatingAConnectionPoolClient() { var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -58,25 +56,22 @@ public void InstantiatingAConnectionPoolClient() /** * Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. - * Be sure to read more about [Connection Pooling and Cluster Failover here](/elasticsearch-net/cluster-failover.html) + * Be sure to read more about <<../connection-pooling/connection-pooling, Connection Pooling and Cluster Failover here>>. * - * ## Options + * === Configuration Options * * Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: */ public void SpecifyingClientOptions() { - //hide var node = new Uri("http://mynode.example.com:8082/apiKey"); var connectionPool = new SniffingConnectionPool(new[] { node }); - //endhide var config = new ConnectionConfiguration(connectionPool) .DisableDirectStreaming() .BasicAuthentication("user", "pass") .RequestTimeout(TimeSpan.FromSeconds(5)); - } /** * The following is a list of available connection configuration options: @@ -84,19 +79,15 @@ public void SpecifyingClientOptions() public void AvailableOptions() { - //hide var client = new ElasticLowLevelClient(); - //endhide var config = new ConnectionConfiguration() + .DisableAutomaticProxyDetection() + /** `DisableAutomaticProxyDetection`: Disable automatic proxy detection. Defaults to true. */ - .DisableAutomaticProxyDetection() - /** Disable automatic proxy detection. Defaults to true. */ - - .EnableHttpCompression() - /** - * Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured - * to allow this. See the [http module settings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html) for more info). + .EnableHttpCompression() + /** `EnableHttpCompression`: Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. + * See the {ref_current}/modules-http.html[http module settings] for more info). */ .DisableDirectStreaming() @@ -106,8 +97,10 @@ public void AvailableOptions() */; var result = client.Search>(new { size = 12 }); + + /** This will only have a value if the client configuration has `DisableDirectStreaming` set */ var raw = result.ResponseBodyInBytes; - /** This will only have a value if the client configuration has ExposeRawResponse set */ + /** * Please note that this only make sense if you need a mapped response and the raw response at the same time. @@ -115,67 +108,65 @@ public void AvailableOptions() */ var stringResult = client.Search(new { }); - //hide + config = config - //endhide .GlobalQueryStringParameters(new NameValueCollection()) /** - * Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. + * - `GlobalQueryStringParameters`: Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. */ .Proxy(new Uri("http://myproxy"), "username", "pass") - /** Sets proxy information on the connection. */ + /** - `Proxy`: Sets proxy information on the connection. */ .RequestTimeout(TimeSpan.FromSeconds(4)) - /** + /** - `RequestTimeout`: * Sets the global maximum time a connection may take. - * Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts - * (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx). + * Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts + * (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). */ .ThrowExceptions() - /** + /** - `ThrowExceptions` * As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw * exceptions. - * - * There are three category of exceptions thay may be thrown: + * + * There are three category of exceptions that may be thrown: * - * 1) ElasticsearchClientException: These are known exceptions, either an exception that occurred in the request pipeline + * . **ElasticsearchClientException**: These are known exceptions, either an exception that occurred in the request pipeline * (such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could * not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property * on the response will contain the the actual error that was returned. The inner exception will always contain the * root causing exception. * - * 2) UnexpectedElasticsearchClientException: These are unknown exceptions, for instance a response from Elasticsearch not - * properly deserialized. These are usually bugs and should be reported. This excpetion also inherits from ElasticsearchClientException + * . **UnexpectedElasticsearchClientException**: These are unknown exceptions, for instance a response from Elasticsearch not + * properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` * so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. * - * 3) Development time exceptions: These are CLR exceptions like ArgumentException, NullArgumentException etc... that are thrown + * . **Development time exceptions**: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown * when an API in the client is misused. These should not be handled as you want to know about them during development. * */ .PrettyJson() /** - * Forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well + * - `PrettyJson`: forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well */ .BasicAuthentication("username", "password") - /** Sets the HTTP basic authentication credentials to specify with all requests. */; + /** - `BasicAuthentication(username, password)`: sets the HTTP basic authentication credentials to specify with all requests. */; /** - * **Note:** This can alternatively be specified on the node URI directly: - */ - + * NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: + */ var uri = new Uri("http://username:password@localhost:9200"); var settings = new ConnectionConfiguration(uri); /** - * ...but may become tedious when using connection pooling with multiple nodes. + *...but this may become tedious when using connection pooling with multiple nodes. */ } - /** + /** === `OnRequestCompleted` * You can pass a callback of type `Action<IApiCallDetails>` that can eaves drop every time a response (good or bad) is created. * If you have complex logging needs this is a good place to add that in. */ @@ -193,8 +184,8 @@ public void OnRequestCompletedIsCalled() counter.Should().Be(2); } - /** - * An example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like + /** [[complex-logging]] + * Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like * to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` * to `true` */ @@ -202,7 +193,7 @@ [U]public async Task UsingOnRequestCompletedForLogging() { var list = new List(); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); - var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) // <1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` to make the actual request .DisableDirectStreaming() .OnRequestCompleted(response => { @@ -263,10 +254,10 @@ [U]public async Task UsingOnRequestCompletedForLogging() public void ConfiguringSSL() { /** - * ## Configuring SSL + * === Configuring SSL * SSL must be configured outside of the client using .NET's - * [ServicePointManager](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx) - * class and setting the [ServerCertificateValidationCallback](http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx) + * http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] + * class and setting the http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx[ServerCertificateValidationCallback] * property. * * The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: @@ -276,24 +267,22 @@ public void ConfiguringSSL() ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; #endif /** - * However, this will accept all requests from the AppDomain to untrusted SSL sites, - * therefore we recommend doing some minimal introspection on the passed in certificate. + * However, this will accept **all** requests from the AppDomain to untrusted SSL sites, + * therefore **we recommend doing some minimal introspection on the passed in certificate.** */ } /** - * ## Overriding default Json.NET behavior + * === Overriding default Json.NET behavior * * Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful * - * Create a subclass of the `JsonNetSerializer` - + * Create a subclass of the `JsonNetSerializer` */ public class MyJsonNetSerializer : JsonNetSerializer { public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } - /** * Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` */ @@ -305,19 +294,19 @@ public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) * This can be much faster then registering them on JsonSerializerSettings.Converters */ public int CallToContractConverter { get; set; } = 0; - protected override IList> ContractConverters => new List>() + protected override IList> ContractConverters => new List> { - { t => { + t => { CallToContractConverter++; return null; - } } + } }; } /** - * You can then register a factory on ConnectionSettings to create an instance of your subclass instead. - * This is called once per instance of ConnectionSettings. + * You can then register a factory on `ConnectionSettings` to create an instance of your subclass instead. + * This is **_called once per instance_** of ConnectionSettings. */ [U] public void ModifyJsonSerializerSettingsIsCalled() diff --git a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs index 200d62c62d9..338f2aa4697 100644 --- a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs @@ -13,19 +13,23 @@ namespace Tests.ClientConcepts.LowLevel { public class Lifetimes { - /** - * ## Lifetimes + /** :section-number: 1.2 + * == Lifetimes * * If you are using an IOC container its always useful to know the best practices around the lifetime of your objects * - * In general we advise folks to register their ElasticClient instances as singleton. The client is thread safe - * so sharing this instance over threads is ok. + * In general we advise folks to register their ElasticClient instances as singletons. The client is thread safe + * so sharing an instance between threads is fine. * * Zooming in however the actual moving part that benefits the most from being static for most of the duration of your - * application is ConnectionSettings. Caches are per ConnectionSettings. + * application is `ConnectionSettings`; caches are __per__ `ConnectionSettings`. + * + * In some applications it could make perfect sense to have multiple singleton `ElasticClient`'s registered with different + * connection settings. e.g if you have 2 functionally isolated Elasticsearch clusters. * - * In some applications it could make perfect sense to have multiple singleton IElasticClient's registered with different - * connectionsettings. e.g if you have 2 functionally isolated Elasticsearch clusters. + * NOTE: Due to the semantic versioning of NEST and the alignment of versions to Elasticsearch, all instances of `ElasticClient` and thus + * Elasticsearch that are connected to must be on the same major version i.e. it is not possible to have both an `ElasticClient` to connect to + * Elasticsearch 1.x and 2.x in the same application as the former would require NEST 1.x and the latter, NEST 2.x. * * Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types */ @@ -79,7 +83,7 @@ [U] public void InitialDisposeState() } /** - * Disposing the ConnectionSettings will dispose the `IConnectionPool` and `IConnection` it has a hold of + * Disposing `ConnectionSettings` will dispose the `IConnectionPool` and `IConnection` it has a hold of */ [U] public void DisposingSettingsDisposesMovingParts() { diff --git a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs index 5db595ca898..74219c99aa2 100644 --- a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs @@ -13,8 +13,9 @@ namespace Tests.ClientConcepts.LowLevel { public class PostingData { - /** # Post data - * The low level allows you to post a string, byte[] array directly. On top of this if you pass a list of strings or objects + /** :section-number: 1.3 + * == Post data + * The low level client allows you to post a `string` or `byte[]` array directly. On top of this if you pass a collection of `strings` or `objects` * they will be serialized in Elasticsearch's special bulk/multi format. */ private readonly string @string = "fromString"; @@ -39,9 +40,15 @@ public PostingData() [U] public void ImplicitConversions() { - /** Even though the argument for postData on the low level client takes a PostData + /** Even though the argument for `PostData` on the low level client takes a `PostData` * You can rely on C# implicit conversion to abstract the notion of PostData completely. - *You can implicitly convert from the following types.*/ + * You can implicitly convert from the following types + * - `string` + * - `byte[]` + * - collection of `string` + * - collection of `object` + * - `object` + */ var fromString = ImplicitlyConvertsFrom(@string); var fromByteArray = ImplicitlyConvertsFrom(bytes); @@ -49,7 +56,7 @@ [U] public void ImplicitConversions() var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); var fromObject = ImplicitlyConvertsFrom(@object); - /** postData Bytes will always be set if it originated from a byte*/ + /** PostData bytes will always be set if it originated from a byte*/ fromByteArray.WrittenBytes.Should().BeSameAs(bytes); fromString.Type.Should().Be(PostType.LiteralString); @@ -58,7 +65,7 @@ [U] public void ImplicitConversions() fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); fromObject.Type.Should().Be(PostType.Serializable); - //passing a PostData object to a method taking PostData should not wrap + // and passing a `PostData` object to a method taking `PostData` should not wrap fromString = ImplicitlyConvertsFrom(fromString); fromByteArray = ImplicitlyConvertsFrom(fromByteArray); @@ -85,32 +92,32 @@ private async Task AssertOn(IConnectionConfigurationValues settings) { /** Although each implicitly types behaves slightly differently */ - await Post(()=>@string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); + await Post(() => @string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); - await Post(()=>bytes, writes: bytes, storesBytes: true, settings: settings); + await Post(() => bytes, writes: bytes, storesBytes: true, settings: settings); /** When passing a list of strings we assume its a list of valid serialized json that we * join with newlinefeeds making sure there is a trailing linefeed */ - await Post(()=>listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); + await Post(() => listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); /** * When passing a list of object we assume its a list of objects we need to serialize * individually to json and join with newlinefeeds aking sure there is a trailing linefeed */ - await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); + await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); /** In all other cases postdata is serialized as is. */ - await Post(()=>@object, writes: objectJson, storesBytes: false, settings: settings); + await Post(() => @object, writes: objectJson, storesBytes: false, settings: settings); /** If you want to maintain a copy of the request that went out use the following settings */ settings = new ConnectionSettings().DisableDirectStreaming(); /** by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream - * so we can get a hold of the serialized bytes */ - await Post(()=>listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); + * so we can get hold of the serialized bytes */ + await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); /** this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` */ - await Post(()=>@object, writes: objectJson, storesBytes: true, settings: settings); + await Post(() => @object, writes: objectJson, storesBytes: true, settings: settings); } private static async Task Post(Func> postData, byte[] writes, bool storesBytes, IConnectionConfigurationValues settings) diff --git a/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs b/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs index d33bd0d9f29..82fb1acfbf4 100644 --- a/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs +++ b/src/Tests/CommonOptions/DateMath/DateMathExpressions.doc.cs @@ -25,8 +25,8 @@ public class DateMathEpressions * - `s` (second) * * as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. - * - * Be sure to read the elasticsearch documentation {ref_current}/mapping-date-format.html#date-math[on this subject here] + * :datemath: {ref_current}/common-options.html#date-math + * Be sure to read the elasticsearch documentation {datemath}[on this subject here] */ [U] public void SimpleExpressions() { diff --git a/src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs b/src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs index fba1b200e34..8c3ec8e7ecb 100644 --- a/src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs +++ b/src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs @@ -28,7 +28,7 @@ protected override LazyResponses ClientUsage() => Calls( protected override bool SupportsDeserialization => false; - protected override object ExpectJson { get; } = new object[] + protected override object ExpectJson => new object[] { new Dictionary{ { "index", new { _type = "project", _id = Project.Instance.Name } } }, Project.InstanceAnonymous, @@ -39,6 +39,32 @@ protected override LazyResponses ClientUsage() => Calls( new Dictionary{ { "delete", new { _type="project", _id = Project.Instance.Name + "1" } } }, }; + protected override Func Fluent => d => d + .Index(CallIsolatedValue) + .Index(b => b.Document(Project.Instance)) + .Update(b => b.Doc(new { leadDeveloper = new { firstName = "martijn" } }).Id(Project.Instance.Name)) + .Create(b => b.Document(Project.Instance).Id(Project.Instance.Name + "1")) + .Delete(b=>b.Id(Project.Instance.Name + "1")); + + + protected override BulkRequest Initializer => + new BulkRequest(CallIsolatedValue) + { + Operations = new List + { + new BulkIndexOperation(Project.Instance), + new BulkUpdateOperation(Project.Instance) + { + Doc = new { leadDeveloper = new { firstName = "martijn" } } + }, + new BulkCreateOperation(Project.Instance) + { + Id = Project.Instance.Name + "1" + }, + new BulkDeleteOperation(Project.Instance.Name + "1"), + } + }; + protected override void ExpectResponse(IBulkResponse response) { response.Took.Should().BeGreaterThan(0); @@ -58,33 +84,9 @@ protected override void ExpectResponse(IBulkResponse response) item.Shards.Successful.Should().BeGreaterThan(0); } - var p1 = this.Client.Source(Project.Instance.Name, p=>p.Index(CallIsolatedValue)); + var p1 = this.Client.Source(Project.Instance.Name, p => p.Index(CallIsolatedValue)); p1.LeadDeveloper.FirstName.Should().Be("martijn"); } - protected override Func Fluent => d => d - .Index(CallIsolatedValue) - .Index(b => b.Document(Project.Instance)) - .Update(b => b.Doc(new { leadDeveloper = new { firstName = "martijn" } }).Id(Project.Instance.Name)) - .Create(b => b.Document(Project.Instance).Id(Project.Instance.Name + "1")) - .Delete(b=>b.Id(Project.Instance.Name + "1")); - - - protected override BulkRequest Initializer => new BulkRequest(CallIsolatedValue) - { - Operations = new List - { - new BulkIndexOperation(Project.Instance), - new BulkUpdateOperation(Project.Instance) - { - Doc = new { leadDeveloper = new { firstName = "martijn" } } - }, - new BulkCreateOperation(Project.Instance) - { - Id = Project.Instance.Name + "1" - }, - new BulkDeleteOperation(Project.Instance.Name + "1"), - } - }; } } diff --git a/src/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs b/src/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs index 441c7a60872..3e3785561ae 100644 --- a/src/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs +++ b/src/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs @@ -39,6 +39,7 @@ protected override LazyResponses ClientUsage() => Calls( protected override bool ExpectIsValid => true; protected override int ExpectStatusCode => 200; protected override HttpMethod HttpMethod => HttpMethod.DELETE; + protected override string UrlPath => $"/{CallIsolatedValue}%2C{SecondIndex}/_query?ignore_unavailable=true"; protected override bool SupportsDeserialization => false; @@ -55,13 +56,6 @@ protected override LazyResponses ClientUsage() => Calls( } }; - protected override void ExpectResponse(IDeleteByQueryResponse response) - { - response.Indices.Should().NotBeEmpty().And.HaveCount(2).And.ContainKey(CallIsolatedValue); - response.Indices[CallIsolatedValue].Deleted.Should().Be(1); - response.Indices[CallIsolatedValue].Found.Should().Be(1); - } - protected override DeleteByQueryDescriptor NewDescriptor() => new DeleteByQueryDescriptor(this.Indices); protected override Func, IDeleteByQueryRequest> Fluent => d => d @@ -82,5 +76,12 @@ protected override void ExpectResponse(IDeleteByQueryResponse response) Values = new Id[] { Project.Projects.First().Name, "x" } } }; + + protected override void ExpectResponse(IDeleteByQueryResponse response) + { + response.Indices.Should().NotBeEmpty().And.HaveCount(2).And.ContainKey(CallIsolatedValue); + response.Indices[CallIsolatedValue].Deleted.Should().Be(1); + response.Indices[CallIsolatedValue].Found.Should().Be(1); + } } } diff --git a/src/Tests/Search/Suggesters/SuggestApiTest.cs b/src/Tests/Search/Suggesters/SuggestApiTests.doc.cs similarity index 94% rename from src/Tests/Search/Suggesters/SuggestApiTest.cs rename to src/Tests/Search/Suggesters/SuggestApiTests.doc.cs index ddf6724fbf9..2f04dd38193 100644 --- a/src/Tests/Search/Suggesters/SuggestApiTest.cs +++ b/src/Tests/Search/Suggesters/SuggestApiTests.doc.cs @@ -12,11 +12,14 @@ namespace Tests.Search.Suggesters { + /** == Suggest API + + */ [Collection(IntegrationContext.ReadOnly)] - public class SuggestApiTest + public class SuggestApiTests : ApiIntegrationTestBase, SuggestRequest> { - public SuggestApiTest(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + public SuggestApiTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } protected override LazyResponses ClientUsage() => Calls( fluent: (c, f) => c.Suggest(f), @@ -31,22 +34,6 @@ protected override LazyResponses ClientUsage() => Calls( protected override string UrlPath => "/_suggest"; protected override bool SupportsDeserialization => false; - protected override void ExpectResponse(ISuggestResponse response) - { - var myCompletionSuggest = response.Suggestions["my-completion-suggest"]; - myCompletionSuggest.Should().NotBeNull(); - var suggest = myCompletionSuggest.First(); - suggest.Text.Should().Be(Project.Instance.Name); - suggest.Length.Should().BeGreaterThan(0); - var option = suggest.Options.First(); - option.Text.Should().NotBeNullOrEmpty(); - option.Score.Should().BeGreaterThan(0); - var payload = option.Payload(); - payload.Should().NotBeNull(); - payload.Name.Should().Be(Project.Instance.Name); - payload.State.Should().NotBeNull(); - } - protected override object ExpectJson => new Dictionary { { "my-completion-suggest", new { @@ -108,6 +95,7 @@ protected override void ExpectResponse(ISuggestResponse response) } }; + /** === Fluent DSL Example */ protected override Func, ISuggestRequest> Fluent => s => s .Term("my-term-suggest", t => t .MaxEdits(1) @@ -158,6 +146,7 @@ protected override void ExpectResponse(ISuggestResponse response) .RealWordErrorLikelihood(0.5) ); + /** === Object Initializer Syntax Example */ protected override SuggestRequest Initializer => new SuggestRequest { @@ -229,5 +218,28 @@ protected override void ExpectResponse(ISuggestResponse response) } }, } }; + + protected override void ExpectResponse(ISuggestResponse response) + { + /** === Handling Responses + * Get the suggestions for a suggester by indexing into + * the `.Suggestions` on the response + */ + var myCompletionSuggest = response.Suggestions["my-completion-suggest"]; + myCompletionSuggest.Should().NotBeNull(); + + var suggest = myCompletionSuggest.First(); + suggest.Text.Should().Be(Project.Instance.Name); + suggest.Length.Should().BeGreaterThan(0); + + var option = suggest.Options.First(); + option.Text.Should().NotBeNullOrEmpty(); + option.Score.Should().BeGreaterThan(0); + + var payload = option.Payload(); + payload.Should().NotBeNull(); + payload.Name.Should().Be(Project.Instance.Name); + payload.State.Should().NotBeNull(); + } } } diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index 778f15fe53a18977a330325e9491659e16f2a9eb..6a1aab144cacf3d14c99c1a26bc9bda27c218936 100644 GIT binary patch literal 69632 zcmeFacVJY-+CM&X&en4_$)0SIO#>1juw)aYDFH!3Rk6VZ5fraM5CxId4WfcTV!IYB z*!5mDDE6+{8(bB8_bPUenN!&3 z!1IJDgb3ho+cqKYM@YX$raLArNY3x^V7^!zeWCh(x%UgzQ;(R}Ty=Cdb9i>vQB|{N zEnJvcRCVZKRoP<~R?S;jHEzEtRYzs!9M(TC&+4sJPZ}@8-qI91kK8iNEp3zNS!K%s zLPVqxA;n$Z7x5~@8xaZ-=eVKlCWaOhq6O*T)6W!5r;;fBp9?i47JhZmyB|fM_jqzd z$6u2aG4Ot@k)pC=+KzA)%=e{7fcNm>{)-Mfei85~Vc3f_uB*1&6$87ef3`V08w|D$ zHgZE*2z|dsSl>T;*n$iM$yNcI*$4UC$&K-4<7gB46+g1g5JB-eJXX~vMEjg1@#lW$ z8_lE88q1JBU^EvCVJ)LpGEyao8fGep#M|pnM!w77 zNKP|45@{|Z%|avwnBrr&1$A*=CL>cxRMN@PB5A3hA4|C!b*!1UdjIGjsz!M3!zL8 zL{lgIquc8xpBrh$$@*ttH~q5~+0p$?1uJ6NsKOZ`7h~+qPvL zRKZALkXqUO5pAwPY)Sv-J_uTJ{Q=?q##9|BGr!~{dJ^dtMr%kESGh!S#Olo8s=alS!-s{ zIH*6-R2rm?lNO<0803mj?L>ooAF8Q0`;^pX>PWk0nHfq*)e~zs6o?k17DvU|PWVOH z$q`?TpL6?C!j<62L}MvBOF$Kr>Q7p0jTGt?D%xsN6fBOS(-l!pgcvlc436xZ(@<1v zrgkC~mn&XHC(3eZW4Q#(Nk*3=t)YN;rz_OFUlm#0EAvkP%cYCVTQ z5`AzeacL|XVl3*4>BDhV#rhP=t;G?HwQ$->H9)X=7>HFUQo|9}+bMV^of$zIz#EBh zCHhE3ERrk4>{AS{??xgW3dS_oiII)OEkSS6?M_CfMiaBUkwWRzi+C<%n@xd^MpL@e z++c_he7nq$==pUKgZglY`*dh)Xc!Wk$3RO8^-Cj#=N`(7xxi^2uJf9m<=wS?-r?Rf zIZj!#6f?8xZyfRU=@+<9)A%bu%s=K{bbC7{Je8Lt=)9Qq6oVsVXF%KyJLzYnCZfm` z%C+i;8mUPhz&O~~1KqNJl{EQ~tP;|xXO;TzHF?H=H7N0oa||y49`RD z3U*UDFHL>5MYXU$DAvPv>@OUD+0*^@@8vV3em9@}C7B7(vl8ttm3%t}735>2wyPl8 zD(9DaUj==+l!%YPOOCF#VpE6To$7=3flpNXa0CoYaEif^KQoPD{x?zwz;?GE{*_zT zZQq*uK%bIykZ0AZv!xIRs;c|>v)lx#UZ)9rbWHGfzn8fC@tEJIUD;-adl=2$bq%Um zGsFFiSvAU8W`@1WtU@D2MVT3*YT7SR^$Lm=&>g0B&z^&B!z)+FOrA}xSyR%Z>I%wZ zS)p_0B?ntZsO0ixSULi=z@>u|9yUVB%a>u93)K2plxK!w8`*zAc_^8}ERd$WGiZ;L zPVEKV%dl|rlE8}5SgZ#j^K;u0EUdIh9fE+`7*nrmQjUOu4T55D#5clU@kV%%MmVOX zfC`sZxmh^k%knB`*`k;BdOO<&^PBgEwM)zlTEoJsbQ4&LUqgH>D{#2AteSLYb2*_( z=fu8`6EXQ>9-j`sN8op}USchO47JMahx}GLFGP)L85xYmbe~XWGC=*8?^~g|P$=^k zfOoN~Jw*+9K6%8P^)hbCEOZ~8nF=<;6josC>YAkPhyPu!Qr%TM zuQ#g^AAF5xUNL8GBZh*oxoAOhaqi) zZmfNgIvIM(V07!uF{-BwK|FOT#dEoQ(OT-GC%{g09tT;sK~iN^o~|Sl4)zK)Gm>=Y z7+Fui%xtB+m_O0E^Fx_K5TUKsGH`Y8{-Ry)&e=nAl7a+uCl^%oGM2G6~)Q-`}pncMP zc+;P*o2d(!ND9dBXsn%}9`=Q(vGfK~4_U97_I1VmJIbfEuD?(s`OBn5gbVJE(8$1` zbRSxi0|GM*|I7@g7`>;!Ovhb)8uBYAsMJgobftB7$jE&SE5(4=#QT0ZQ9b?m_I=^1+@XxQj3_G zab&@4Qmf{~6H(ik>Ti2e5_MG!XNt~&RC238=yivkR=X-gq_X{XXYYeWS}SA zC+y9h;kr;*&7PsU3T>FD!S5c`--e5_DXPC!pdDbM$RoRy>t9C6Jw}?DLtt3*;V6w= zV`i|W3uQ32)g(TT%|Ny;CUMr)aopDG{@zcNjdADgfH)H6=XWR{iv~`PeC4B0?rLUm z(t=SnA7$Hc9UHvuIV74`ng+!667{B50WQnDAe}PR)N#J0P!U#kM_RUR0|m9n3*)hXeW6TQiuJD zWHVC_mK`3CXBD{HcP2?AI6bCIA#N9?shbw!uHJvUt`>8Utg>iez^&%$(?U1GZAUMl@%k0~7YA$Z8i#?j?1V zq3kWlqqr-Rn92C6E7J_wK4#`~$f~QsWGMSQ3o@%Wl3kgv{W2f3472<)pL8hmcNQaV z$1-)(#RFv2mk>~+OtID2K%M?yUEgV4#v08(%muH(e!UL7PEoxM)OgFl5L8pm1!jgM zc=zi~@wwF8bW3ZiDKLHT&&)i4T*<*BwcB>{^l=U|gTdNvvgsh89I7+#!9M34JlD8$ z&@|?cB~84FqGamdzB%tLO7qQmb32;xb_X*$2zc$wN+i~>Nhj@kUA7?)w_G2 zHOOgZ?gL+?@+#u(eeU;Cw_BRn?*TDd*TbY;g4XTMcu#O{Y`USFQZu|i(KUJ3OZ2tl zj`e-zW$8p;AV?LV!aRKy=$qKK3kUz}Qj1tB04Xd@Td|%ABeRI6k7J2YhcYu@hBAjC z`e(L4*ly{4#?GQ_-`qZ9M}FC^9!)5$R$J(+2lspEr+&B(Li*{;kE`4^)ww!!H8X>& z>_62PY3^!)UbGL-%jl2mT-~@Hrsy14*X4eZCH}0l{?vYPH&J##&X41%()g)s`!+O< z>c4IutKtSFzL~k28qVLxcHu;3^IYN1A!C@ohAP*Nzc2G~8lm~;8%uj)KT%&{*69vJ z2lMG*YB5}5B$rVlIsol^nq+QmgAa>bAG+&YAsEW?!(b^Pcg3nk+`j_SrH+{)u3C+b zLs_nDvQt^&ZZF#dTyM2JkZZ=Q-adVCzf6{8nB|u#^UIvcGR*SJ6#He`ScX}CnQnfW z`&ourIT_uTUql*RltMm~Ii5W2o9py(5YCvdL2Kg>Yc&PI)U^nFxAb%(b1~KRqK3l3 z^fHcsfkG97BVg3H437BDuU>~4CarUZz}YPS^exLi$YPW)>q`M2(VIBk`U1vxINkaY zEX9XzzKeA`89TQtHFP9Lx+x^(6s9Po3UI_{-Un=6?vVa&QjHA#+zcG?W!TIauGEF2 z_Xg0B>nLz)tQ7g%A(p7E<4hcc_*y|mleuq96`cBm%$M*25HH`ZURSm zKi3T{T}bOjS@Tj<)C#4ZMM<{*bR~>x=(#_FyRmA{qWN?z_zB8Ow`ER5?)p&k3*=3s zc^T_!-WS!dn=b?nXBL6R-Y@cBRioek1%mHJa1C3DB}()V`SnV_AxcG$p}DdeQC1O^ z#Y4T$D`@$DS&%BHQsmdV0C?)k0<;P`5^B~xf zdYO>>0Kty5QLmtM3Rx{eD$9S5;47}#L~Ywp&k}E(=2)0~-l3wQg_smJP)OsGBR+@y zo7E0Cvb&K30;zexn5PsBGQ=ddNvj*?s^N%F&4;YU$9R(&ujVEmEchKK9xP<-kJVFO z>2ij<%iJ!4WVJ<83;5hy|z zR=(qiPtjYfXgB1gyAAOA@1z1x5+qZF%@qZOU;kePtO-{O~$w?7~q=~}u6jB%9h|iRF*p!||lB?l$f2=0%h}oT@rOR*) zlbeO3x;PRe^&~^#9u!hB907xJfsst*Q4U|Z?{T?Xb-nk7*ninuDzym{-6A=HBKL9` z907xrlX2LkD&sf;#=b6tBVg?3GB^UpB$vSvFebYUj(~xwP$}gI7*kvZM|?Hj#5JCa z`Qc=mEqVeP0TnN$x?mWN^9{p&jVy1rco7Sv@WfWA_E00W0HJr+uI`Ft<`gKyTBC(e zCDlifEIGX&MPSoR*CvjDaj?tah|kE6ki+D27Pymtx`l9Bj1F-c^;aD1`x&nMroS~^R>WFm^Oo-K!)1G$H!3Pt907+T*u zyB0Ob@%gDKJ|xP1MO9;OxX)UVt`gFP25hhEjQ>(sP&gqd!!Ns)JU=0fQ^|{=m2Uf3 z*@=Km_?CS0nc%e?iqz~>N_dCJ=bebmCXsD!f>Kb1yh_0wNJmb#uXY@YTQlbOP%GFdpK$S3QAPDM-V*Fax2)| zlbc5gM|6@fpAv3!6FOGwNJ<@RLm!>~q*g*-N09|2asWh>1xFEVrW`px=iIcAQXlUs zHRF{=$5)+}cC;r#=Rlo`977^yG1s6h!B)Ud4QlrE(S5s4^(`Wic;5CtJ(dzKa1%QE zWwEC@h7-$9H6KSJx4H^=U??ZzI!e2JT7DOKPau(*NX=DCSuoyf^Cg}ZI&kRJ0_>J` zL3B^3Q;`!%>C(k3JdrLfZSh2E;$0NfN+P=>RXHNp z`LSX6-)e~^DA0U1TvzjQCHC}PrvR=2*Dq*viA_5O@vdKKo`L^B7t#%1}oq>}V1oaKXT#q=ti z<%3nl^eXHx-K%g;XA9IyxbDG2AK7K-H8dUnjlyf zdpCtGw1#9KM>OSNVW&rntd>iN_gj13rBoD^(}YrzbiG%##TH^d{h%bpIryKlS&(=Uq zT~95YoUY`J?d9tN;mDw1C_FuFhQc$fa109aaMKGrNNdo!`kAq?z{Z1rD-?mI?Nz_Y zBBj}PI4sL<<`7FNhZWgxIIPV6z+t!SZya{d%0e;;s%?tExb0OtEK-^+=CCYV!C`r} z7l#$uejHY2>pAR}9n4|(?5-R_^>~V4oiFd`kG)u;G`k;%W!e2%u!TB6GrE{n(__zM z2K@?=d2VD{h2|`FBh!0WnsvMv+q=gg&0FBb#`c(_d9%IPxT+t~YMMRA5B910%=A)@ z%7GT@T)tzx@z@vQ@^5$AT4MkBcS@!GBS*mahs)rIZ$tSBZzv&g1xX;hQioSj=o8$+ zg6<&#N$XP#%7AM!lGoRXz9-QRhA-8Q9LBVfN)&N5g=8H^z_`X`aD?vV?@#qn_wv!3 z=}a+&5ChpUjHRR}gXXbPlUQsrDDJl!q10a(?+1$Gj-{(1r;ns5i$0Qu=jce966reU zNLc6|H*~npnMQi3Y^)Ld(-#eEkX2uQTuV{!O!I%g{s<&@if4~Sk=a)A3?^V}NuY9| zSs6Fr57rh);fP$7JL6B5o4Z)qk^U4tE26Gr&{epQ;renWkUEIUL{m`RC?r!TypBR@ zD~|a3!>6RI);+|$p8Qb0>;?+l*f^EB?xv^X|X0VnYrA0hYATDt6Q_h@bH zVi?v7hSe3Si(>UCSni=$S|dIS2vLUq%Lkmed4?*6`gCu`0JZF*Si^ltHZyQUDA~U* zlz9S?t)p(Bfkq~n z!n;CKZ(%Qj9--}az2UtgG7$( zAYx~4rwIfzleJ{|k`9Sp{*{z}CgrD#Eq@Vq_AM`eL|vheMl;vh*>J+sOPg?iCQolM zx?aQoNIXrP?FaExBW3kcu>nmt;C>5Iciuh~o3eDndQKhXrq&lOU)oh!*jS|-;45g` z(4sS>Kf@f*B>QX_e<(zt)n+j`bhu^8TN|OHq z^L8ZrH=q1*UCDPN`MX*E5}!O>m2|4VJISBS^4Giab@^_W>Vees5z9~LklW7Q4O!h; z4(*WWW&RsFOFF%LUWfEN-(--Eg|$^!_1#HKafa{qpKaTWP&kr07kX&@3W$}k6Yh2N zgn=yr?hj?!5MU?#8ky9W`fn(+8Udg5)2(SMa}9`Qegml-Q{B5Ui_*oNCfi}0e&8li zU{YN)FeyT>M1^Vt{N7}ZLX&wt-wAf1VI3@k$HQ1ulfgu2H0CuGnO96gb>ueVv$q22?*$W@Uat+T_~U5SfD*QzTB zCus_{njb|$vGjbMhPA?~ONL9rdW^68?tuows zYHv!#Z8g+6D8``wqoX>@59hwozCNS8`ZP~RrW&p9uy(cLXZQKZdVYXEvzJej?s(V=(`AvmlI=5465R+Te_}lp7|2eb$F7;1&}zj4#|6BD^j-DqFC})mZzz0ujGZ1) zYkQ%3^TLRvPC#GCU~^-Ilhf@mE?oz`R?Cus_L6~|qprO@sBT%+0Qf%{On8CTLFdYG0TuSQ)>QH2nHc%DDVD|n#! z9*AJb<%Ugupoqq$dgi#AY@p3AW>u#iA!*>EfT>21o>=J!%?XK|PwWm{^G*o_VF0mJ{Iy zbTHvy+V(^vrW0lbJ!%G5IziJ3IbkQH=8p``>keF%2&ES~k^0`AY_I;MUc7(*m=_;8 zc!CpzWIpTB(@?rVYfaAZ>7`ey*Ft|ub02srvorkfgkw(FZur_H8&PW5wRF^;cw4&R zU*Jc3^lHRBD5yqJCz`MtPNN#ZEpCnKdYMj?+csf`9J{3XJ?ez4-ikSv-Ea=nn2x0? z-JdF=<26(f9UnP34K)tj$^9h}3pufNs&L{%sdmFCvetq*mTSeRqsZF6Y;FI>=e=gg zBct=3{6qmis_hiyj84Q&r$AeTX2>(0e5b(4_qod{pv>ucPMn%S%W^a5I9spdBL|Om z@*s(3fF55nu+|REkXO=tfY$;AF{i+8IMP6!sK5f($Wi-Jou+^v?J=^E9#=QR5q1qP zQ3;3YR@kr?5**A+Ze!HN%-!sSR z*}s^8Q|LIXS-B+*W@(ODI$bwak>l|0f!DkGIv~2LS7<&E-OE(yD4^Xjf)zRheY}Y8 zR#s#%D`6f^J4N0^T&E`DL~+O|F1g$(PG0ULn%{T3R(f2>DFVamYw5v?L8k`X`O-ZV zgKn2921c60ndZ4Hr!eLeqW@EmE+l`tt{ip4R_g!M?}uZO5P{(|j?L_37+=Q5CQ8ig z{yCI1vomt2)F~+*kmn>Z5jv&CyPb`^WoM7%16QZy%9^B;yt1a$DZO%eto@|aNR!gN za79fErI4G_sr!KwWlmXg;2vg)Q|9Xf`{Kwsz}4JbN%I>HBnoUZ~pe1V?UGZvGf1 z>4mEOd~Jt$moS`qtr6B!H%@HT1wi!jL}2-0aJHigrLRWt+BhtqdU;T<0PR*DRXa?z zS$tnW_p6aW7kH=%=qe8#4RpPS4h6c?L)iu#2YBVQ->(&hQxCvf!%l$&rcJ(CpZN^& z^szLru0|Rkap$~{`GQgp=qmN!lsc^Qtc4LStPbrPQ6+65X*>HEY*p70eEJ;0XDv3M zqi(mFtF`}WOdd7<_M~fTP-3{Mh$oeXX<=UcEPQ6@#zKX}S zf%xSLMrA8d2PatFoXF)^zasT{5iC{-6y9(c z@gvE>WlprvQV!2A3^-QmWYnZ#cTO#BpBi*i@i>K0T{X)4m4xlss;d@IK6}SqHG`_E zDXY-*JZ(1GRf^OJw8A!w}t9^IP;F>w4E>yb^sDeQHu&%O~ zQ0neor8<<_udCGVlxk;JQG4P-+FHU(Rm6!nVf5E5`fFi8y+_lnFsLF$5wNi9w7{Ss z(;GTeua5Ago!+CG0$o`2@%QOv+x2NX`#BZuzqW0^Tg9uWC8;w|g6>&#AnfbbG%Lm; z%?CmNSEIB~j{0o~h^epv+8upx*KWV+B;BG_7ieE{^TW_)sq5oVW-xlUdws0XT zCdG#p7nb2NuFwP)0JUt#SsJxH4=u zpA~**K#tA|{ROs{YaxBlker&&y3)sIg{w*Ks2%F#v%(WduC;?4R>A7wAIu9VkJZI|_p^tjGscc`I|k0|{Hyh_jSq+_^8aRMq6oW##5>d%`=>}Vr+ zZA8QWVC;GeyP90}cfaU}k7oIxn&EIM&gU18q27o(%MZzQa-Oo?ao6$d+nSA?YZk-LD&zt>)U9KhHH@( zsPC>r6uWlUPtiOL=O}j5&f}3de8zYriYD;p<8MY-g^wac>OnKchmeX6B=$h+egG6c zgw+evg=iQH0I{XJ4pk*A+x1jL8tTA~hL%!&GmpYsb-PCB7~5)IN90a)kwiflX9(*7 zwOmQ&p8%?IPHcwqc*B=uMt=PU&z#9i=CI*0A@oaG)L&mHCD;Mem-mYA>Kq`7)KK1l8*K%PbS$z4I9x0 zu#S3*a>?;dEHJQyDm+6UbPSFpaV~W`1mU|PpDTLdP=M>`E8DRhs~NLyD1qayL>J{# zY05{cV>bLnS%H1A=cC>IKB5HIN4Q$``v@PtaD7B69ewmGI#Aa>DhfMAJFrpvXf1TW zM>NoskD5FBsFr*bZ8!^p9eh;VnUA8)2a|`2!%lG*rBhk1hoTLGl>vCe&vVZne)mv< z>mFPo`Q0-%=N?Mw=$^L%J91A+*eTh8f!aM6K?mGJ6OeMx2_4;Y2)QTHumFNiK0d_g zL=LI*cceo)b5f-FJ91Jo>?FIefl73p6lus;X5bNj&q;gwokR()lW;`mchb0=lPIO5 zlh$H>>beh=hMm$K7^t0eG<2YAO!W<)roj`s)>;@$RTABtZaCLS(F|Mf zbldKnw7b(C$E4kpmp5bE9!m5GJ3ZK_wBvMZ#?CyHs0uq(o!O}x3RWm*_$=r(xK>$^ zR85tf(fkZrE}^#xxpiwWmS3+maC;#K@D6TAXO7sBGpoZ+b!SFKolrYxqUYrb!EFtA zF{HeB763eZN_%JSHh8h$nLVAJIcN6V&Y8WOUT|hFIP(u$NqdK#-mWuyHsi^QP@*R6 z)O2QN2WO@$UALqQy;#JJDPebyGb;GYwr%d1DEC>bmdie2rw^B??qix_IBHmry7Eqv zzY~C2xFSP)?4Uk7GeZ15+yGxosI8#l@Ya;~*a3kPa?zjk^g`cicWq&Z>;50Px~SoL z_%ARr2I?8p-}~K${_R~?=)HcpZs&BFp#;>fIJFd6+Ffkb73v$Y*Fyo{x~+dfxk)R& z7TvwWWeN830g=G)-3dN(_vZc!d%8aHZtC9XU7qN(@=i{hn)|^nT+xIOc(u^t?e78G zn)^<>3zC@Te%Fqhr@7%$|HVrppxNEpvxDkrzP=#{uMU-J!Al?*-Cl5l6HqEELKR99jL}f-Q`QrocpgV9 zMOmm^%LF^fs8hD~7kmkHe@q70Vxya0;9mB??+bf=Z4Oo^$4jebX;y>_G>?71Sf@k zy*@8p5S$eCGop2UxvxjnOjpj`T!TD*3{ru*r;LcdbGJK#4~i>Lzagj}KkI;RE6@AlEqZ+3-FCn6u5=7KQ`>>3kZ*z8>G9-S zb$A&&HovZSK1n*OD$|z?p)|z!6`DUpT|t&CkPoHQ9sF!?Lqz zrhkF)QG}1lVSLy6=G7L&Id{3`aKu;6uUrl+!2>T`1++eg_fY5){Eh|P zHy21+dzmu8%OtP8j92E1Qg>6y?t|^P7oK~f{eGn2nZbKW00mPTh4)cNkF9eA44eTg z21k6Re9xvp;!RhABe_~XM5=umKIaT98HFQUH~^jtyb-?GFSvfcNj$VRe+(&+mlC{^r2He_Cc zGS>PsYX!3_t?FBxVNq6<`*z3_=)nP-t_#l9w)<{!muBMed7M6lGIi`A+C7Idmd{zb z4*qW@8=?y3*(k5wHwcHa&FZ^?b5M&NeS@&UCwq*N^|jIva*+@3LYREVkqP?CS+tAK zgeZx9i5ikav=6pYJ^l)g|MR+;5=eLUdEH!F#YMUPZi-tB-QLU;P%$p2gmlM=Gf{nP z7XO$DjvO+tpg8(Qs0pAFQm=wVAOBC+_HQ1E94%3#)z+HFqNf`44?*k0X?p^qul|2mxJjgeJY*y5eMN9=QRQcIKsqV6Yy*Jqr7y-3|*Y| z0HOtdPvVdAVI#v~03oi_L<9cF^xg1>(TdY!`h~>b@}`u8L|H!32bg{st1d~1W@;Ky zns-29NW8)HKBjH?#F@x+Hq%Dt{~Q|v4X-o3oH+;O%`6Cs8_J%-X96CGk^Z^zHzOoI zah`H4ac=%k$&k37IU+_fc}#!cyrt2KQrK2ZbQhLMF+H5=bf(?pQ_fOxPchlqJ4zbf zELsWu#}>`342dxg#V0Tw&-@0^eDPA{8z}csj=xzz@%Nx7BraikC2O|wiL;b-E=y2- z|4~4kkqM%6nR8K+_%Y_ZUHBAUSuBgbln9CMnDa9@A@MAidxk;rg{=Rd%wJtWoF^k> z;qX$5zghW|lP{i0yphZo^9qUfj*)HaiYfKRBBJA98?{*rQ|g-%Uk+_4EHcM)T%t*r zTSew%w0DHl4l1TJTceScg!1qu+Ez?_w^*(dkHM9rDEyCKP+ zoOXAd()!@rxg`WMz=ERFCJrLu`NTyi;V7!lH?Ha5~Dp#LPN!y zjLwP`nXh9^y~pTVlyE6dNj_w>k;@y7f7yt7=2kvTADD%s85^;JI7;I8Np~DPCHGEVsso^eHs3VFDjuw_qxA} zv5Z#06XUT{-;>c4*3u^SWn|@%Eo;OyMnAAW*N6idUB$iUdT}VDOQ5AU+G`%82UyE3 zViBWvxWC*YE@E^uyt`7|E-q*E2z%*vaRsA~xHaz-*DxwBAibO@oeatNVO;qUytvS-x0V2@jXLpBcafx#siUQEjK3a z09_IzdR;lu#RWvWgD=I0W(fO=&x1q{4?O_Rt>KW75Pw7-M*OJ&@ek(If0sM~&fi1N zL;r{2ml0nPcumVoQ4u1^1WW$Lx!wbojJa%O_jSZ+i+3% z59DoPdN~j{9rzD)`l6r*I&;y|pe!wN3yYb}bpidLH-HWl#3WGA{99E=!d- zkL_8(^xEJbUdw)B#G=z$E{_wvnd5Cte{zWP1=Hh^N-axuSrm+U7UG_wjw`?Ig7vaI zx{EldnCOUZM1RUB`iw>N^aRnPnYNTtd}Jlj>l~to#fjc;6YatB%Q^3zQR3`j65SXf zI+x`iEui?#93R8w-pv{|7{uR~vKv(S``o8m6-BMxz9g1?LCUpg4JJyAyVUZ!J{Ls9yXr6b_^?R&Dn*Bwoau!6t2j`+V(U)za zpGCg+Qg2Nh3eER2y~d{azKFYduZ|xM&fQFB#wfmm>7xY{zcE2{33IM1r}$##cW3@p zWyHCPP?&I)p4RVTmrgQ5)B(f zr+|jUl*j{-kQi7_G|cg@u(E{2gQ5+oizLyHnGP`8qLZqyG>OwnpDn%#?Q$%mEzze- z?uZ&|;*HzixM* zM)la42gEvsPOPsh8JLp1s_KMpjKk*Y(L*jJ~O6q9SGF=~xe7YBh3VYDUsYQ;v; zQ)IQ|)Z)EmPeI>frdG+b2%WAaKdK~jo=$ryYFjKApqKCF>(|q*QNDgX-5MEeygNaZ;_j-N&*He^yhfo2)o*ukvqog~ z?&5BZ$j;rxLtehQ*6!jJop!vrx7<^_rO`^W822GRWVD4_Wuo{(BWjh2;s=GeRrbQM zo@+}`>@D&dNi z@Y7lkt+8f^yq(;%o2&yxm51)M4ibBL=ss(vSnQ!kt%JoH4?Su9Rg9n`KDPRK>k#p< zhhDRq#NdH$+S}GFv6qK7S%->+jJC+V@YdgKu}q@_%0IPci#88^ZOsusdC0L26L~mX zr7?X#`484yQR$)Iti#2Xbo|I^!ahRW;eLpg1tofRi|Xp-G5F7(he zdy)9cLo@AT#WG=FqKO<-abLh^w0`>iMYi>r`k(J zZ$2$1p9QTG#Uc-#WiJyid+2<7xmZ9C*s#va>=oh>4_#%qh<|zLI=fYT&FBfVU$Hnz z6zxj+TE%+fR{LbpGJ+7zXZP5riYq)c*E(I?tq}Gh)5V$MA&m~i{Bovvf{_}VXNl)E zqOp0F_?MQXF}+f}rxA_mm12vMaKz2O4SBJmjX4xt%4xqUEj;g@ zBPNa{Q8mw>E9Nj#d#Q890*z>gbgo#W5zXx9iW4;=JI@uTD#W&&CoX2BX7*L$T3^2N z#jU=4=ZkxN`7RJo`SM*TzVXn*_C=za56_jI7mG2Bl${rgi7E}=ebT;I{6(V!t>=Ia z(vnn%OT=uAs1BEiBQ>HrTp|`J#C5n-oXY65$kQdS+Lwv5HJVra4p5s$&z5cix<{}&@gt)xT!*Vfu#qH{&)US!9*T=LG1f!*_G*#w zkQKXHoa~{vxJIna>qMnS)JE5d8iiQr^abp1!ASY~pW-$zpA?Ua*E|#l+NSeO zE*ltoLWIXsjZ~j_LKHAMEkZr(36a!k)I**SJv1V#pAacV>Pq8DF^thEuv%hoImSal zpoKagT{k`@7HdR3`6;oS(P{XE$42p#I8CEGCkS+|mLyxACL{6N5Tt9Tr^O{olFNIh z-CpV$(Z*@Y6VHk}8Ifgi@tpWh<%%(v&yF99!f8bE-H%y)oEm)@4h64FlvqDq3^yVM(VVa(S9$B@fxi}`@Jmo z)rk7%D`J{P)IVPlhiG(Fbh>y|9Inv~(Kyi28oh+H*TnG}y@j;bM5{&xaVPe=ID=7Z zq%2+zbUq{1e*Y5JC`nOTK0Nk@ctj!iY_7FYJnx~#*xO>0LXqD~CdS?sziAXq?g!-G z)4nHSMag>W72#NHR(G?GQ-Kz%e?Ua)`c1JPfjl?4X@4P~TSbCcLZr9o$z zy;)r8p+jRIiZ?tI$65Zzj8uz#EWXl+uF*dhKPto{?qd<0;My4%pNJkFl46S(#7Jq` zB8F>3<6(;!qY;gVEn+W)Sm&o=CZmhRcSZAJpNShZlEn*weq^Lh4?Yt``%vjFI+4-E z;>P%~ko-)e<>i~q&&8sBbCO?(Ig?zg=UQKgC5+VG<|}cMMr7Gn;w&W@p?T?Rae+oO zFMTckp(NSre~VjnJ{qath3cCyr&Zu==6f+*rST5_2eG$Cw6pp_v@lY;!ym-8 zjMVD%qgd;q#@Ns8dh4(4dh4&^X-~2>_M2$@i|fy`WB(D?dMF+HAF-B^>IK`x!x~Xv z+9sY*l01WL6VGczGuSrqFD1#|6>^J8a4B%j6@ za+pSR8e_;YN|H-3nZylGaVUZ!?2X zs~A>%UCfb}YV>pEZLx%W-9z`pisi2!dL)*VPamlAEh>IIRw_$pD)dI_ZLuPCr7SkD}Mb2Fv?3l4YOAc9ze3=%-kNe13tFlx0TV2>HZO z3Y}0`oYyGNTd2_VxREzbR%I0GRn{kO54q`hg>JD2V<=xrULlWud%9BbuQX%C#ENJh)Ikq7d7XkuNeL zTkyek`JOM|G4c~%zGLLSefhF-o5~kCuk>$u&F%csEO%)Y_$i&uay%n7CohuwXhgOw zlG7AoTaJ~7>ol5o7t4%BT#94M1HH$a9kxXk-up~`-!Dep2Ri6>1!OwVx;!MC&~()M!sGqduc@V zTPEuiV(%`OyE0OHjTLflUs{WtrqcNIu2mk+NVVokGNTcB;v{*TM&yZ;s%jdw$AgR%j{J?ly9H!LuK{_KGfU3 z(1(WF7x~bA*2O*~>`Q!TqmNQ8wy*G^x2-FE=o0HH zANtK|^Pw}W)jss7b+r#YXR z)9jmlXr_IO56!l3^`ZIpZ9a62eY+1GZ{OiVE9^Uc=q&p#A3EQ@+lQ{Q*ZR9u)V>mpv56b2@MN#=}EiJ{naIdx*w#4$+u?Sbm}M;hgVO z`w{uOhl19lK2&Et=0j_&b@C5S@=9yHFKv?jPr2x1>hyFfJ$^`+fpz2+98Z}}u2wchqgK54xp@9-p_x8C(xeV+B6FP~$*??aoc4}5mk+M9ej$Jv{GX%p=a zeQ28fkq^zZKlbIDZGYlJ^X)A@$z$wKeWf37f969g?9Y9YXW3u)w485$>65(5{>q20 zv%i)PaNS$QZqZeF|CY~d^w+YH_BXQXRO%D0qQ2tNyl>?ojkc9vmG_-q(bY-D_wCmA z@8vj_JQ=4gzen4r{U8tUrTri?jMP=#kL|SlD3@x!J+ALVHp+2WSGpX9k3%@+6M z{UR^bXsdWI?^h2!Dj&@I%|njyVBYT@IvD6b?aKQ@{#|R?C?3oEL*A&-Qu$ckR(YRB zUjhl^NsWdYkL4K#JzIUJMYOtrXkJM!{((txqK5b(p5yyvRIb`0l37zpGW#&~=Tdr9 zt~q!`z%5I~e<`E9dzBO4A6N1dx!lX3UkZ{pw4K{qt2pbpbfT_gZ{|$oI{wokJ%0Kg zOWwmWim&qeWt7fu;28r?ZIA{PKZ$*%YVEfNTP($pt7@&}*Hp&w zc0n7rh+mJAOme*xUvZQTAFA<(9^W5w9K)XvZjOov;p(#O}%b0Fr z&IY#gfhh6kaV=Iee?Ruaw_KNxSbi?cs1gt5nksr0+pOZxu(fm8{?XjuzGj^!+k7jR zMYb8-)077cjE;ER)SmCE75tvxzCU!u@$>x}{Ozmasx|jv`&BM~?^2$e%60Ll`t|4J z4e_eiiwr^jG<_Vm-}?Koif?a~pQH3Idz%l&~;UH`<<=iRu<<+ns}l!pJ#|89ME>?NgH`O|N+>ZLojlk9Ol zOufR5lW*O)-+sS-Rc>ykZQnPPq<_Bh$5q~m+@@;oQufn|VDOwN1yis$4_aWZ;Zpc9?`vQ+#5o&mbb``_~Y`c+=4qbWA<9OCDY&4Et%+gq+Q z`1yW4ettGitH7~5XDS&=HMJkQ%C%!YX^>)jZK@Tv*S|gI&)dHbuVU-CMAch%JYQ`; z8*IzNmS8%*R zRwAr~OeN%dAYKg})rj{(ycdTJvN!VdMxNf_^@eO8gnba!BCO@G63zA zoe&>@d;^eg0MZ74KM-Fj9tisfi%R?rz{{%*atLIHKxPQyckeoT z|MnWi@tl0I1-sOev7CQ<2Vdj~*R^A#u zA8(^A%DW8uRjvcOUC%PNvWB(dPL%Q>d1ALovJ(75z&W`52*`{rI2N>^l63YhpuF@1?^NVE6Y}3zo+nqyMcr-$ zJ*Dh6&{?Gq%4g)|xP!k+PA-1}GPfq40}Vx=Lu$9eP4X44-748HzEQlz@tIuW9I>I| z2>F(nf+wIIzUR3L_JoX8a<51fbXi$}Q6?9~ikVg#RC+&S0efH(dw^2$*1bH}mQ3T~ zMAm!?YbO32o(`c_c%HRYLk2xlCL{kb&JfBQr$DAm*K1i>zDbr;8o$XW@ZR5gnJF(d z`yp4IIS`&1We!7ptT~#?dYya4yG(m?Ykth}hd~8OpIkoQB;PJFzheILEb}Ax$v>Fx z$$F@bt~K|R@7lMRf3V~q+&_Qh_>UZSj1#-vX@1TvxLzI_dmOg?tMWB)ro}dy0ZIKl z0Bv}a2hWb5DJDz0A3d4tRRn%eRDx3980efQiy$N9p7PCtLjq;SPo;ay8FE_b+(5N4 z)maeeXVAUZ-Ym0{ZC)iu#@C_eTvKp*V3i!A<7Xp2wqQ+Q0n5~}{3@%b?;xJtf=r@6@<3HqO6PRt~kICF|jvcJ?M`zuYdzsfuX zw6|FbZFMX^faQm<{0NRWa(o=;+QaMy$-T{OFxhK7c&1+=Kq8FYnXon^KSv)5Vx9C$2&N6Eth^j+x#%wypC;tg6(n2nBw8UJm;wJ6 z1(tx822KX846FpL3S0y|HNm-IQ(PNti&W#^#X2(FAG;Hx2{A3dKiHjp;h3 z>&023q2O`0XEWk^6bMNcN_m!;QBcM4YQ!@Iqd`wDn8lpg@&d8MY2kP))046HIx^hG z@zqS%Gu^~g7_5_N71L^_jZ9}TZ81ngE5}zeUC(qgQ)!ZhYNn%^HZh&Ww1sIa)74DZ zGu_No1}N_=rmaldn675Jj_G=)o0*CrTg$YHX*JW)OlL7|W!lDcHPdxW*E8M3bTd;K zV#}G1W;%;$E7R3X*E8MBREAle>1d|2n6@%q&2&A}%}hmv{3aumtBT{*93RcJiRmn+ zvm@6)riJ6JOjk2q&vY|W5hXp6X%*9Irj1NTGi_ozi)ky<)lAnhUC(qA)6GnU#X6Z* zF|B4gn&~X2A2BuYWc`uhMy6w#HZh&ew1sIa)74DZFiTE(=QX&cjZ zOlKuXrj_Yxrt6t*W-5v(wTfvY)6qvVvH*tJ3;zwZ1$QG8JC6>mkLC=ZL0)4rl74)Nm)u2BY zG?kM~3)42Ho0-ZA;#V=PX4=SfG}9)go0y79l5AtTj_D?*q8n>qTHWm|u{z$!@zIE{ zjW=<87UECGTR7f|_}lR|j;}`itN1#OuSdM0U^D0*1+qKMpVgq5g2wKoe>CDJ7c_Bv z7UIHb;dm?J#ZDW?S0kQw)`O06HiJ%aWRJ7N;Z9W#($L6s9n(!rMHO4lw2|pLrkj|G zYEEU^$W-)X4%0@aO-x&uwlQ7DbQ4q2i{+U%GHqho!nBR)I;NYLiry^Gw2^634RKnS zwlQ7Dw5bpCnTo!gi)ka%mK1T?n66{GiD^|o;x{sFV!DZ`sAUaI8=1DHiL;LBCZ?i} zI4w-un66{GiD_d!r8Y5bVcMqXAlAcllcIx(BZd&IV%oyAjcMb~tcPhE({)TYF>Tp} zQrnoWW4ei{7)ty`rcF#m1M6qn$dtZnQzVzlYvjH1G5Lk;ZR~C|8OInG8f%TGjc*LY z>}?J)Cz@xN7nu*6pO`h%Y82?4_AKqHV9>EqdoT()EYew{) zB1d!+g?Jyg2)p89(F@-os=>F0QrIu|!`VPRb~Zz>YaR-zVUQY*lY&ur3wJam$6yCN z0k4lvg!EKM?~k`$55VqchS&-Fn*sPH(Lm9JcTo?;UT8M7%*A)_=0Veu(6kVmj>hij z7+eu&@jhoW-rHP^cQ8+Y#wF0WOzbO`i%DXIn2hrfd|{>J$vh!Ol|2i3v-LV?ZQ?D^ zf#wIGpT~*zD*6cYs!EEFD*F`l5S!u^1w;=j{tonw3X+*#{4=Oy5&g81XkY7h(EA-6 zI%y4QhjJar8fus>OtNN<|HsOuj`DHNGfA7WVJ^pSW=X|Ssn4-|54Kj-OVvfmD6053 zTOruvPyMJQ2F?k^#h~w$mV^Fk_X1U(QIdVFe&F~$rud4Z^j{Jo`yVUc36fjNh^{Fi zPLMsh8`sodmtUAayR5;}+}^5O>o^X1SfwTkN$17fBC7Pu%81j8%RP^EsuFLB62C9| zs#~1wi6%#b_9~+Ic?A=^a#hRv>*DwA_O3D@m2hZx2ZtI88PAF9;gIc$Pe_@nt`ZYXjdZu)&Ff z8a%pjhZX-B7~{AU5OGig{K5Y)gJPk>fnyi1JjV#I08ON`|t;wg-K$)n%Eh^_!9 zjnQx5U!>^)T8|mPz*ot8L1rgVoZ%w3#8|IEd@TO`HGE?S)WG-3`XRn2sDTlkMtm<& z18*tUgYJXe21fZn@b?2XFxm$rJ{i;y2V$-;FpCTYor(Fv5P!vNA;lq}24KP{Ski%vz&qVt>_DEkANEZ8rngi>oDUP zIA1&j^q;U!ipN0>oN3KQ{7Fy)Z!sMP`jj{voTotzyj?R7^mWXNhWM8_3iK`fJJ^PJ z8*`%+?|>TO1I&+7Yyvg#X34RLZvi#Lr{XxoKLf@20On39z5q4Em$;6Ucw=KJ;$LGf z#nTv|2Hu8Pf%p%g2EOdkiug~U2EIdeGUC638e*$B6?B{U8>oucmmYGns*s!vHUwYC7`%NEU!Sk6x6_Z z-c^W~gQ8E$)rePu;#@^ugLrpPL-df>B3=bbXEpTIx}Knh=qqnTJOzqgDsM)-4ivpq z-immCP(uusw}TFmcY-#^yFrJ^dyqOD)W8Y)eTa_-HN*t@0OGrY8aO$A2y~)+1avR? z80da-JyIuu8aS(a9Pz(^8aOX{67d9Iq;i6@wA700rW8W66jp{ z3iyYE8e+bD4e=vE4V*0f3-O~s4Sc)pP0)*Rl55~=i|>G5CEo*WlOI54H7I(u+>H3O zpy<`|BhZ`VC*a%+ie4>01-(sv4tl%%5_B!z+A+jE@*Bw93u=h_`5Wj{@;{*ek^cj_O>P54hmcZ8P#Y)2eK9xm!MGlR^?bH?SL`g0 zlCAOw`MVruG#Y;~W*8?Lrx+`ZHO4K*L&iqq1LIR;e{-fe+gxg%ZT{W-%KX7J0+GP+ zf!hMF2et-g1P==x89FX>MJN=m4A+GRhXdFK=*LR2AD|z7c`cx#Os9r7!mReZgTp`J z8H@J3so|&aWJpI|DW2I87}+r~9e*=Wmjea9eT6^z6^J+S#E-x{NFnWwF6OcZYyM~* z?x(}Eba<`~Z`I+GI($io`$(mCmJa9XaG4G-)8VZ;d_aef>+mTZexSpzb@+=8!-mqI z)L}Or?ykc_baF{wKzM{j;9L7bSN%`=N8XXqvFsZ|8 z4r$+}>>8%S@jBc`hck3I>;G%->tf?dvh%8c$nMrpi)=}wnJlGgt++dshT>2&)T~C! z(GG{Cr1pxWEVh2u;)uHJz9f6q-IsH3w|8F53!T)JLgv4+uhV`f&jq=h^SjXr%qL!I_K1>Q+0nj zjDs-#FpU2}7=JsAKMLdj7REmdC# ze20pQS5_Gecftcj$xUUkpT^em3;$iSG`7+k6)%+kcY! z?Zl^vV`#64wvM5#BHBHM_KIk$h_;Go>loS^GcRO5NWGAG2k{Sa{RHWs;`&3>r`^K} zok(E~N+TY^HH<5R3+KFv9IgYn4&pk5>o6{yO(%}v!Z%D4qqqvVcz5*}uH(2~z;y!G zi@09G_4jan0oNEVeA_2+3K#E|7IB?M`ir>E;2OvEC0t*IZMAnvUxAH&1=e>0@dV_Ek64!ZLQ@CEkHI3^6uGewBfolfWMO<&<`UDb*Y|}gkmQ)zd9T@WYE69KxbkS(X}D~QgHakw&3dhA z2c;D2kkRmk&%u)7<#xU9Y}DO{7fflf*>1SL&CPrDx?3UXQucn^sn=S&^Il`e@m)WL z-|{4PqZYIXZMNQcJ?#JUIyYC_&C0{qP3e~FR9Bky-G!QT=J>mSipW6V8=uz%i=`D{ zQE*sVp34%H5d}?N{2VMTCL%s(_}sQo7Pj@3&%r`lD8BNRnO*X#?Yeu#T$?wmyFtrs zOqEu!AAaoA+wS_hxxKUF`g8T2ZO7d3p4g;l>XKWnIp$6cDx}GV03d{hV;Vul^XoNy zVD?JI%t3Coig^N!t2Ik4$f{yHiv$@=U2~hRkD|GtQmZX^VWNt}mfKn{RZXDL4bQ2X zxoXucc}*|aaVl=rTy>j_HZ>yt{I*+p1Q09P^m-Mu#0vl=#)8*|axJ*^TBFtqG5cZF zJ{;Ct#fQJ^?k~4JTd5ZiFRfM0Y^i$X(fazkPUR6wuGZW-U?D++1%3SwBEP4-itWwe|zAwl`YODQWHQS3zd}K9n>7p?7Q5{lK8+(ID~-XTz-zg6}~#&ndd$ zKHjg!V#BHJ)6iVKw$&VLA0i7Nv$ojt0ZHhP2Wyd`&nug2R<=EV|2n}SIJRUBbYFJ1 z_N&oup@V%2!bNbOl6j|I_u8#}O0L#Dr!`2G@OEW$6J}tr@VZ;u+TI6VYF4oZ58{{I zr~5$X>MhrAIxTnq;!i0V%)#t7X}c;OqWNvdcPi-Qn(wuD z?s|Rj>#drk7JP3<5}~Li9dbv~Yt)tu5c(f+a9ANRWu6I5FmZx-zCz?aI)Q z+p+9z*uzb*Dh8sjjcMsmRon8 zN-9>qBCW;%mR@LSwOxrekZ`A!mGj=tuFv%@>ZE_ODLRB*WP}k_#@4DCD+sM8$pmQ| zHSWKnYEE}pR9aDTQF~2w@u+4BA{tDeW}v~4k)|Khg@Y0|yvLXo?VTMTJKw9dCalZ{ zuHpRWV*PYw)2<&t#dZ`*V&_mu=~O60mfUrG!C|DfUcXQ#zFd*tjiIT%1jTYw8J| zPqklea|_AEW;NjM9o;#8OOrL@ZG6+Lz-y3=xb0dq5E4zfX2i7WX6~Brx{tJFc(T$Z zjMyXduID{63vLC=bRBlWXH@pU8f?Jp<_1h8V@O&|!nsiV zdKXu`G_6lx*wiIt%i;t}iKgc2_3j37s)`KfC;09<4FfSTVzm->vQkSD(wz%y4{c#V zD83cH3R^n>z73PwTOixDZf#0inptIAH3qtMhUu*}Xm&R+B^qF33q}T04gI zX)5zINr?%;;?)bqnp&zg%`bTf7N1t?PD7@@m}^bZWNXTj#Wl3nY%4I_%7fG4F^Lh^ zG1_fg7R+@$0OLeSSwH%XgD9FkF~TqZ>Cq9_krI6$YM5IEwXRquZ2Gsvby;b*RyJ=r z%`JDZj0Ze}&C5DH%1vlAM#RNSLhFJma((f)TJUnAN6S+cB$;5R|Kj}GlqG(ZeeoW@8W}R@3w1o*4}7u;?Mv?ZE+hTmJ3<01wRB1y&Uc#73VdwB~cL| z*sTc>K!o@fzG0_fa{UQ?Dh!Yik&{z1u z@9nI*{^J^sh5L)uk#PNPxjJM}0B+fW$kh%g8?MNK@Smy|2>Ug)x&wp1((Ecc<~222 zJV>q4UDg9-@qhs_>s`MorFnQ?gK-QSeC1Sf;0rS>*X~0K*~5jzq6_*mVxkEM{RW+Z{2Da10&_jk911 zgtzOCzxY%<7nq)|geV#86PhgwqCU0Yw4AwSGqme5EPK=);Ly|V*HA3RPo<*1pq;|X zTQT^Wq|AE9Or6<+Q`=|66n%9EOTSa^N*dyz``#7Be&W%ZI;leO+l)>z0)qe^5CV!~ zwO!#o47&~q%pUuQY`d9ovF^Q-fP)1ZgD#S*3s5-T@Q_Fkr|pqZ=tR!7;3vSWBZj~$ zPRqdJV0{$|+LZZx+mF&7&X%w?&=(SGF1tVzz^-cw8yU<#3ysn^ zr2}cE$F7*J(WI3zn-pO3k?>Fyb7BYK5_U?^k{Ag}6VEO+klF;ylT-jKAJ0L-kq2Dc zGWa!wCTg}(X66-E1Wo`9+pdE&n2Fz)t(hv)4sf-l4XMZent(RYtF~7~3ZKL5{Ba2d znknMp07shjq*4(?ZK9$NC<$^gtRfx}YXgUa*#JaIXyPG}CURTSaSf!fgtbUa9XTwr zNWsPkR8zzWK=22Gt$h)L@Cy3I-VNyrYGF%?wh|}o;FY;#(CcJ!$aLm~>6wsmhaDNm zHfsC$azhc%Qc?iy!@Sbyjsr`H^i#uVchNVQ*~L5jLZ|DcJh;Ta#1|Cf?U4R>YbNzYw1P(mQ}+>1;(8A)UIr%B>M|$` z$9OP;nStPO*9a+aCd0NJl3HkXDF!GHtdoekd3Pw&L;9Tle zv}G|K8gtn8e;QPoqvQeWUWq8oO+jDyXOIe8ezlCp3Kwt{%^gwUnrPCzNWFqb|BB{@ zz@h5+Aq<^L=>4_*>)n8?sD;!MYFbpc232=NXAORqgOkFA7MO$7h^pw5d6~7SsdbcW z;*Zm^g-0nvT2F8?QL6*Mz8FFwo#QQOxgSbg_R@^EafZ+edSI_EIAytZAMKInkZ$g6 zw9h}2dkv3*@{hmu@|ti`qr0$yIw#IvS zU{?D+1F100{+RyzVH)4gJ@_C@KY*^%3c%aJ2zsP(LXF-Q_}l|OuF`wd3q7$Z(xwgQ z#ijusXgi#zDmC(n)YIZnYP1MX(T;gLvLtE|*}7UiT2rQJz0|7F{?VS&s)btdF&M0iMiO{if-rZUGYOk?mP)`@CLz>zgBe`L8JNi=d;|veOQ32)}e@ z_SG9L<1u3L%u;5qJ-{Q=UxW5=)Vor4C6wS<(R}hyF)a74z&@NqowFfl&*4=HlX?dJ z-be2_a=Pll7kD*v(}$d>;98Xj*GgNh!Q@VQn9z zZ;BAe*a}it(8sC}bQZNp)EZjgh2O2lVsai!)f~cKF^S{x+%#Zsq4z|Clm_VGa@dDm zbFUb_Ey6K838~c7T1X>Hl|`HemO@?8+d^5yCXSA5N_@?-JL<(^QMtbs(y(7EEHy7b z_#BGR{$9$?KTFUi<{;gd78s_^1mzo_8640nU}2o`MOY{m7>+n0vZ`oCyaleFoLe)9 zdt0CwRD4k@b@bg&!^NTk5pOqCy6rvT6feARB^>1eBpsCi^@`p z>ov6X4A^IlSx&Y%d;06=ucNfW83@=A_I@iv1a0Ir%E$Ue;;Ne(egG+1dL))3E-=$>9m% z$)JX*tqwq-m51olOL2L=8fxGq;4Ty!gUS#dE{@Sqy)TWV=mG>R4^Ur9c@7mYUZ1;>vb$K zJZ;#)dsylMv>|~fkijmzB6D#LZ^6!EAzZ|JtJmJn!Tq(h?p`aACAMZBivnr4lGJ z8HSp>19ubG&>ev@1U#p)V%!4;uAzIN+GH4N?grqvhHeO)A>cWU6=NP4xQ6Dz8IxhC zxdp&+4J`cWU6=Mk)xQ3R%Ka*jI_%J^2|^BB6pjZkvPOSI_QR*rm=f9|5$hopmWKbh^XgQ+d3QuzggQ&zt#pd)G6vKk2LgflvG4m$it z9$`L32OB)(BAoTj-T%E2#e4bO(Yz8L4d+pGOxvRyXX1EqU5M#SYzD@y&<)GEGjsQis&ek@x|CXbqt zqj>QyaWY?UGRWsgJO43bQe$W%i9Ft~Lvb-t==`UAb|jHFWeT1DkUo$o+#WJOMuSPB zB7=5^fS)I+Ndl5%V>wU|jAAMNZV5d0eI_oNHo0_0E}l*5NXhHFy6r##e1LDv@ z*djU=QozKu?D0b9UnC3TNsedi#llD;nbZcP;FL)YWq|iEjn^>q8IvYQ$5NR@3L{Tt z(;4s*96OmmnHoV=TayH2QwI|H9C<}(KAXXiLHz{S0x2?Lj%40Q4(HK*KCi4rgJA8+ zu}m?YU~g&gEO`L(2%Be>SyYEgFoJ^29>|~!%^fQo)8-j54@$xM6x$JjjR8|p_okso zXhLETBr&S&P3J;N_hwinl?5KlXArY|W|%S*bacHp4bCLSj%3mzlWFb|@Y>jEF2kbSzg)Qc9zHLr~*<{$w6B0ggd}oqIE26d~V$ z_U0+^&i8YgLrN=*VW5};P_UDy3}l-c&ZJJJ^4TLGRSDG)zx zzL892LB>Ihpvvy^g~=g_(HYeclUm4`ri^!(?EIO8eQwe`8;dcnW$KWCJ zdoO0mp^x*05#jO2P%cy08)atia2`4G;l#|TjC7+ZLl$zbe-&S#KHmUbkUNs6KuCOMW*SUCC8NI03g3_<~B#;L^6fh5L$ zP%sOV{CjaEnK~8XF(xKv(W%7nfh5Z(GGhgN*)av}1>dsSWH!s0rRjV&35k-)m_tPa zD*{=9q1oh#zF8??%xVY_pG{0)`nMC=BQT@S*g&3agQRHgMzSww4hb7Ozmr#$)ld*I z^p6h+r^tmr7b7tO9)wcOQ3BtmMTS^T;lnlfRD=;l{``BPyC##8A0sBn|P0)x)4N{Gad3Nr{mTA_$PP3_GV@W1mTQL&VS zFmuq(6s_JTDKz)uAbUhY#Fq0{C{s0yX|6qfY zS89f~q3v+0juGziINU_lF=-^w4#$h?H$lG&8ZjC|Kbj*AxG02KCS+!{_!WY{4_ z0M8B?==8~>BME8*?JcL=-f0r`FF#nj^U}yDF0=HH>)&ri-yp4UZm550CEg+pm-$Jqwj&VH}7f$>C&rxUe^Zpz{$C zi!4Rei7=ieaGb@T0m5Zo+5yHflwk1)dzvB2_YX)H1qVqrpRmrU;gk9F@JSeODa0ZS z%pb7we`nhe=jdLV0SZRR6>=|*6#tY+gny?%v;C8UR5jM>b z3Qda*LqHHTUz{emf5^ZB3fegAExrRio()|a@vq=g(PR}S;h``BZy3*FmarFuSUHo@ zbmt>!rYhmAI$~h{tQP)}MnBf*F9b>Zolww^1hk-;U)AVOHTpA+{#>Kq62vvh>>ZPg zhW8|WU9tW^qkpW??;OD3L(WFY8L9A8TO!*Mg-a4X(^}t=OkKi<5^9YdE&icKpKA0| zjXslTkL*bliV|kEyU2wKPtnfW z9D0J1j4KXYVtCe{4Vgrt3P~Y^{~~?tO|yc`3K5N@Py&py2vNn(*&=$Dg;yhMW}f?n zlb{6FUFhk2Px{gbD@z(HkT@@xN@+MU;c$O&P#Qpkdox)XA7VJISZDqM|Ir3hEXa=( zCaI4knbF<^dn;%-tFX>@@*{9sSvDdIq1J(3W)EW70K8B}|A!Q(P{vB|{lauYY81-d zD$)i<+y#J0Rf`$yOQsXjQnzr_w$_ClQu;K1L_6*l9@e~&CnGwU&!=RLcK#LoLKVX$ zjV443#)JzLjW{BONzUIa18y3yex)a96ehYxVS+{h!CpBvVe+`L-NG5-jsTPd0_XVz z=eZykvtbJp#F@3ZSt%SRdgn6&MJH_OG2lYr=&bWS=|l#RO&Bg62Hq3CN>on1a2Ky9 z;hn|qn-}G6-+K}yfXDR^CoZU9A7#f0Cs#^*1j`h<@01n)-4BYz*QYPwl=m!tDPg*D zY5J1;M)mwfx3YPD=1u3V^KZTJX7&6=r8<4#t&K|;FKxbsH8o)}7pA89XUq~loHez) zSnj^CHyOUL_4ebLsW+!CfX@7}ZXsWG#EWWtT>Thp6}u%x!9F4b%cqHuDwl3TyV-!` z)5|O6MSK;$3&@q0Zm!%a&n=hn`v_fV=I-3B<K+XPk2SAr+WCfZx1YdWxEF!zMRuD z3Vp*pmoRC0%Zs{hF24Pral?VX3uEwoH+&=N%lI-OrpK+-h1Ejq=Fso`{y&-jM;rHl z_l2#0juJfbd3o(N9_0LA;HN4*G;{Dw&aB8Qz!LI(F z|5tuR?1YS?$#il5Aw7)Y;j5?fp1)A9FX1Il{fdn1%6opS`#-*fHt6sEg8bvxDfvA$ z)9EFMN^5Y}YY$vW{19Qi1M)+?mHG|Y0+-+M&xG4AC^xob&?rkmO{@jXS{_FIA z`8)lR9DCqDjqzlV{7WNLlN|yOE#OL^Ro;WSit|~XxtDOZDfcB%Hf~s}j8dL>1}Nt# zvflMU0sj57^fNS?0CoC21@G4kwscQ$@Jm7A-wf{ifCufS+J-a(4S zb^&)~r@NQIBLatkPwwcQDBkJ8JFs1f`umu|$usZ9@ZWWOpEQBfZhfS>E+gK-ct|Pl z$>OoYePBiW9#9c~uY-;Y2J0v85R+d~J1QBTbn{Hw$9-Mg0}21VEA*~}eek{r>9w+9 zPC5B`biXeAy@@tFjHWGj1)>q}&(|5@Yj2%??)LNclGGt3y!XI|pX%TaA1dyZN`E~& a)?bLYn85cHF|oh$3qj5QC*uDy2mU8%Su!sG literal 69120 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 D{@1ou diff --git a/src/lib/dnx451/AsciiDoc.pdb b/src/lib/dnx451/AsciiDoc.pdb index 4b9a274ab767f914ffa6857eabfcb16eaac58cda..eea737332196bb64efd19533618d6932fcde5ae1 100644 GIT binary patch literal 241152 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ⅇ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 + /// Visits the "raw" asciidoc generated using Roslyn and adds attribute entries, section titles + /// public class AddAttributeEntriesVisitor : NoopVisitor { - private readonly FileInfo _destination; - private bool _topLevel = true; private static readonly Dictionary Ids = new Dictionary(); + + private readonly FileInfo _destination; private Document _newDocument; + private bool _topLevel = true; public AddAttributeEntriesVisitor(FileInfo destination) { @@ -29,7 +33,16 @@ public Document Convert(Document document) public override void Visit(Document document) { - _newDocument = new Document(); + _newDocument = new Document + { + Title = document.Title, + DocType = document.DocType + }; + + foreach (var authorInfo in document.Authors) + { + _newDocument.Authors.Add(authorInfo); + } foreach (var attributeEntry in document.Attributes) { @@ -78,7 +91,7 @@ public override void Visit(IList elements) continue; } - // check that the previous element is a SectionTitle and if not, add one + // if there is a section title since the last source block, don't add one var lastSourceBlock = _newDocument.Elements.LastOrDefault(e => e is Source); var lastSectionTitle = _newDocument.Elements.OfType().LastOrDefault(e => e.Level == 3); if (lastSourceBlock != null && lastSectionTitle != null) @@ -92,9 +105,7 @@ public override void Visit(IList elements) } } - var method = source.Attributes.OfType() - .FirstOrDefault(a => a.Name == "method-name"); - + var method = source.Attributes.OfType().FirstOrDefault(a => a.Name == "method"); if (method == null) { _newDocument.Elements.Add(element); @@ -144,7 +155,7 @@ public override void Visit(SectionTitle sectionTitle) return; } - // Generate an anchor for all section titles + // Generate an anchor for all Level 2 section titles if (!sectionTitle.Attributes.HasAnchor) { var builder = new StringBuilder(); @@ -157,18 +168,15 @@ public override void Visit(SectionTitle sectionTitle) sectionTitle.Attributes.Add(new Anchor(title)); } - // check for duplicate ids + // Check for duplicate ids across documents var key = sectionTitle.Attributes.Anchor.Id; string existingFile; if (Ids.TryGetValue(key, out existingFile)) { throw new Exception($"duplicate id {key} in {_destination.FullName}. Id already exists in {existingFile}"); } - else - { - Ids.Add(key, _destination.FullName); - } + Ids.Add(key, _destination.FullName); base.Visit(sectionTitle); } } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs index b629758114f..c94d317fb4d 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CodeBlock.cs @@ -7,12 +7,12 @@ namespace Nest.Litterateur.Documentation.Blocks { public class CodeBlock : IDocumentationBlock { - public CodeBlock(string lineOfCode, int lineNumber, Language language, string propertyName) + public CodeBlock(string lineOfCode, int lineNumber, Language language, string propertyOrMethodName) { Value = ExtractCallOutsFromText(lineOfCode); LineNumber = lineNumber; Language = language; - PropertyName = propertyName?.ToLowerInvariant(); + PropertyName = propertyOrMethodName?.ToLowerInvariant(); } public List CallOuts { get; } = new List(); @@ -23,7 +23,7 @@ public CodeBlock(string lineOfCode, int lineNumber, Language language, string pr public string PropertyName { get; set; } - public string Value { get; private set; } + public string Value { get; } private string ExtractCallOutsFromText(string lineOfCode) { diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CombinedBlock.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CombinedBlock.cs index a40927f0fc2..ac880574611 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CombinedBlock.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Blocks/CombinedBlock.cs @@ -4,7 +4,7 @@ namespace Nest.Litterateur.Documentation.Blocks { /// /// Used to keep a line of code (could be multiple e.g fluent syntax) and its annotations in one logical unit. - /// So they do not suffer from reoordering based on line number when writing out the documentation + /// So they do not suffer from reordering based on line number when writing out the documentation /// public class CombinedBlock : IDocumentationBlock { diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index 561865986c8..628d778f29d 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -95,7 +95,7 @@ private void RenderBlocksToDocumentation( if (!lastBlockWasCodeBlock) { - builder.AppendLine($"[source,{codeBlock.Language.ToString().ToLowerInvariant()},method-name=\"{codeBlock.PropertyName ?? "unknown"}\"]"); + builder.AppendLine($"[source,{codeBlock.Language.ToString().ToLowerInvariant()},method=\"{codeBlock.PropertyName ?? "unknown"}\"]"); builder.AppendLine("----"); } else diff --git a/src/CodeGeneration/Nest.Litterateur/LitUp.cs b/src/CodeGeneration/Nest.Litterateur/LitUp.cs index 98e5e514f86..c1029e5429d 100644 --- a/src/CodeGeneration/Nest.Litterateur/LitUp.cs +++ b/src/CodeGeneration/Nest.Litterateur/LitUp.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using Nest.Litterateur.Documentation.Files; @@ -16,8 +17,8 @@ public static class LitUp private static readonly Dictionary Sections = new Dictionary(); - public static IEnumerable InputFiles(string extension) => - from f in Directory.GetFiles(Program.InputDirPath, $"*.{extension}", SearchOption.AllDirectories) + public static IEnumerable InputFiles(string path) => + from f in Directory.GetFiles(Program.InputDirPath, $"{path}", SearchOption.AllDirectories) let dir = new DirectoryInfo(f) where dir?.Parent != null && !SkipFolders.Contains(dir.Parent.Name) select DocumentationFile.Load(new FileInfo(f), Sections); @@ -26,11 +27,12 @@ public static IEnumerable> Input { get { - yield return InputFiles("doc.cs"); - yield return InputFiles("asciidoc"); - yield return InputFiles("png"); - yield return InputFiles("gif"); - yield return InputFiles("jpg"); + yield return InputFiles("*.doc.cs"); + yield return InputFiles("*UsageTests.cs"); + yield return InputFiles("*.asciidoc"); + yield return InputFiles("*.png"); + yield return InputFiles("*.gif"); + yield return InputFiles("*.jpg"); } } @@ -66,7 +68,12 @@ public static void Go(string[] args) { indexDoc.Accept(visitor); } + + if (Debugger.IsAttached) + Console.ReadKey(); #endif + + } } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs index 06da7ac8381..16c067dd0b5 100644 --- a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; @@ -101,6 +102,7 @@ public static bool TryGetJsonForAnonymousType(this string anonymousTypeString, o $@" using System; using System.Collections.Generic; + using System.ComponentModel; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -124,6 +126,7 @@ public string Write() MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(JsonConvert).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(ITypedList).GetTypeInfo().Assembly.Location), }; var compilation = @@ -143,11 +146,12 @@ public string Write() diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); - var builder = new StringBuilder(); + var builder = new StringBuilder($"Unable to serialize: {anonymousTypeString}"); foreach (var diagnostic in failures) { builder.AppendLine($"{diagnostic.Id}: {diagnostic.GetMessage()}"); } + builder.AppendLine(new string('-', 30)); Console.Error.WriteLine(builder.ToString()); return false; diff --git a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs similarity index 97% rename from src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs index b36b58d7f70..b90e9009608 100644 --- a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.doc.cs +++ b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs @@ -38,7 +38,6 @@ public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : b } }; - /** Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Children("name_of_child_agg", child => child @@ -49,7 +48,6 @@ public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : b ) ); - /** Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { diff --git a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs similarity index 97% rename from src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs index 29d492bc46a..4dde951763e 100644 --- a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.doc.cs +++ b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs @@ -12,9 +12,9 @@ namespace Tests.Aggregations.Bucket.Filters /** == Filters Aggregation * Defines a multi bucket aggregations where each bucket is associated with a filter. * Each bucket will collect all documents that match its associated filter. For documents - * that do not match any filter, these will be collected in the other bucket. + * that do not match any filter, these will be collected in the _other bucket_. * - * Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-filters-aggregation.html[on this subject here] + * Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. */ /** == Named filters **/ @@ -191,6 +191,7 @@ protected override void ExpectResponse(ISearchResponse response) singleBucket.DocCount.Should().BeGreaterThan(0); } + /** The last bucket is the _other bucket_ */ results.Last().DocCount.Should().Be(0); } } diff --git a/src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/GeoDistance/GeoDistanceAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Global/GlobalAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Histogram/HistogramAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/IpRange/IpRangeAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Missing/MissingAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Nested/NestedAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Range/RangeAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/ReverseNested/ReverseNestedAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Sampler/SamplerAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/SignificantTerms/SignificantTermsAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Bucket/Terms/TermsAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Average/AverageAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Cardinality/CardinalityAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/ExtendedStats/ExtendedStatsAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/GeoBounds/GeoBoundsAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Max/MaxAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Min/MinAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/PercentileRanks/PercentileRanksAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Percentiles/PercentilesAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/ScriptedMetric/ScriptedMetricAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Stats/StatsAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/Sum/SumAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/TopHits/TopHitsAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Metric/ValueCount/ValueCountAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/AverageBucket/AverageBucketAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/BucketScript/BucketScriptAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/BucketSelector/BucketSelectorAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/CumulativeSum/CumulativeSumAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/Derivative/DerivativeAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MaxBucket/MaxBucketAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MinBucket/MinBucketAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageEwmaAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltLinearAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageHoltWintersAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageLinearAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/SerialDifferencing/SerialDifferencingAggregationUsageTests.cs diff --git a/src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.doc.cs b/src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.cs similarity index 100% rename from src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.doc.cs rename to src/Tests/Aggregations/Pipeline/SumBucket/SumBucketAggregationUsageTests.cs diff --git a/src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs b/src/Tests/Document/Multiple/Bulk/BulkApiTests.cs similarity index 100% rename from src/Tests/Document/Multiple/Bulk/BulkApiTests.doc.cs rename to src/Tests/Document/Multiple/Bulk/BulkApiTests.cs diff --git a/src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.doc.cs b/src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.cs similarity index 100% rename from src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.doc.cs rename to src/Tests/QueryDsl/Compound/And/AndQueryUsageTests.cs From 685138d20090969d8a1f483dac8c8b2d1f28fc4f Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Wed, 16 Mar 2016 13:51:07 +1100 Subject: [PATCH 10/18] Add asciidocs in the root to group categories Move example json to below the initializer example Ensure level 2 Section titles have an anchor generated --- docs/asciidoc/aggregations-usage.asciidoc | 92 ++++ docs/asciidoc/aggregations.asciidoc | 13 + .../children-aggregation-mapping.asciidoc | 1 + .../children-aggregation-usage.asciidoc | 53 +- .../date-histogram-aggregation-usage.asciidoc | 43 +- .../date-range-aggregation-usage.asciidoc | 36 +- .../filter/filter-aggregation-usage.asciidoc | 41 +- .../filters-aggregation-usage.asciidoc | 226 +++++---- .../geo-distance-aggregation-usage.asciidoc | 60 +-- .../geo-hash-grid-aggregation-usage.asciidoc | 34 +- .../global/global-aggregation-usage.asciidoc | 38 +- .../histogram-aggregation-usage.asciidoc | 38 +- .../ip-range-aggregation-usage.asciidoc | 44 +- .../missing-aggregation-usage.asciidoc | 28 +- .../nested/nested-aggregation-usage.asciidoc | 42 +- .../range/range-aggregation-usage.asciidoc | 52 +- .../reverse-nested-aggregation-usage.asciidoc | 66 +-- .../sampler-aggregation-usage.asciidoc | 44 +- ...gnificant-terms-aggregation-usage.asciidoc | 38 +- .../terms/terms-aggregation-usage.asciidoc | 68 +-- .../average-aggregation-usage.asciidoc | 42 +- .../cardinality-aggregation-usage.asciidoc | 30 +- .../extended-stats-aggregation-usage.asciidoc | 28 +- .../geo-bounds-aggregation-usage.asciidoc | 30 +- .../metric/max/max-aggregation-usage.asciidoc | 28 +- .../metric/min/min-aggregation-usage.asciidoc | 28 +- ...ercentile-ranks-aggregation-usage.asciidoc | 50 +- .../percentiles-aggregation-usage.asciidoc | 52 +- ...scripted-metric-aggregation-usage.asciidoc | 50 +- .../stats/stats-aggregation-usage.asciidoc | 28 +- .../metric/sum/sum-aggregation-usage.asciidoc | 28 +- .../top-hits-aggregation-usage.asciidoc | 106 ++-- .../value-count-aggregation-usage.asciidoc | 28 +- .../average-bucket-aggregation-usage.asciidoc | 58 +-- .../bucket-script-aggregation-usage.asciidoc | 100 ++-- ...bucket-selector-aggregation-usage.asciidoc | 66 +-- .../cumulative-sum-aggregation-usage.asciidoc | 56 +-- .../derivative-aggregation-usage.asciidoc | 56 +-- .../max-bucket-aggregation-usage.asciidoc | 56 +-- .../min-bucket-aggregation-usage.asciidoc | 56 +-- ...ng-average-ewma-aggregation-usage.asciidoc | 64 +-- ...age-holt-linear-aggregation-usage.asciidoc | 66 +-- ...ge-holt-winters-aggregation-usage.asciidoc | 76 +-- ...-average-linear-aggregation-usage.asciidoc | 62 +-- ...-average-simple-aggregation-usage.asciidoc | 64 +-- ...al-differencing-aggregation-usage.asciidoc | 58 +-- .../sum-bucket-aggregation-usage.asciidoc | 56 +-- .../writing-aggregations.asciidoc | 29 +- .../analyzers/analyzer-usage.asciidoc | 28 +- .../char-filters/char-filter-usage.asciidoc | 28 +- .../token-filters/token-filter-usage.asciidoc | 28 +- .../tokenizers/tokenizer-usage.asciidoc | 28 +- docs/asciidoc/client-concepts.asciidoc | 12 + .../connection-pooling.asciidoc | 1 + .../date-time-providers.asciidoc | 1 + .../keeping-track-of-nodes.asciidoc | 1 + .../request-pipelines.asciidoc | 1 + .../building-blocks/transports.asciidoc | 1 + .../exceptions/unexpected-exceptions.asciidoc | 1 + .../unrecoverable-exceptions.asciidoc | 1 + .../failover/falling-over.asciidoc | 1 + .../max-retries/respects-max-retry.asciidoc | 1 + .../pinging/first-usage.asciidoc | 1 + .../pinging/revival.asciidoc | 1 + .../disable-sniff-ping-per-request.asciidoc | 1 + .../request-timeouts-overrides.asciidoc | 2 + .../respects-allowed-status-code.asciidoc | 1 + .../respects-force-node.asciidoc | 1 + .../respects-max-retry-overrides.asciidoc | 1 + .../round-robin/round-robin.asciidoc | 1 + .../round-robin/skip-dead-nodes.asciidoc | 1 + .../sniffing/on-connection-failure.asciidoc | 1 + .../sniffing/on-stale-cluster-state.asciidoc | 1 + .../sniffing/on-startup.asciidoc | 1 + .../sniffing/role-detection.asciidoc | 1 + .../covariant-search-results.asciidoc | 1 + .../inference/document-paths.asciidoc | 1 + .../inference/field-inference.asciidoc | 7 +- .../inference/ids-inference.asciidoc | 1 + .../inference/indices-paths.asciidoc | 1 + .../inference/property-inference.asciidoc | 1 + .../inferrence/document-paths.asciidoc | 126 ----- .../inferrence/field-inference.asciidoc | 460 ------------------ .../inferrence/ids-inference.asciidoc | 135 ----- .../inferrence/indices-paths.asciidoc | 56 --- .../inferrence/property-inference.asciidoc | 37 -- .../high-level/mapping/auto-map.asciidoc | 8 +- .../low-level/connecting.asciidoc | 107 ++-- .../low-level/lifetimes.asciidoc | 1 + .../low-level/post-data.asciidoc | 7 +- .../naming-conventions.asciidoc | 1 + docs/asciidoc/common-options.asciidoc | 14 + .../date-math/date-math-expressions.asciidoc | 1 + .../distance-unit}/distance-units.asciidoc | 26 +- .../time-unit/time-units.asciidoc | 1 + docs/asciidoc/connection-pooling.asciidoc | 61 +++ .../document/multiple/bulk/bulk-api.asciidoc | 131 ----- docs/asciidoc/high-level.asciidoc | 26 + docs/asciidoc/index.asciidoc | 353 +------------- docs/asciidoc/low-level.asciidoc | 14 +- docs/asciidoc/query-dsl-usage.asciidoc | 2 + docs/asciidoc/query-dsl.asciidoc | 12 + .../query-dsl/bool-dsl/bool-dsl.asciidoc | 1 + .../search/request/explain-usage.asciidoc | 16 +- .../request/fielddata-fields-usage.asciidoc | 24 +- .../search/request/fields-usage.asciidoc | 22 +- .../request/from-and-size-usage.asciidoc | 18 +- .../request/highlighting-usage.asciidoc | 128 ++--- .../search/request/index-boost-usage.asciidoc | 22 +- .../search/request/min-score-usage.asciidoc | 30 +- .../search/request/post-filter-usage.asciidoc | 20 +- .../search/request/query-usage.asciidoc | 28 +- .../request/script-fields-usage.asciidoc | 44 +- .../search/request/sort-usage.asciidoc | 138 +++--- .../request/source-filtering-usage.asciidoc | 26 +- .../search/request/suggest-usage.asciidoc | 134 ++--- .../search/suggesters/suggest-api.asciidoc | 68 +-- .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 46 +- .../Files/ImageDocumentationFile.cs | 8 +- .../Files/RawDocumentationFile.cs | 40 ++ src/CodeGeneration/Nest.Litterateur/LitUp.cs | 36 +- .../Walkers/DocumentationFileWalker.cs | 22 +- .../Filters/FiltersAggregationUsageTests.cs | 9 +- .../HighLevel/Inference/FieldInference.doc.cs | 6 +- .../HighLevel/Mapping/AutoMap.doc.cs | 2 +- .../ClientConcepts/LowLevel/Connecting.doc.cs | 105 ++-- .../ClientConcepts/LowLevel/PostData.doc.cs | 6 +- .../DistanceUnit}/DistanceUnits.doc.cs | 28 +- src/Tests/aggregations-usage.asciidoc | 6 + src/Tests/aggregations.asciidoc | 13 + src/Tests/client-concepts.asciidoc | 12 + src/Tests/common-options.asciidoc | 14 + src/Tests/connection-pooling.asciidoc | 61 +++ src/Tests/high-level.asciidoc | 26 + src/Tests/index.asciidoc | 14 + src/Tests/low-level.asciidoc | 13 + src/Tests/query-dsl-usage.asciidoc | 6 + src/Tests/query-dsl.asciidoc | 12 + src/lib/dnx451/AsciiDoc.dll | Bin 69632 -> 69632 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 241152 -> 241152 bytes 140 files changed, 2228 insertions(+), 3222 deletions(-) create mode 100644 docs/asciidoc/aggregations-usage.asciidoc create mode 100644 docs/asciidoc/aggregations.asciidoc create mode 100644 docs/asciidoc/client-concepts.asciidoc delete mode 100644 docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc delete mode 100644 docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc delete mode 100644 docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc delete mode 100644 docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc delete mode 100644 docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc create mode 100644 docs/asciidoc/common-options.asciidoc rename docs/asciidoc/{query-dsl/geo/distance => common-options/distance-unit}/distance-units.asciidoc (69%) create mode 100644 docs/asciidoc/connection-pooling.asciidoc delete mode 100644 docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc create mode 100644 docs/asciidoc/high-level.asciidoc create mode 100644 docs/asciidoc/query-dsl-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl.asciidoc rename src/Tests/{QueryDsl/Geo/Distance => CommonOptions/DistanceUnit}/DistanceUnits.doc.cs (67%) create mode 100644 src/Tests/aggregations-usage.asciidoc create mode 100644 src/Tests/aggregations.asciidoc create mode 100644 src/Tests/client-concepts.asciidoc create mode 100644 src/Tests/common-options.asciidoc create mode 100644 src/Tests/connection-pooling.asciidoc create mode 100644 src/Tests/high-level.asciidoc create mode 100644 src/Tests/index.asciidoc create mode 100644 src/Tests/low-level.asciidoc create mode 100644 src/Tests/query-dsl-usage.asciidoc create mode 100644 src/Tests/query-dsl.asciidoc diff --git a/docs/asciidoc/aggregations-usage.asciidoc b/docs/asciidoc/aggregations-usage.asciidoc new file mode 100644 index 00000000000..1b9aafea645 --- /dev/null +++ b/docs/asciidoc/aggregations-usage.asciidoc @@ -0,0 +1,92 @@ +:includes-from-dirs: aggregations/bucket,aggregations/metric,aggregations/pipeline + +include::aggregations/bucket/children/children-aggregation-mapping.asciidoc[] + +include::aggregations/bucket/children/children-aggregation-usage.asciidoc[] + +include::aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] + +include::aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] + +include::aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] + +include::aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] + +include::aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc[] + +include::aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc[] + +include::aggregations/bucket/global/global-aggregation-usage.asciidoc[] + +include::aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc[] + +include::aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc[] + +include::aggregations/bucket/missing/missing-aggregation-usage.asciidoc[] + +include::aggregations/bucket/nested/nested-aggregation-usage.asciidoc[] + +include::aggregations/bucket/range/range-aggregation-usage.asciidoc[] + +include::aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc[] + +include::aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc[] + +include::aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc[] + +include::aggregations/bucket/terms/terms-aggregation-usage.asciidoc[] + +include::aggregations/metric/average/average-aggregation-usage.asciidoc[] + +include::aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc[] + +include::aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc[] + +include::aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc[] + +include::aggregations/metric/max/max-aggregation-usage.asciidoc[] + +include::aggregations/metric/min/min-aggregation-usage.asciidoc[] + +include::aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc[] + +include::aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc[] + +include::aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc[] + +include::aggregations/metric/stats/stats-aggregation-usage.asciidoc[] + +include::aggregations/metric/sum/sum-aggregation-usage.asciidoc[] + +include::aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc[] + +include::aggregations/metric/value-count/value-count-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc[] + +include::aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc[] + diff --git a/docs/asciidoc/aggregations.asciidoc b/docs/asciidoc/aggregations.asciidoc new file mode 100644 index 00000000000..d4631347878 --- /dev/null +++ b/docs/asciidoc/aggregations.asciidoc @@ -0,0 +1,13 @@ +:output-dir: aggregations + +[[aggregations]] += Aggregations + +include::{output-dir}/writing-aggregations.asciidoc[] + +include::aggregations-usage.asciidoc[] + + + + + diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index 99fb5d1bef9..4578212341b 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[child-aggregation-mapping]] == Child Aggregation Mapping To use the child aggregation you have to make sure diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index c71259ea2c5..01187d93e26 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[children-aggregation]] == Children Aggregation A special single bucket aggregation that enables aggregating from buckets on parent document types to @@ -11,32 +12,6 @@ buckets on child documents. Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "name_of_child_agg": { - "children": { - "type": "commits" - }, - "aggs": { - "average_per_child": { - "avg": { - "field": "confidenceFactor" - } - }, - "max_per_child": { - "max": { - "field": "confidenceFactor" - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -77,3 +52,29 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "name_of_child_agg": { + "children": { + "type": "commits" + }, + "aggs": { + "average_per_child": { + "avg": { + "field": "confidenceFactor" + } + }, + "max_per_child": { + "max": { + "field": "confidenceFactor" + } + } + } + } + } +} +---- + diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index f750140c7f7..963117ae1d4 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[date-histogram-aggregation]] == Date Histogram Aggregation A multi-bucket aggregation similar to the histogram except it can only be applied on date values. @@ -16,48 +17,10 @@ as part of the format value. Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month", - "min_doc_count": 2, - "format": "yyyy-MM-dd'T'HH:mm:ss||date_optional_time", - "order": { - "_count": "asc" - }, - "extended_bounds": { - "min": "2014-06-06T12:01:02.123", - "max": "2016-06-06T12:01:02.123" - }, - "missing": "2015-06-06T12:01:02.123" - }, - "aggs": { - "project_tags": { - "nested": { - "path": "tags" - }, - "aggs": { - "tags": { - "terms": { - "field": "tags.name" - } - } - } - } - } - } - } -} ----- - === Fluent DSL Example +=== Fluent DSL Example + [source,csharp,method="fluent"] ---- s => s diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index ce9c98bba24..1a9ff074265 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[{sectiontitle}]] == {sectiontitle} A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` @@ -16,41 +17,10 @@ IMPORTANT: this aggregation includes the `from` value and excludes the `to` valu Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "projects_date_ranges": { - "date_range": { - "field": "startedOn", - "ranges": [ - { - "to": "now", - "from": "2015-06-06T12:01:02.123||+2d" - }, - { - "to": "now+1d-30m/h" - }, - { - "from": "2012-05-05||+1d-1m" - } - ] - }, - "aggs": { - "project_tags": { - "terms": { - "field": "tags" - } - } - } - } - } -} ----- - === Fluent DSL Example +=== Fluent DSL Example + [source,csharp,method="fluent"] ---- s => s diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index 719fbb3edb9..1492782b522 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[filter-aggregation]] == Filter Aggregation Defines a single bucket of all the documents in the current document set context that match a specified filter. @@ -11,33 +12,10 @@ Often this will be used to narrow down the current aggregation context to a spec Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "bethels_projects": { - "filter": { - "term": { - "leadDeveloper.firstName": { - "value": "pierce" - } - } - }, - "aggs": { - "project_tags": { - "terms": { - "field": "curatedTags.name" - } - } - } - } - } -} ----- - === Fluent DSL Example +=== Fluent DSL Example + [source,csharp,method="fluent"] ---- s => s @@ -83,23 +61,12 @@ tags.Should().NotBeNull(); tags.Buckets.Should().NotBeEmpty(); ---- +[[empty-filter]] == Empty Filter When the collection of filters is empty or all are conditionless, NEST will serialize them to an empty object. -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "empty_filter": { - "filter": {} - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index a4185aaf8be..db7f59924b1 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[filters-aggregation]] == Filters Aggregation Defines a multi bucket aggregations where each bucket is associated with a filter. @@ -12,53 +13,9 @@ that do not match any filter, these will be collected in the _other bucket_. Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. +[[named-filters]] == Named filters -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "projects_by_state": { - "filters": { - "other_bucket": true, - "other_bucket_key": "other_states_of_being", - "filters": { - "belly_up": { - "term": { - "state": { - "value": "BellyUp" - } - } - }, - "stable": { - "term": { - "state": { - "value": "Stable" - } - } - }, - "very_active": { - "term": { - "state": { - "value": "VeryActive" - } - } - } - } - }, - "aggs": { - "project_tags": { - "terms": { - "field": "curatedTags.name" - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -92,9 +49,9 @@ new SearchRequest OtherBucketKey = "other_states_of_being", Filters = new NamedFiltersContainer { - { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, - { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, - { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } + { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, + { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, + { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } }, Aggregations = new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } @@ -102,33 +59,6 @@ new SearchRequest } ---- -=== Handling Responses - -Using the `.Agg` aggregation helper we can fetch our aggregation results easily -in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() - -[source,csharp,method="expectresponse"] ----- -response.IsValid.Should().BeTrue(); - -var filterAgg = response.Aggs.Filters("projects_by_state"); -filterAgg.Should().NotBeNull(); -var namedResult = filterAgg.NamedBucket("belly_up"); -namedResult.Should().NotBeNull(); -namedResult.DocCount.Should().BeGreaterThan(0); -namedResult = filterAgg.NamedBucket("stable"); -namedResult.Should().NotBeNull(); -namedResult.DocCount.Should().BeGreaterThan(0); -namedResult = filterAgg.NamedBucket("very_active"); -namedResult.Should().NotBeNull(); -namedResult.DocCount.Should().BeGreaterThan(0); -namedResult = filterAgg.NamedBucket("other_states_of_being"); -namedResult.Should().NotBeNull(); -namedResult.DocCount.Should().Be(0); ----- - -== Anonymous filters - [source,javascript,method="expectjson"] .Example json output ---- @@ -137,29 +67,30 @@ namedResult.DocCount.Should().Be(0); "projects_by_state": { "filters": { "other_bucket": true, - "filters": [ - { + "other_bucket_key": "other_states_of_being", + "filters": { + "belly_up": { "term": { "state": { "value": "BellyUp" } } }, - { + "stable": { "term": { "state": { "value": "Stable" } } }, - { + "very_active": { "term": { "state": { "value": "VeryActive" } } } - ] + } }, "aggs": { "project_tags": { @@ -173,6 +104,34 @@ namedResult.DocCount.Should().Be(0); } ---- +=== Handling Responses + +Using the `.Agg` aggregation helper we can fetch our aggregation results easily +in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + +[source,csharp,method="expectresponse"] +---- +response.IsValid.Should().BeTrue(); + +var filterAgg = response.Aggs.Filters("projects_by_state"); +filterAgg.Should().NotBeNull(); +var namedResult = filterAgg.NamedBucket("belly_up"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().BeGreaterThan(0); +namedResult = filterAgg.NamedBucket("stable"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().BeGreaterThan(0); +namedResult = filterAgg.NamedBucket("very_active"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().BeGreaterThan(0); +namedResult = filterAgg.NamedBucket("other_states_of_being"); +namedResult.Should().NotBeNull(); +namedResult.DocCount.Should().Be(0); +---- + +[[anonymous-filters]] +== Anonymous filters + === Fluent DSL Example [source,csharp,method="fluent"] @@ -217,6 +176,50 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "projects_by_state": { + "filters": { + "other_bucket": true, + "filters": [ + { + "term": { + "state": { + "value": "BellyUp" + } + } + }, + { + "term": { + "state": { + "value": "Stable" + } + } + }, + { + "term": { + "state": { + "value": "VeryActive" + } + } + } + ] + }, + "aggs": { + "project_tags": { + "terms": { + "field": "curatedTags.name" + } + } + } + } + } +} +---- + === Handling Responses Using the `.Agg` aggregation helper we can fetch our aggregation results easily @@ -231,33 +234,13 @@ filterAgg.Should().NotBeNull(); var results = filterAgg.AnonymousBuckets(); results.Count.Should().Be(4); singleBucket.DocCount.Should().BeGreaterThan(0); +results.Last().DocCount.Should().Be(0); //<1> ---- +<1> The last bucket is the _other bucket_ -The last bucket is the _other bucket_ - -=== Handling Responses - -[source,csharp,method="expectresponse"] ----- -results.Last().DocCount.Should().Be(0); ----- - +[[empty-filters]] == Empty Filters -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "empty_filters": { - "filters": { - "filters": [] - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -283,22 +266,12 @@ new SearchRequest } ---- -=== Handling Responses - -[source,csharp,method="expectresponse"] ----- -response.IsValid.Should().BeTrue(); -response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); ----- - -== Conditionless Filters - [source,javascript,method="expectjson"] .Example json output ---- { "aggs": { - "conditionless_filters": { + "empty_filters": { "filters": { "filters": [] } @@ -307,6 +280,17 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); } ---- +=== Handling Responses + +[source,csharp,method="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); +---- + +[[conditionless-filters]] +== Conditionless Filters + === Fluent DSL Example [source,csharp,method="fluent"] @@ -337,6 +321,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "conditionless_filters": { + "filters": { + "filters": [] + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index ba2d7da4af4..e3a2abca421 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -4,36 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "rings_around_amsterdam": { - "geo_distance": { - "field": "location", - "origin": { - "lat": 52.376, - "lon": 4.894 - }, - "ranges": [ - { - "to": 100.0 - }, - { - "from": 100.0, - "to": 300.0 - }, - { - "from": 300.0 - } - ] - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -72,6 +42,36 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "rings_around_amsterdam": { + "geo_distance": { + "field": "location", + "origin": { + "lat": 52.376, + "lon": 4.894 + }, + "ranges": [ + { + "to": 100.0 + }, + { + "from": 100.0, + "to": 300.0 + }, + { + "from": 300.0 + } + ] + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index a5a2aed71e0..1746a4b57f4 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -4,23 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "my_geohash_grid": { - "geohash_grid": { - "field": "location", - "precision": 3, - "size": 1000, - "shard_size": 100 - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -52,6 +35,23 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "my_geohash_grid": { + "geohash_grid": { + "field": "location", + "precision": 3, + "size": 1000, + "shard_size": 100 + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index ff04357043b..af9fca32e82 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -4,25 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "all_projects": { - "global": {}, - "aggs": { - "names": { - "terms": { - "field": "name" - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -55,6 +36,25 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "all_projects": { + "global": {}, + "aggs": { + "names": { + "terms": { + "field": "name" + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index 6496e64c413..811f02848ff 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -4,25 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commits": { - "histogram": { - "field": "numberOfCommits", - "interval": 100.0, - "missing": 0.0, - "order": { - "_key": "desc" - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -54,6 +35,25 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits": { + "histogram": { + "field": "numberOfCommits", + "interval": 100.0, + "missing": 0.0, + "order": { + "_key": "desc" + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index e8dd43fd886..a285f11dd6a 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -4,28 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "ip_ranges": { - "ip_range": { - "field": "leadDeveloper.iPAddress", - "ranges": [ - { - "to": "10.0.0.5" - }, - { - "from": "10.0.0.5" - } - ] - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -60,6 +38,28 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "ip_ranges": { + "ip_range": { + "field": "leadDeveloper.iPAddress", + "ranges": [ + { + "to": "10.0.0.5" + }, + { + "from": "10.0.0.5" + } + ] + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index 3d1502380e4..2085e6be383 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "projects_without_a_description": { - "missing": { - "field": "description" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -43,6 +29,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "projects_without_a_description": { + "missing": { + "field": "description" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index 121f4084956..dcf81fc4236 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -4,27 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "tags": { - "nested": { - "path": "tags" - }, - "aggs": { - "tag_names": { - "terms": { - "field": "tags.name" - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -59,6 +38,27 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "tags": { + "nested": { + "path": "tags" + }, + "aggs": { + "tag_names": { + "terms": { + "field": "tags.name" + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index 34db5d81177..ad652cfc899 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -4,32 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commit_ranges": { - "range": { - "field": "numberOfCommits", - "ranges": [ - { - "to": 100.0 - }, - { - "from": 100.0, - "to": 500.0 - }, - { - "from": 500.0 - } - ] - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -66,6 +40,32 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_ranges": { + "range": { + "field": "numberOfCommits", + "ranges": [ + { + "to": 100.0 + }, + { + "from": 100.0, + "to": 500.0 + }, + { + "from": 500.0 + } + ] + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index f3e74ed8399..aeff4fd486e 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -4,39 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "tags": { - "nested": { - "path": "tags" - }, - "aggs": { - "tag_names": { - "terms": { - "field": "tags.name" - }, - "aggs": { - "tags_to_project": { - "reverse_nested": {}, - "aggs": { - "top_projects_per_tag": { - "terms": { - "field": "name" - } - } - } - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -87,6 +54,39 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "tags": { + "nested": { + "path": "tags" + }, + "aggs": { + "tag_names": { + "terms": { + "field": "tags.name" + }, + "aggs": { + "tags_to_project": { + "reverse_nested": {}, + "aggs": { + "top_projects_per_tag": { + "terms": { + "field": "name" + } + } + } + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index 120c184acea..b063f9e3e82 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -4,28 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "sample": { - "sampler": { - "shard_size": 200, - "field": "name" - }, - "aggs": { - "significant_names": { - "significant_terms": { - "field": "name" - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -62,6 +40,28 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "sample": { + "sampler": { + "shard_size": 200, + "field": "name" + }, + "aggs": { + "significant_names": { + "significant_terms": { + "field": "name" + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 255757373b1..1e9ba8a8b1a 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -4,25 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "significant_names": { - "significant_terms": { - "field": "name", - "min_doc_count": 10, - "mutual_information": { - "background_is_superset": true, - "include_negatives": true - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -59,6 +40,25 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "significant_names": { + "significant_terms": { + "field": "name", + "min_doc_count": 10, + "mutual_information": { + "background_is_superset": true, + "include_negatives": true + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index 6d5cbe0cec4..9c20d66ea17 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -4,40 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "states": { - "meta": { - "foo": "bar" - }, - "terms": { - "field": "state", - "min_doc_count": 2, - "size": 5, - "shard_size": 100, - "show_term_doc_error_count": true, - "execution_hint": "map", - "missing": "n/a", - "script": { - "inline": "'State of Being: '+_value" - }, - "order": [ - { - "_term": "asc" - }, - { - "_count": "desc" - } - ] - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -91,6 +57,40 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "states": { + "meta": { + "foo": "bar" + }, + "terms": { + "field": "state", + "min_doc_count": 2, + "size": 5, + "shard_size": 100, + "show_term_doc_error_count": true, + "execution_hint": "map", + "missing": "n/a", + "script": { + "inline": "'State of Being: '+_value" + }, + "order": [ + { + "_term": "asc" + }, + { + "_count": "desc" + } + ] + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index 9c2f9af06be..623cbb4082d 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -4,27 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "average_commits": { - "meta": { - "foo": "bar" - }, - "avg": { - "field": "numberOfCommits", - "missing": 10.0, - "script": { - "inline": "_value * 1.2" - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -60,6 +39,27 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "average_commits": { + "meta": { + "foo": "bar" + }, + "avg": { + "field": "numberOfCommits", + "missing": 10.0, + "script": { + "inline": "_value * 1.2" + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index ed8e1eacbc1..7e2227852cc 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -4,21 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "state_count": { - "cardinality": { - "field": "state", - "precision_threshold": 100 - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -45,6 +30,21 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "state_count": { + "cardinality": { + "field": "state", + "precision_threshold": 100 + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 98148760544..d4f0a201c4a 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commit_stats": { - "extended_stats": { - "field": "numberOfCommits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,6 +26,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_stats": { + "extended_stats": { + "field": "numberOfCommits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index cb5d25bc0c1..60257c7e25d 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -4,21 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "viewport": { - "geo_bounds": { - "field": "location", - "wrap_longitude": true - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -45,6 +30,21 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "viewport": { + "geo_bounds": { + "field": "location", + "wrap_longitude": true + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index 1223a64c70d..dd35a83a9b8 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "max_commits": { - "max": { - "field": "numberOfCommits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,6 +26,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "max_commits": { + "max": { + "field": "numberOfCommits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index e6fe8a591a1..53089f98b17 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "min_commits": { - "min": { - "field": "numberOfCommits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,6 +26,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "min_commits": { + "min": { + "field": "numberOfCommits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index fb0061e4cf4..9adad63d89f 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -4,31 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commits_outlier": { - "percentile_ranks": { - "field": "numberOfCommits", - "values": [ - 15.0, - 30.0 - ], - "tdigest": { - "compression": 200.0 - }, - "script": { - "inline": "doc['numberOfCommits'].value * 1.2" - }, - "missing": 0.0 - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -68,6 +43,31 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits_outlier": { + "percentile_ranks": { + "field": "numberOfCommits", + "values": [ + 15.0, + 30.0 + ], + "tdigest": { + "compression": 200.0 + }, + "script": { + "inline": "doc['numberOfCommits'].value * 1.2" + }, + "missing": 0.0 + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index f0719ad6672..d1dc722f9c9 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -4,32 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commits_outlier": { - "percentiles": { - "field": "numberOfCommits", - "percents": [ - 95.0, - 99.0, - 99.9 - ], - "hdr": { - "number_of_significant_value_digits": 3 - }, - "script": { - "inline": "doc['numberOfCommits'].value * 1.2" - }, - "missing": 0.0 - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -69,6 +43,32 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits_outlier": { + "percentiles": { + "field": "numberOfCommits", + "percents": [ + 95.0, + 99.0, + 99.9 + ], + "hdr": { + "number_of_significant_value_digits": 3 + }, + "script": { + "inline": "doc['numberOfCommits'].value * 1.2" + }, + "missing": 0.0 + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index 66ae4a224ec..7e607bff961 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -4,31 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "sum_the_hard_way": { - "scripted_metric": { - "init_script": { - "inline": "_agg['commits'] = []" - }, - "map_script": { - "inline": "if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }" - }, - "combine_script": { - "inline": "sum = 0; for (c in _agg.commits) { sum += c }; return sum" - }, - "reduce_script": { - "inline": "sum = 0; for (a in _aggs) { sum += a }; return sum" - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -60,6 +35,31 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "sum_the_hard_way": { + "scripted_metric": { + "init_script": { + "inline": "_agg['commits'] = []" + }, + "map_script": { + "inline": "if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }" + }, + "combine_script": { + "inline": "sum = 0; for (c in _agg.commits) { sum += c }; return sum" + }, + "reduce_script": { + "inline": "sum = 0; for (a in _aggs) { sum += a }; return sum" + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index a49d559ed6f..86c99cbfdd5 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commit_stats": { - "stats": { - "field": "numberOfCommits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,6 +26,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_stats": { + "stats": { + "field": "numberOfCommits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 072e1b225c9..863b662a861 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commits_sum": { - "sum": { - "field": "numberOfCommits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,6 +26,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commits_sum": { + "sum": { + "field": "numberOfCommits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index cf49ab9e854..d3cc0ab59f9 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -4,59 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "states": { - "terms": { - "field": "state" - }, - "aggs": { - "top_state_hits": { - "top_hits": { - "sort": [ - { - "startedOn": { - "order": "desc" - } - } - ], - "_source": { - "include": [ - "name", - "startedOn" - ] - }, - "size": 1, - "version": true, - "explain": true, - "fielddata_fields": [ - "state", - "numberOfCommits" - ], - "highlight": { - "fields": { - "tags": {}, - "description": {} - } - }, - "script_fields": { - "commit_factor": { - "script": { - "inline": "doc['numberOfCommits'].value * 2" - } - } - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -143,6 +90,59 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "states": { + "terms": { + "field": "state" + }, + "aggs": { + "top_state_hits": { + "top_hits": { + "sort": [ + { + "startedOn": { + "order": "desc" + } + } + ], + "_source": { + "include": [ + "name", + "startedOn" + ] + }, + "size": 1, + "version": true, + "explain": true, + "fielddata_fields": [ + "state", + "numberOfCommits" + ], + "highlight": { + "fields": { + "tags": {}, + "description": {} + } + }, + "script_fields": { + "commit_factor": { + "script": { + "inline": "doc['numberOfCommits'].value * 2" + } + } + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index 91586851e1d..02d4d2fb17b 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -4,20 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "commit_count": { - "value_count": { - "field": "numberOfCommits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,6 +26,20 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "aggs": { + "commit_count": { + "value_count": { + "field": "numberOfCommits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index be5ea293c96..cef90fd5f4a 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -4,35 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - } - } - }, - "average_commits_per_month": { - "avg_bucket": { - "buckets_path": "projects_started_per_month>commits", - "gap_policy": "insert_zeros" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -76,6 +47,35 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "average_commits_per_month": { + "avg_bucket": { + "buckets_path": "projects_started_per_month>commits", + "gap_policy": "insert_zeros" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index a11a4b1aead..de5023df0ec 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -4,56 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "stable_state": { - "filter": { - "term": { - "state": { - "value": "Stable" - } - } - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - } - } - }, - "stable_percentage": { - "bucket_script": { - "buckets_path": { - "totalCommits": "commits", - "stableCommits": "stable_state>commits" - }, - "script": { - "inline": "stableCommits / totalCommits * 100" - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -124,6 +74,56 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "stable_state": { + "filter": { + "term": { + "state": { + "value": "Stable" + } + } + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "stable_percentage": { + "bucket_script": { + "buckets_path": { + "totalCommits": "commits", + "stableCommits": "stable_state>commits" + }, + "script": { + "inline": "stableCommits / totalCommits * 100" + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 97538352169..7eca62e67ac 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -4,39 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_bucket_filter": { - "bucket_selector": { - "buckets_path": { - "totalCommits": "commits" - }, - "script": { - "inline": "totalCommits >= 500" - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -86,6 +53,39 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_bucket_filter": { + "bucket_selector": { + "buckets_path": { + "totalCommits": "commits" + }, + "script": { + "inline": "totalCommits >= 500" + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index ce96ce52b5d..92395894887 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -4,34 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "cumulative_commits": { - "cumulative_sum": { - "buckets_path": "commits" - } - } - } - } - } -} ----- - === Handling Responses [source,csharp,method="expectresponse"] @@ -86,3 +58,31 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "cumulative_commits": { + "cumulative_sum": { + "buckets_path": "commits" + } + } + } + } + } +} +---- + diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index 14d79bbcea1..46a8f502cb2 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -4,34 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_derivative": { - "derivative": { - "buckets_path": "commits" - } - } - } - } - } -} ----- - === Handling Responses [source,csharp,method="expectresponse"] @@ -86,3 +58,31 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_derivative": { + "derivative": { + "buckets_path": "commits" + } + } + } + } + } +} +---- + diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index 918669178a8..94588f8fbee 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -4,34 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - } - } - }, - "max_commits_per_month": { - "max_bucket": { - "buckets_path": "projects_started_per_month>commits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -71,6 +43,34 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "max_commits_per_month": { + "max_bucket": { + "buckets_path": "projects_started_per_month>commits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index 332b5927d69..fbaad557ee0 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -4,34 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - } - } - }, - "min_commits_per_month": { - "min_bucket": { - "buckets_path": "projects_started_per_month>commits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -71,6 +43,34 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "min_commits_per_month": { + "min_bucket": { + "buckets_path": "projects_started_per_month>commits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index ec35876fe7d..fe39ffa3f0e 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -4,38 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_moving_avg": { - "moving_avg": { - "buckets_path": "commits", - "model": "ewma", - "settings": { - "alpha": 0.3 - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -87,6 +55,38 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "model": "ewma", + "settings": { + "alpha": 0.3 + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index 8c62867ff83..ac7610e938c 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -4,39 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_moving_avg": { - "moving_avg": { - "buckets_path": "commits", - "model": "holt", - "settings": { - "alpha": 0.5, - "beta": 0.5 - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -90,6 +57,39 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "model": "holt", + "settings": { + "alpha": 0.5, + "beta": 0.5 + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index 0b5a3e3da36..c4c6849b778 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -4,44 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_moving_avg": { - "moving_avg": { - "buckets_path": "commits", - "window": 60, - "model": "holt_winters", - "settings": { - "type": "mult", - "alpha": 0.5, - "beta": 0.5, - "gamma": 0.5, - "period": 30, - "pad": false - } - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -105,6 +67,44 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "window": 60, + "model": "holt_winters", + "settings": { + "type": "mult", + "alpha": 0.5, + "beta": 0.5, + "gamma": 0.5, + "period": 30, + "pad": false + } + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index 16bb300d22b..efdf2c0598e 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -4,37 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_moving_avg": { - "moving_avg": { - "buckets_path": "commits", - "gap_policy": "insert_zeros", - "model": "linear", - "settings": {} - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -83,6 +52,37 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "gap_policy": "insert_zeros", + "model": "linear", + "settings": {} + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index 4e30d35227b..1512121492d 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -4,38 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "commits_moving_avg": { - "moving_avg": { - "buckets_path": "commits", - "model": "simple", - "window": 30, - "predict": 10, - "settings": {} - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -86,6 +54,38 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "commits_moving_avg": { + "moving_avg": { + "buckets_path": "commits", + "model": "simple", + "window": 30, + "predict": 10, + "settings": {} + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index e3d515ab084..655e6ae0eec 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -4,35 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - }, - "thirtieth_difference": { - "serial_diff": { - "buckets_path": "commits", - "lag": 30 - } - } - } - } - } -} ----- - === Handling Responses [source,csharp,method="expectresponse"] @@ -91,3 +62,32 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + }, + "thirtieth_difference": { + "serial_diff": { + "buckets_path": "commits", + "lag": 30 + } + } + } + } + } +} +---- + diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index 0028772954d..6c7ebd4ecf5 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -4,34 +4,6 @@ :imagesdir: ../../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "size": 0, - "aggs": { - "projects_started_per_month": { - "date_histogram": { - "field": "startedOn", - "interval": "month" - }, - "aggs": { - "commits": { - "sum": { - "field": "numberOfCommits" - } - } - } - }, - "sum_of_commits": { - "sum_bucket": { - "buckets_path": "projects_started_per_month>commits" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -71,6 +43,34 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month" + }, + "aggs": { + "commits": { + "sum": { + "field": "numberOfCommits" + } + } + } + }, + "sum_of_commits": { + "sum_bucket": { + "buckets_path": "projects_started_per_month>commits" + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 295e5b0a34f..57ef0422d23 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../images +[[aggregations]] == Aggregations Aggregations are arguably one of the most powerful features of Elasticsearch. @@ -22,37 +23,13 @@ want to use each. This is the json output for each example -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "aggs": { - "name_of_child_agg": { - "children": { - "type": "commits" - }, - "aggs": { - "average_per_child": { - "avg": { - "field": "confidenceFactor" - } - }, - "max_per_child": { - "max": { - "field": "confidenceFactor" - } - } - } - } - } -} ----- - === Fluent DSL The fluent lambda syntax is the most terse way to write aggregations. It benefits from types that are carried over to sub aggregations +=== Fluent DSL Example + [source,csharp,method="fluent"] ---- s => s diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc index 6a645009b46..69b9a8e55fd 100644 --- a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -4,6 +4,20 @@ :imagesdir: ../../images +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + [source,javascript,method="expectjson"] .Example json output ---- @@ -58,17 +72,3 @@ } ---- -=== Fluent DSL Example - -[source,csharp,method="fluent"] ----- -FluentExample ----- - -=== Object Initializer Syntax Example - -[source,csharp,method="initializer"] ----- -InitializerExample ----- - diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc index 97e43235b05..a5e4427f018 100644 --- a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -4,6 +4,20 @@ :imagesdir: ../../images +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + [source,javascript,method="expectjson"] .Example json output ---- @@ -29,17 +43,3 @@ } ---- -=== Fluent DSL Example - -[source,csharp,method="fluent"] ----- -FluentExample ----- - -=== Object Initializer Syntax Example - -[source,csharp,method="initializer"] ----- -InitializerExample ----- - diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc index 7633c83941a..72cce3246a5 100644 --- a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -4,6 +4,20 @@ :imagesdir: ../../images +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + [source,javascript,method="expectjson"] .Example json output ---- @@ -221,17 +235,3 @@ } ---- -=== Fluent DSL Example - -[source,csharp,method="fluent"] ----- -FluentExample ----- - -=== Object Initializer Syntax Example - -[source,csharp,method="initializer"] ----- -InitializerExample ----- - diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc index abbbdb10612..fcf5fc455f7 100644 --- a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -4,6 +4,20 @@ :imagesdir: ../../images +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + [source,javascript,method="expectjson"] .Example json output ---- @@ -57,17 +71,3 @@ } ---- -=== Fluent DSL Example - -[source,csharp,method="fluent"] ----- -FluentExample ----- - -=== Object Initializer Syntax Example - -[source,csharp,method="initializer"] ----- -InitializerExample ----- - diff --git a/docs/asciidoc/client-concepts.asciidoc b/docs/asciidoc/client-concepts.asciidoc new file mode 100644 index 00000000000..eb7ac6d6167 --- /dev/null +++ b/docs/asciidoc/client-concepts.asciidoc @@ -0,0 +1,12 @@ +[[client-concepts]] += Client Concepts + +include::low-level.asciidoc[] + +include::high-level.asciidoc[] + +include::connection-pooling.asciidoc[] + + + + diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index 56b54416ca1..b4c155d2a75 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[connection-pooling]] == Connection Pooling Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 050485d2b06..b3197bbfaf1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[date-time-providers]] == Date time providers Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 25a7f6f1111..d5cb51399e3 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[keeping-track-of-nodes]] == Keeping track of nodes === Creating a Node diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 25019419619..601a8884fc2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[request-pipeline]] == Request Pipeline Every request is executed in the context of a `RequestPipeline` when using the diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index 1e447a2735f..c83dedb609d 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[transports]] == Transports The `ITransport` interface can be seen as the motor block of the client. It's interface is deceitfully simple and diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index 5e5d4f12c19..fce1c34f396 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[unexpected-exceptions]] == Unexpected exceptions When a client call throws an exception that the IConnction can not handle, this exception will bubble diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 1bcd782799f..1c315d7b5e2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[unrecoverable-exceptions]] == Unrecoverable exceptions Unrecoverable exceptions are _excepted_ exceptions that are grounds to exit the client pipeline immediately. diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 4fcf267ce0a..c8ecc076371 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[fail-over]] == Fail over When using connection pooling and the pool has sufficient nodes a request will be retried if diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index 91231ecbd43..d38daa49726 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[max-retries]] == MaxRetries By default retry as many times as we have nodes. However retries still respect the request timeout. diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index a73a8cca401..d2be9120876 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[pinging---first-usage]] == Pinging - First Usage Pinging is enabled by default for the Static & Sniffing connection pool. diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 6ac650bcc66..29472c2c06e 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[pinging---revival]] == Pinging - Revival When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 20477cdcaf1..4f16cde4420 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[disabling-sniffing-and-pinging-on-a-request-basis]] == Disabling sniffing and pinging on a request basis Even if you are using a sniffing connection pool thats set up to sniff on start/failure diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 26346af6d69..fcd8e5e2e49 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[request-timeouts]] == Request Timeouts While you can specify Request time out globally you can override this per request too @@ -49,6 +50,7 @@ new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) ); ---- +[[connect-timeouts]] == Connect Timeouts Connect timeouts can be overridden, webrequest/httpclient can not distinguish connect and retry timeouts however diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 49cd23fb61c..19a18a7dfab 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[allowed-status-codes]] == Allowed status codes [source,csharp,method="canoverridebadresponse"] diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 5f457321333..63659f79d5f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[forcing-nodes]] == Forcing nodes Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index ef91ad1dc8b..11b0497085f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[maximum-retries]] == Maximum Retries By default retry as many times as we have nodes. However retries still respect the request timeout. diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index 71e6b8a26b6..ed1d320833b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[round-robin]] == Round Robin Each connection pool round robins over the `live` nodes, to evenly distribute the load over all known nodes. diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index f1d91811244..d490c9c92a1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../../images +[[round-robin---skipping-dead-nodes]] == Round Robin - Skipping Dead Nodes When selecting nodes the connection pool will try and skip all the nodes that are marked dead. diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index e1c86ad213e..a40eb4355ca 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[sniffing-on-connection-failure]] == Sniffing on connection failure Sniffing on connection is enabled by default when using a connection pool that allows reseeding. diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index b2f50e7f0a3..0460c3ecfd7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[sniffing-periodically]] == Sniffing periodically Connection pools that return true for `SupportsReseeding` can be configured to sniff periodically. diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index f976c44b1c8..225e5d33499 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[sniffing-on-startup]] == Sniffing on startup Connection pools that return true for `SupportsReseeding` by default sniff on startup. diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index cab25b04c21..396b83f420b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[sniffing-role-detection]] == Sniffing role detection When we sniff the custer state we detect the role of the node whether its master eligible and holds data diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index 0c065e6f7ee..b78e05a30f2 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[covariant-search-results]] == Covariant Search Results NEST directly supports returning covariant result sets. diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index ac9fca23db8..7ecff879cda 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[document-paths]] == DocumentPaths Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index 6c5a30e08a7..660f1a74847 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[strongly-typed-field-access]] == Strongly typed Field Access Several places in the elasticsearch API expect the path to a field from your original source document as a string. @@ -158,10 +159,10 @@ Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable]) Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ---- -If you are using elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow +If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow you to analyze a string in a number of different ways, these _"virtual" sub fields do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that -should be mapped. +should be mapped and <> [source,csharp,method="complexfieldnameexpressions"] ---- @@ -413,7 +414,7 @@ class CustomSerializer : JsonNetSerializer } ---- -here we provide an explicit rename of a property on connectionsettings using `.Rename()` +here we provide an explicit rename of a property on `ConnectionSettings` using `.Rename()` and all properties that are not mapped verbatim should be uppercased [source,csharp,method="precedenceisasexpected"] diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index 8babd2f9966..335cc289fe0 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[id-inference]] == Id Inference === Implicit Conversions diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index dc0df0a8ea7..56c0715f441 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[indices-paths]] == Indices paths Some API's in elasticsearch take one or many index name or a special "all" marker to send the request to all the indices diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index 4218dd541e9..8aa6a57c511 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../../images +[[property-names]] == Property Names Property names resolve to the last token. An example using the `.Suffix()` extension diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc deleted file mode 100644 index 454d61ebced..00000000000 --- a/docs/asciidoc/client-concepts/high-level/inferrence/document-paths.asciidoc +++ /dev/null @@ -1,126 +0,0 @@ -:section-number: 2.4 - -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images - -== DocumentPaths - -Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes -and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path -to your document more succintly - -=== Creating new instances - -here we create a new document path based on Project with the id 1 - -[source,csharp,method-name="fromid"] ----- -IDocumentPath path = new DocumentPath(1); - -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); ----- - -You can still override the inferred index and type name - -[source,csharp,method-name="fromid"] ----- -path = new DocumentPath(1).Type("project1"); - -Expect("project1").WhenSerializing(path.Type); -path = new DocumentPath(1).Index("project1"); -Expect("project1").WhenSerializing(path.Index); ----- - -and there is also a static way to describe such paths - -[source,csharp,method-name="fromid"] ----- -path = DocumentPath.Id(1); - -Expect("project").WhenSerializing(path.Index); -Expect("project").WhenSerializing(path.Type); -Expect(1).WhenSerializing(path.Id); ----- - -=== Creating from a document type instance - -if you have an instance of your document you can use it as well generate document paths - -[source,csharp,method-name="fromobject"] ----- -var project = new Project { Name = "hello-world" }; ----- - -here we create a new document path based on the instance of `Project`, project - -[source,csharp,method-name="fromobject"] ----- -IDocumentPath path = new DocumentPath(project); - -Expect("project").WhenSerializing(path.Index); - -Expect("project").WhenSerializing(path.Type); - -Expect("hello-world").WhenSerializing(path.Id); ----- - -You can still override the inferred index and type name - -[source,csharp,method-name="fromobject"] ----- -path = new DocumentPath(project).Type("project1"); - -Expect("project1").WhenSerializing(path.Type); - -path = new DocumentPath(project).Index("project1"); - -Expect("project1").WhenSerializing(path.Index); ----- - -and again, there is also a static way to describe such paths - -[source,csharp,method-name="fromobject"] ----- -path = DocumentPath.Id(project); - -Expect("project").WhenSerializing(path.Index); - -Expect("project").WhenSerializing(path.Type); - -Expect("hello-world").WhenSerializing(path.Id); - -DocumentPath p = project; ----- - -=== An example with requests - -[source,csharp,method-name="usingwithrequests"] ----- -var project = new Project { Name = "hello-world" }; ----- - -we can see an example of how `DocumentPath` helps your describe your requests more tersely - -[source,csharp,method-name="usingwithrequests"] ----- -var request = new IndexRequest(2) { Document = project }; - -request = new IndexRequest(project) { }; ----- - -when comparing with the full blown constructor and passing document manually, -`DocumentPath`'s benefits become apparent. - -[source,csharp,method-name="usingwithrequests"] ----- -request = new IndexRequest(IndexName.From(), TypeName.From(), 2) -{ - Document = project -}; ----- - diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc deleted file mode 100644 index 6eacd91488b..00000000000 --- a/docs/asciidoc/client-concepts/high-level/inferrence/field-inference.asciidoc +++ /dev/null @@ -1,460 +0,0 @@ -:section-number: 2.1 - -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images - -== Strongly typed Field Access - -Several places in the elasticsearch API expect the path to a field from your original source document as a string. -NEST allows you to use C expressions to strongly type these field path strings. - -These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: - -Using the constructor directly is possible but rather involved - -[source,csharp,method-name="usingconstructors"] ----- -var fieldString = new Field { Name = "name" }; ----- - -especially when using C expressions since these can not be simply new'ed - -[source,csharp,method-name="usingconstructors"] ----- -Expression> expression = p => p.Name; - -var fieldExpression = Field.Create(expression); -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- - -Therefore you can also implicitly convert strings and expressions to `Field`s - -[source,csharp,method-name="implicitconversion"] ----- -Field fieldString = "name"; ----- - -but for expressions this is still rather involved - -[source,csharp,method-name="implicitconversion"] ----- -Expression> expression = p => p.Name; - -Field fieldExpression = expression; - -Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); ----- - -to ease creating `Field`s from expressions there is a static Property class you can use - -[source,csharp,method-name="usingstaticpropertyfield"] ----- -Field fieldString = "name"; ----- - -but for expressions this is still rather involved - -[source,csharp,method-name="usingstaticpropertyfield"] ----- -var fieldExpression = Infer.Field(p => p.Name); ----- - -this can be even shortened even further using static imports in c 6 i.e. - `using static Nest.Static;` - -[source,csharp,method-name="usingstaticpropertyfield"] ----- -fieldExpression = Field(p => p.Name); ----- - -Now this is much much terser then our first example using the constructor! - -[source,csharp,method-name="usingstaticpropertyfield"] ----- -Expect("name") - .WhenSerializing(fieldString) - .WhenSerializing(fieldExpression); ----- - -By default, NEST will camel-case all field names to be more _javascript-y_ - -using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior - -[source,csharp,method-name="defaultfieldnameinferrer"] ----- -var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); - -setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); ----- - -However string are *always* passed along verbatim - -[source,csharp,method-name="defaultfieldnameinferrer"] ----- -setup.Expect("NaMe").WhenSerializing("NaMe"); ----- - -if you want the same behavior for expressions simply do nothing in the default inferrer - -[source,csharp,method-name="defaultfieldnameinferrer"] ----- -setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); - -setup.Expect("Name").WhenSerializing(Field(p => p.Name)); ----- - -=== Complex field name expressions - -You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ----- - -When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ----- - -NOTE: Similarly, LINQ's `.First()` method also works -remember these are expressions and not actual code that will be executed - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); - -Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); - -Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); ----- - -An indexer on a dictionary is assumed to describe a property name - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); - -Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); ----- - -A cool feature here is that we'll evaluate variables passed to an indexer - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -var variable = "var"; - -Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable])); - -Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ----- - -If you are using elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow -you to analyze a string in a number of different ways, these _"virtual" sub fields -do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that -should be mapped. - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); - -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); - -Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags.First().Suffix("raw"))); - -Expect("curatedTags.added.raw").WhenSerializing(Field(p => p.CuratedTags[0].Added.Suffix("raw"))); - -Expect("metadata.hardcoded.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Suffix("raw"))); - -Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created.Suffix("raw"))); ----- - -You can even chain `.Suffix()` calls to any depth! - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ----- - -Variables passed to suffix will be evaluated as well - -[source,csharp,method-name="complexfieldnameexpressions"] ----- -var suffix = "unanalyzed"; - -Expect("metadata.var.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Suffix(suffix))); - -Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p.Metadata[variable].Created.Suffix(suffix))); ----- - -Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix -to a list of fields. - -Here we have a list of expressions - -[source,csharp,method-name="appendingsuffixtoexpressions"] ----- -var expressions = new List>> -{ - p => p.Name, - p => p.Description, - p => p.CuratedTags.First().Name, - p => p.LeadDeveloper.FirstName -}; ----- - -and we want to append the suffix "raw" to each - -[source,csharp,method-name="appendingsuffixtoexpressions"] ----- -var fieldExpressions = - expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); - -Expect("name.raw").WhenSerializing(fieldExpressions[0]); - -Expect("description.raw").WhenSerializing(fieldExpressions[1]); - -Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); - -Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); ----- - -=== Annotations - -When using NEST's property attributes you can specify a new name for the properties - -[source,csharp,method-name="unknown"] ----- -public class BuiltIn -{ - [String(Name = "naam")] - public string Name { get; set; } -} ----- - -[source,csharp,method-name="builtinannotiatons"] ----- -Expect("naam").WhenSerializing(Field(p => p.Name)); ----- - -Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. -Here we ask the default `JsonNetSerializer` to resolve a property name and it takes -the `JsonPropertyAttribute` into account - -[source,csharp,method-name="unknown"] ----- -public class SerializerSpecific -{ - [JsonProperty("nameInJson")] - public string Name { get; set; } -} ----- - -[source,csharp,method-name="serializerspecificannotations"] ----- -Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ----- - -If both a NEST property attribute and a serializer specific attribute are present on a property, -NEST takes precedence - -[source,csharp,method-name="unknown"] ----- -public class Both -{ - [String(Name = "naam")] - [JsonProperty("nameInJson")] - public string Name { get; set; } -} ----- - -[source,csharp,method-name="nestattributetakesprecedence"] ----- -Expect("naam").WhenSerializing(Field(p => p.Name)); - -Expect(new -{ - naam = "Martijn Laarman" -}).WhenSerializing(new Both { Name = "Martijn Laarman" }); ----- - -Resolution of field names is cached per connection settings instance. To demonstrate, -take the following simple POCOs - -[source,csharp,method-name="unknown"] ----- -class A { public C C { get; set; } } - -class B { public C C { get; set; } } - -class C { public string Name { get; set; } } ----- - -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ----- -var connectionSettings = TestClient.CreateSettings(forceInMemory: true); - -var client = new ElasticClient(connectionSettings); - -var fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); - -var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); ----- - -Here we have to similary shaped expressions on coming from A and on from B -that will resolve to the same field name, as expected - -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ----- -fieldNameOnA.Should().Be("c.name"); - -fieldNameOnB.Should().Be("c.name"); ----- - -now we create a new connectionsettings with a remap for C on class A to `d` -now when we resolve the field path for A will be different - -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ----- -var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s - .InferMappingFor(m => m - .Rename(p => p.C, "d") - ) -); - -var newClient = new ElasticClient(newConnectionSettings); - -fieldNameOnA = newClient.Infer.Field(Field(p => p.C.Name)); - -fieldNameOnB = newClient.Infer.Field(Field(p => p.C.Name)); - -fieldNameOnA.Should().Be("d.name"); - -fieldNameOnB.Should().Be("c.name"); ----- - -however we didn't break inferrence on the first client instance using its separate connectionsettings - -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] ----- -fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); - -fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); - -fieldNameOnA.Should().Be("c.name"); - -fieldNameOnB.Should().Be("c.name"); ----- - -To wrap up, the precedence in which field names are inferred is: - -. A hard rename of the property on connection settings using `.Rename()` - -. A NEST property mapping - -. Ask the serializer if the property has a verbatim value e.g it has an explicit JsonPropery attribute. - -. Pass the MemberInfo's Name to the DefaultFieldNameInferrer which by default camelCases - -The following example class will demonstrate this precedence - -[source,csharp,method-name="unknown"] ----- -class Precedence -{ - // Even though this property has a NEST property mapping and a JsonProperty attribute, - // We are going to provide a hard rename for it on ConnectionSettings later that should win. - [String(Name = "renamedIgnoresNest")] - [JsonProperty("renamedIgnoresJsonProperty")] - public string RenamedOnConnectionSettings { get; set; } - - // This property has both a NEST attribute and a JsonProperty, NEST should win. - [String(Name = "nestAtt")] - [JsonProperty("jsonProp")] - public string NestAttribute { get; set; } - - // We should take the json property into account by itself - [JsonProperty("jsonProp")] - public string JsonProperty { get; set; } - - // This property we are going to special case in our custom serializer to resolve to ask - [JsonProperty("dontaskme")] - public string AskSerializer { get; set; } - - // We are going to register a DefaultFieldNameInferrer on ConnectionSettings - // that will uppercase all properties. - public string DefaultFieldNameInferrer { get; set; } -} ----- - -Here we create a custom serializer that renames any property named `AskSerializer` to `ask` - -[source,csharp,method-name="unknown"] ----- -class CustomSerializer : JsonNetSerializer -{ - public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } - - public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) - { - return memberInfo.Name == nameof(Precedence.AskSerializer) - ? new PropertyMapping { Name = "ask" } - : base.CreatePropertyMapping(memberInfo); - } -} ----- - -here we provide an explicit rename of a property on connectionsettings using `.Rename()` -and all properties that are not mapped verbatim should be uppercased - -[source,csharp,method-name="precedenceisasexpected"] ----- -var usingSettings = WithConnectionSettings(s => s - - .InferMappingFor(m => m - .Rename(p => p.RenamedOnConnectionSettings, "renamed") - ) - .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) -).WithSerializer(s => new CustomSerializer(s)); - -usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); - -usingSettings.Expect("nestAtt").ForField(Field(p => p.NestAttribute)); - -usingSettings.Expect("jsonProp").ForField(Field(p => p.JsonProperty)); - -usingSettings.Expect("ask").ForField(Field(p => p.AskSerializer)); - -usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => p.DefaultFieldNameInferrer)); ----- - -The same naming rules also apply when indexing a document - -[source,csharp,method-name="precedenceisasexpected"] ----- -usingSettings.Expect(new [] -{ - "ask", - "DEFAULTFIELDNAMEINFERRER", - "jsonProp", - "nestAtt", - "renamed" -}).AsPropertiesOf(new Precedence -{ - RenamedOnConnectionSettings = "renamed on connection settings", - NestAttribute = "using a nest attribute", - JsonProperty = "the default serializer resolves json property attributes", - AskSerializer = "serializer fiddled with this one", - DefaultFieldNameInferrer = "shouting much?" -}); ----- - diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc deleted file mode 100644 index fb85a375f6d..00000000000 --- a/docs/asciidoc/client-concepts/high-level/inferrence/ids-inference.asciidoc +++ /dev/null @@ -1,135 +0,0 @@ -:section-number: 2.3 - -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images - -== Id Inference - -=== Implicit Conversions - -Several places in the Elasticsearch API expect an `Id` object to be passed. -This is a special box type that you can implicitly convert to from the following types - -* `Int32` - -* `Int64` - -* `String` - -* `Guid` - -Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` - -[source,csharp,method-name="canimplicitlyconverttoid"] ----- -Id idFromInt = 1; -Id idFromLong = 2L; -Id idFromString = "hello-world"; -Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"); -Expect(1).WhenSerializing(idFromInt); -Expect(2).WhenSerializing(idFromLong); -Expect("hello-world").WhenSerializing(idFromString); -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); ----- - -=== Inferring from a Type - -Sometimes a method takes an object and we need an Id from that object to build up a path. -There is no implicit conversion from any object to Id but we can call `Id.From`. - -Imagine your codebase has the following type that we want to index into Elasticsearch - -[source,csharp,method-name="unknown"] ----- -class MyDTO -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } -} ----- - -By default NEST will try to find a property called `Id` on the class using reflection -and create a cached fast func delegate based on the properties getter - -[source,csharp,method-name="cangetidfromdocument"] ----- -var dto = new MyDTO -{ - Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), - Name = "x", - OtherName = "y" -}; - -Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); ----- - -Using the connection settings you can specify a different property that NEST should use to infer the document Id. -Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property - -[source,csharp,method-name="cangetidfromdocument"] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.Name) - ) -).Expect("x").WhenInferringIdOn(dto); ----- - -IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. - -Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance -with different inference rules - -[source,csharp,method-name="cangetidfromdocument"] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- - -=== Using the `ElasticsearchType` attribute - -Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` -to the name of the property that should be used for the document id - -[source,csharp,method-name="unknown"] ----- -[ElasticsearchType(IdProperty = nameof(Name))] -class MyOtherDTO -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } -} ----- - -Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` - -[source,csharp,method-name="cangetidfromattribute"] ----- -var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; - -Expect("x").WhenInferringIdOn(dto); ----- - -=== Using Mapping inference on `ConnectionSettings` - -This attribute *is* cached statically/globally, however an inference rule on the `ConnectionSettings` for the type will -still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance -that will infer the document id from the property `OtherName`: - -[source,csharp,method-name="cangetidfromattribute"] ----- -WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) -).Expect("y").WhenInferringIdOn(dto); ----- - diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc deleted file mode 100644 index 3fbdb39838b..00000000000 --- a/docs/asciidoc/client-concepts/high-level/inferrence/indices-paths.asciidoc +++ /dev/null @@ -1,56 +0,0 @@ -:section-number: 2.5 - -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images - -== Indices paths - -Some API's in elasticsearch take one or many index name or a special "all" marker to send the request to all the indices -In nest this is encoded using `Indices` - -Several types implicitly convert to `Indices` - -[source,csharp,method-name="implicitconversionfromstring"] ----- -Nest.Indices singleIndexFromString = "name"; -Nest.Indices multipleIndicesFromString = "name1, name2"; -Nest.Indices allFromString = "_all"; -Nest.Indices allWithOthersFromString = "_all, name2"; -singleIndexFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(1).And.Contain("name") -); -multipleIndicesFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(2).And.Contain("name2") -); -allFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() -); -allWithOthersFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() -); ----- - -to ease creating Field's from expressions there is a static Property class you can use - -[source,csharp,method-name="usingstaticpropertyfield"] ----- -var all = Nest.Indices.All; - -var many = Nest.Indices.Index("name1", "name2"); - -var manyTyped = Nest.Indices.Index().And(); - -var singleTyped = Nest.Indices.Index(); - -var singleString = Nest.Indices.Index("name1"); - -var invalidSingleString = Nest.Indices.Index("name1, name2"); ----- - diff --git a/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc deleted file mode 100644 index 421cbf92b5b..00000000000 --- a/docs/asciidoc/client-concepts/high-level/inferrence/property-inference.asciidoc +++ /dev/null @@ -1,37 +0,0 @@ -:section-number: 2.2 - -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images - -== Property Names - -Property names resolve to the last token. An example using the `.Suffix()` extension - -[source,csharp,method-name="propertynamesareresolvedtolasttokenusingsuffix"] ----- -Expression> expression = p => p.Name.Suffix("raw"); -Expect("raw").WhenSerializing(expression); ----- - -And an example using the `.ApplySuffix()` extension on lambda expressions - -[source,csharp,method-name="propertynamesareresolvedtolasttokenusingapplysuffix"] ----- -Expression> expression = p => p.Name; - -expression.AppendSuffix("raw"); - -Expect("raw").WhenSerializing(expression); ----- - -Property names cannot contain a `.` in order to prevent the potential for collision with a field that -may have {ref_current}/_multi_fields.html[`multi_fields`] - -[source,csharp,method-name="stringscontainingdotsisanexception"] ----- -Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); ----- - diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index ca07f9da95c..e78ce57d252 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -1,11 +1,10 @@ -:section-number: 3.1 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images +[[auto-mapping-properties]] == Auto mapping properties When creating a mapping (either when creating an index or via the put mapping API), @@ -238,6 +237,7 @@ var expected = new Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- +[[automapping-with-overrides]] == Automapping with overrides In most cases, you'll want to map more than just the vanilla datatypes and also provide @@ -290,6 +290,7 @@ var expected = new Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- +[[automap-with-attributes]] == Automap with attributes It is also possible to define your mappings using attributes on your POCOS. When you @@ -645,6 +646,7 @@ var expected = new Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- +[[ignoring-properties]] == Ignoring Properties Properties on a POCO can be ignored in a few ways: @@ -712,6 +714,7 @@ var settings = WithConnectionSettings(s => s settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ---- +[[mapping-recursion]] == Mapping Recursion If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive @@ -825,6 +828,7 @@ var expectedWithMaxRecursion = new Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); ---- +[[applying-conventions-through-the-visitor-pattern]] == Applying conventions through the Visitor pattern It is also possible to apply a transformation on all or specific properties. diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 5fe3ae29d35..094d2699e24 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -1,11 +1,10 @@ -:section-number: 1.1 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../images +[[connecting]] == Connecting Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. @@ -49,7 +48,7 @@ var client = new ElasticLowLevelClient(config); ---- Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. -Be sure to read more about <<../connection-pooling/connection-pooling, Connection Pooling and Cluster Failover here>>. +Be sure to read more about <>. === Configuration Options @@ -72,25 +71,19 @@ The following is a list of available connection configuration options: [source,csharp,method="availableoptions"] ---- var client = new ElasticLowLevelClient(); ----- - -`DisableAutomaticProxyDetection`: Disable automatic proxy detection. Defaults to true. -`EnableHttpCompression`: Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. -See the {ref_current}/modules-http.html[http module settings] for more info). - -By default responses are deserialized off stream to the object you tell it to. -For debugging purposes it can be very useful to keep a copy of the raw response on the result object. - -[source,csharp,method="availableoptions"] ----- var config = new ConnectionConfiguration() - .DisableAutomaticProxyDetection() -.EnableHttpCompression() -.DisableDirectStreaming() + .DisableAutomaticProxyDetection() //<1> + .EnableHttpCompression() //<2> + .DisableDirectStreaming(); //<3> var result = client.Search>(new { size = 12 }); ---- +<1> Disable automatic proxy detection. Defaults to `true`. + +<2> Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. See the {ref_current}/modules-http.html[http module settings] for more info). + +<3> By default responses are deserialized directly from the response stream to the object you tell it to. For debugging purposes, it can be very useful to keep a copy of the raw response on the result object, which is what calling this method will do. This will only have a value if the client configuration has `DisableDirectStreaming` set @@ -99,56 +92,35 @@ This will only have a value if the client configuration has `DisableDirectStream var raw = result.ResponseBodyInBytes; ---- -Please note that this only make sense if you need a mapped response and the raw response at the same time. -If you need a `string` or `byte[]` response simply call: +Please note that using `.DisableDirectStreaming` only makes sense if you need the mapped response **and** the raw response __at the same time__. +If you need a only `string` or `byte[]` response simply call [source,csharp,method="availableoptions"] ---- var stringResult = client.Search(new { }); ---- -* `GlobalQueryStringParameters`: Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. - -* `Proxy`: Sets proxy information on the connection. - -* `RequestTimeout`: -Sets the global maximum time a connection may take. -Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts -(see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). - -* `ThrowExceptions` -As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw -exceptions. - -There are three category of exceptions that may be thrown: - -. **ElasticsearchClientException**: These are known exceptions, either an exception that occurred in the request pipeline -(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could -not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property -on the response will contain the the actual error that was returned. The inner exception will always contain the -root causing exception. - -. **UnexpectedElasticsearchClientException**: These are unknown exceptions, for instance a response from Elasticsearch not -properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` -so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. - -. **Development time exceptions**: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown -when an API in the client is misused. These should not be handled as you want to know about them during development. - -* `PrettyJson`: forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well - -* `BasicAuthentication(username, password)`: sets the HTTP basic authentication credentials to specify with all requests. +other configuration options [source,csharp,method="availableoptions"] ---- config = config - .GlobalQueryStringParameters(new NameValueCollection()) -.Proxy(new Uri("http://myproxy"), "username", "pass") -.RequestTimeout(TimeSpan.FromSeconds(4)) -.ThrowExceptions() -.PrettyJson() -.BasicAuthentication("username", "password") + .GlobalQueryStringParameters(new NameValueCollection()) //<1> + .Proxy(new Uri("http://myproxy"), "username", "pass") //<2> + .RequestTimeout(TimeSpan.FromSeconds(4)) //<3> + .ThrowExceptions() //<4> + .PrettyJson() //<5> + .BasicAuthentication("username", "password"); ---- +<1> Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. + +<2> Sets proxy information on the connection. + +<3> Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). + +<4> As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to <>. + +<5> forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: @@ -161,7 +133,24 @@ var settings = new ConnectionConfiguration(uri); ...but this may become tedious when using connection pooling with multiple nodes. -=== `OnRequestCompleted` +=== Exceptions + +There are three category of exceptions that may be thrown: + +. `ElasticsearchClientException`: These are known exceptions, either an exception that occurred in the request pipeline +(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could +not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property +on the response will contain the the actual error that was returned. The inner exception will always contain the +root causing exception. + +. `UnexpectedElasticsearchClientException`: These are unknown exceptions, for instance a response from Elasticsearch not +properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` +so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. + +. Development time exceptions: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown +when an API in the client is misused. These should not be handled as you want to know about them during development. + +=== OnRequestCompleted You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. If you have complex logging needs this is a good place to add that in. @@ -199,8 +188,8 @@ var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200 var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) //<1> .DisableDirectStreaming() - .OnRequestCompleted(response => - { + .OnRequestCompleted(response => + { // log out the request if (response.RequestBodyInBytes != null) { diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 88e54543e66..b395f62bafd 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -6,6 +6,7 @@ :imagesdir: ../../images +[[lifetimes]] == Lifetimes If you are using an IOC container its always useful to know the best practices around the lifetime of your objects diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index 73752561a7c..e8c59fb26a3 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -6,13 +6,14 @@ :imagesdir: ../../images +[[post-data]] == Post data The low level client allows you to post a `string` or `byte[]` array directly. On top of this if you pass a collection of `strings` or `objects` they will be serialized in Elasticsearch's special bulk/multi format. -Even though the argument for `PostData` on the low level client takes a `PostData` -You can rely on C implicit conversion to abstract the notion of PostData completely. +Even 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 completely. You can implicitly convert from the following types * `string` @@ -35,7 +36,7 @@ var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); var fromObject = ImplicitlyConvertsFrom(@object); ---- -PostData bytes will always be set if it originated from a byte +PostData bytes will always be set if it originated from `byte[]` [source,csharp,method="implicitconversions"] ---- diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index cfd6b1b9ce2..18e7a9dc7f8 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../images +[[naming-conventions]] == Naming Conventions NEST uses the following naming conventions (with _some_ exceptions). diff --git a/docs/asciidoc/common-options.asciidoc b/docs/asciidoc/common-options.asciidoc new file mode 100644 index 00000000000..e44f0938f07 --- /dev/null +++ b/docs/asciidoc/common-options.asciidoc @@ -0,0 +1,14 @@ +:output-dir: common-options + +[[common-options]] +== Common Options + +include::{output-dir}/time-unit/time-units.asciidoc[] + +include::{output-dir}/distance-unit/distance-units.asciidoc[] + +include::{output-dir}/date-math/date-math-expressions.asciidoc[] + + + + diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index e9595eb8286..5a04dd6a7e1 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../images +[[date-math-expressions]] == Date Math Expressions The date type supports using date math expression when using it in a query/filter diff --git a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc similarity index 69% rename from docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc rename to docs/asciidoc/common-options/distance-unit/distance-units.asciidoc index f4b5efc0edc..a662dca20f1 100644 --- a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc +++ b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc @@ -2,8 +2,9 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../images +[[distance-units]] == Distance Units Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], @@ -21,10 +22,11 @@ The most straight forward way to construct a `Distance` is through its construct [source,csharp,method="constructor"] ---- var unitComposed = new Nest.Distance(25); -var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); +var unitComposedWithUnits = new Nest.Distance(25, Nest.DistanceUnit.Meters); ---- -`Distance` serializes to a string composed of a factor and distance unit +`Distance` serializes to a string composed of a factor and distance unit. +The factor is a double so always has at least one decimal place when serialized [source,csharp,method="constructor"] ---- @@ -59,28 +61,28 @@ A number of distance units are supported, from millimeters to nautical miles [source,csharp,method="usingdifferentunits"] ---- -Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); +Expect("2.0mm").WhenSerializing(new Nest.Distance(2, Nest.DistanceUnit.Millimeters)); ---- `cm` (Centimeters) [source,csharp,method="usingdifferentunits"] ---- -Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); +Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, Nest.DistanceUnit.Centimeters)); ---- `m` (Meters) [source,csharp,method="usingdifferentunits"] ---- -Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); +Expect("400.0m").WhenSerializing(new Nest.Distance(400, Nest.DistanceUnit.Meters)); ---- `km` (Kilometers) [source,csharp,method="usingdifferentunits"] ---- -Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); +Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilometers)); ---- ===== Imperial @@ -89,34 +91,34 @@ Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)) [source,csharp,method="usingdifferentunits"] ---- -Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); +Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, Nest.DistanceUnit.Inch)); ---- `ft` (Feet) [source,csharp,method="usingdifferentunits"] ---- -Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); +Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, Nest.DistanceUnit.Feet)); ---- `yd` (Yards) [source,csharp,method="usingdifferentunits"] ---- -Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); +Expect("9.0yd").WhenSerializing(new Nest.Distance(9, Nest.DistanceUnit.Yards)); ---- `mi` (Miles) [source,csharp,method="usingdifferentunits"] ---- -Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); +Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, Nest.DistanceUnit.Miles)); ---- `nmi` or `NM` (Nautical Miles) [source,csharp,method="usingdifferentunits"] ---- -Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); +Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, Nest.DistanceUnit.NauticalMiles)); ---- diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index ab1a39c0f18..6e2cf5c5e35 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../images +[[time-units]] == Time units Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified diff --git a/docs/asciidoc/connection-pooling.asciidoc b/docs/asciidoc/connection-pooling.asciidoc new file mode 100644 index 00000000000..83cf15af019 --- /dev/null +++ b/docs/asciidoc/connection-pooling.asciidoc @@ -0,0 +1,61 @@ +:output-dir:client-concepts/connection-pooling +:building-blocks: {output-dir}/building-blocks +:sniffing: {output-dir}/sniffing +:pinging: {output-dir}/pinging +:round-robin: {output-dir}/round-robin +:failover: {output-dir}/failover +:max-retries: {output-dir}/max-retries +:request-overrides: {output-dir}/request-overrides +:exceptions: {output-dir}/exceptions + +include::{building-blocks}/connection-pooling.asciidoc[] + +include::{building-blocks}/request-pipelines.asciidoc[] + +include::{building-blocks}/transports.asciidoc[] + +include::{building-blocks}/keeping-track-of-nodes.asciidoc[] + +include::{building-blocks}/date-time-providers.asciidoc[] + +include::{sniffing}/on-startup.asciidoc[] + +include::{sniffing}/on-connection-failure.asciidoc[] + +include::{sniffing}/on-stale-cluster-state.asciidoc[] + +include::{sniffing}/role-detection.asciidoc[] + +include::{pinging}/first-usage.asciidoc[] + +include::{pinging}/revival.asciidoc[] + +include::{round-robin}/round-robin.asciidoc[] + +include::{round-robin}/skip-dead-nodes.asciidoc[] + +include::{round-robin}/volatile-updates.asciidoc[] + +include::{failover}/failing-over.asciidoc[] + +include::{max-retries}/respects-max-retry.asciidoc[] + +include::{request-overrides}/disable-sniff-ping-per-request.asciidoc[] + +include::{request-overrides}/request-timeouts-overrides.asciidoc[] + +include::{request-overrides}/respects-max-retry-overrides.asciidoc[] + +include::{request-overrides}/respects-allowed-status-code.asciidoc[] + +include::{request-overrides}/respects-force-node.asciidoc[] + +include::{exceptions}/unexpected-exceptions.asciidoc[] + +include::{exceptions}/unrecoverable-exceptions.asciidoc[] + + + + + + diff --git a/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc b/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc deleted file mode 100644 index 093060e75e6..00000000000 --- a/docs/asciidoc/document/multiple/bulk/bulk-api.asciidoc +++ /dev/null @@ -1,131 +0,0 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images - -[source,javascript,method-name="expectjson"] -.Example json output ----- -[ - { - "index": { - "_type": "project", - "_id": "Durgan LLC" - } - }, - { - "name": "Koch, Collier and Mohr", - "state": "BellyUp", - "startedOn": "2015-01-01T00:00:00", - "lastActivity": "0001-01-01T00:00:00", - "leadDeveloper": { - "gender": "Male", - "id": 0, - "firstName": "Martijn", - "lastName": "Laarman" - }, - "location": { - "lat": 42.1523, - "lon": -80.321 - } - }, - { - "update": { - "_type": "project", - "_id": "Durgan LLC" - } - }, - { - "doc": { - "leadDeveloper": { - "firstName": "martijn" - } - } - }, - { - "create": { - "_type": "project", - "_id": "Durgan LLC1" - } - }, - { - "name": "Koch, Collier and Mohr", - "state": "BellyUp", - "startedOn": "2015-01-01T00:00:00", - "lastActivity": "0001-01-01T00:00:00", - "leadDeveloper": { - "gender": "Male", - "id": 0, - "firstName": "Martijn", - "lastName": "Laarman" - }, - "location": { - "lat": 42.1523, - "lon": -80.321 - } - }, - { - "delete": { - "_type": "project", - "_id": "Durgan LLC1" - } - } -] ----- - -=== Fluent DSL Example - -[source,csharp,method-name="fluent"] ----- -d => d -.Index(CallIsolatedValue) -.Index(b => b.Document(Project.Instance)) -.Update(b => b.Doc(new { leadDeveloper = new { firstName = "martijn" } }).Id(Project.Instance.Name)) -.Create(b => b.Document(Project.Instance).Id(Project.Instance.Name + "1")) -.Delete(b=>b.Id(Project.Instance.Name + "1")) ----- - -=== Object Initializer Syntax Example - -[source,csharp,method-name="initializer"] ----- -new BulkRequest(CallIsolatedValue) -{ - Operations = new List - { - new BulkIndexOperation(Project.Instance), - new BulkUpdateOperation(Project.Instance) - { - Doc = new { leadDeveloper = new { firstName = "martijn" } } - }, - new BulkCreateOperation(Project.Instance) - { - Id = Project.Instance.Name + "1" - }, - new BulkDeleteOperation(Project.Instance.Name + "1"), - } -} ----- - -=== Handling Responses - -[source,csharp,method-name="expectresponse"] ----- -response.Took.Should().BeGreaterThan(0); -response.Errors.Should().BeFalse(); -response.ItemsWithErrors.Should().NotBeNull().And.BeEmpty(); -response.Items.Should().NotBeEmpty(); -item.Index.Should().Be(CallIsolatedValue); -item.Type.Should().Be("project"); -item.Status.Should().BeGreaterThan(100); -item.Version.Should().BeGreaterThan(0); -item.Id.Should().NotBeNullOrWhiteSpace(); -item.IsValid.Should().BeTrue(); -item.Shards.Should().NotBeNull(); -item.Shards.Total.Should().BeGreaterThan(0); -item.Shards.Successful.Should().BeGreaterThan(0); -var p1 = this.Client.Source(Project.Instance.Name, p => p.Index(CallIsolatedValue)); -p1.LeadDeveloper.FirstName.Should().Be("martijn"); ----- - diff --git a/docs/asciidoc/high-level.asciidoc b/docs/asciidoc/high-level.asciidoc new file mode 100644 index 00000000000..222038941c6 --- /dev/null +++ b/docs/asciidoc/high-level.asciidoc @@ -0,0 +1,26 @@ +:output-dir: client-concepts/high-level + +[[high-level]] +== High Level + +include::{output-dir}/inference/field-inference.asciidoc[] + +include::{output-dir}/inference/property-inference.asciidoc[] + +include::{output-dir}/inference/ids-inference.asciidoc[] + +include::{output-dir}/inference/document-paths.asciidoc[] + +include::{output-dir}/inference/indices-paths.asciidoc[] + +include::{output-dir}/inference/features-inference.asciidoc[] + +include::{output-dir}/mapping/auto-map.asciidoc[] + +include::{output-dir}/covariant-hits/covariant-search-results.asciidoc[] + + + + + + diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 1143c6ad30f..0dbcfe2affd 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -1,357 +1,14 @@ -[[elasticsearch-net-reference]] +[[elasticsearch-net-reference]] = Elasticsearch.Net and NEST, the .NET Elasticsearch clients include::intro.asciidoc[] -include::client-concepts/low-level/connecting.asciidoc[] +include::client-concepts.asciidoc[] -include::client-concepts/low-level/lifetimes.asciidoc[] +include::common-options.asciidoc[] -include::client-concepts/low-level/post-data.asciidoc[] +include::query-dsl.asciidoc[] -include::client-concepts/high-level/inference/field-inference.asciidoc[] +include::aggregations.asciidoc[] -include::client-concepts/high-level/inference/property-inference.asciidoc[] - -include::client-concepts/high-level/inference/ids-inference.asciidoc[] - -include::client-concepts/high-level/inference/document-paths.asciidoc[] - -include::client-concepts/high-level/inference/indices-paths.asciidoc[] - -include::client-concepts/high-level/mapping/auto-map.asciidoc[] - -include::client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc[] - -include::client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc[] - -include::client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc[] - -include::client-concepts/connection-pooling/building-blocks/transports.asciidoc[] - -include::client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc[] - -include::client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc[] - -include::client-concepts/connection-pooling/pinging/first-usage.asciidoc[] - -include::client-concepts/connection-pooling/pinging/revival.asciidoc[] - -include::client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc[] - -include::client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc[] - -include::client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc[] - -include::client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc[] - -include::client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc[] - -include::client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc[] - -include::client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc[] - -include::client-concepts/connection-pooling/sniffing/on-startup.asciidoc[] - -include::client-concepts/connection-pooling/sniffing/role-detection.asciidoc[] - -include::aggregations/writing-aggregations.asciidoc[] - -include::aggregations/bucket/children/children-aggregation-mapping.asciidoc[] - -include::aggregations/bucket/children/children-aggregation-usage.asciidoc[] - -include::aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] - -include::aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] - -include::aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] - -include::aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] - -include::aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc[] - -include::aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc[] - -include::aggregations/bucket/global/global-aggregation-usage.asciidoc[] - -include::aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc[] - -include::aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc[] - -include::aggregations/bucket/missing/missing-aggregation-usage.asciidoc[] - -include::aggregations/bucket/nested/nested-aggregation-usage.asciidoc[] - -include::aggregations/bucket/range/range-aggregation-usage.asciidoc[] - -include::aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc[] - -include::aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc[] - -include::aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc[] - -include::aggregations/bucket/terms/terms-aggregation-usage.asciidoc[] - -include::aggregations/metric/average/average-aggregation-usage.asciidoc[] - -include::aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc[] - -include::aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc[] - -include::aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc[] - -include::aggregations/metric/max/max-aggregation-usage.asciidoc[] - -include::aggregations/metric/min/min-aggregation-usage.asciidoc[] - -include::aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc[] - -include::aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc[] - -include::aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc[] - -include::aggregations/metric/stats/stats-aggregation-usage.asciidoc[] - -include::aggregations/metric/sum/sum-aggregation-usage.asciidoc[] - -include::aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc[] - -include::aggregations/metric/value-count/value-count-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc[] - -include::aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc[] - -include::analysis/analyzers/analyzer-usage.asciidoc[] - -include::analysis/char-filters/char-filter-usage.asciidoc[] - -include::analysis/token-filters/token-filter-usage.asciidoc[] - -include::analysis/tokenizers/tokenizer-usage.asciidoc[] - -include::client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc[] - -include::client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc[] - -include::client-concepts/connection-pooling/failover/falling-over.asciidoc[] - -include::client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc[] - -include::client-concepts/connection-pooling/round-robin/round-robin.asciidoc[] - -include::client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc[] - -include::client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc[] - -include::code-standards/descriptors.asciidoc[] - -include::code-standards/elastic-client.asciidoc[] - -include::code-standards/naming-conventions.asciidoc[] - -include::code-standards/queries.asciidoc[] - -include::code-standards/serialization/properties.asciidoc[] - -include::common-options/date-math/date-math-expressions.asciidoc[] - -include::common-options/time-unit/time-units.asciidoc[] - -include::query-dsl/bool-dsl/bool-dsl.asciidoc[] - -include::query-dsl/bool-dsl/operators/and-operator-usage.asciidoc[] - -include::query-dsl/bool-dsl/operators/not-operator-usage.asciidoc[] - -include::query-dsl/bool-dsl/operators/or-operator-usage.asciidoc[] - -include::query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc[] - -include::query-dsl/compound/and/and-query-usage.asciidoc[] - -include::query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc[] - -include::query-dsl/compound/bool/bool-query-usage.asciidoc[] - -include::query-dsl/compound/boosting/boosting-query-usage.asciidoc[] - -include::query-dsl/compound/constant-score/constant-score-query-usage.asciidoc[] - -include::query-dsl/compound/dismax/dismax-query-usage.asciidoc[] - -include::query-dsl/compound/filtered/filtered-query-usage.asciidoc[] - -include::query-dsl/compound/function-score/function-score-query-usage.asciidoc[] - -include::query-dsl/compound/indices/indices-no-match-query-usage.asciidoc[] - -include::query-dsl/compound/indices/indices-query-usage.asciidoc[] - -include::query-dsl/compound/limit/limit-query-usage.asciidoc[] - -include::query-dsl/compound/not/not-query-usage.asciidoc[] - -include::query-dsl/compound/or/or-query-usage.asciidoc[] - -include::query-dsl/full-text/common-terms/common-terms-usage.asciidoc[] - -include::query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc[] - -include::query-dsl/full-text/match/match-phrase-usage.asciidoc[] - -include::query-dsl/full-text/match/match-usage.asciidoc[] - -include::query-dsl/full-text/multi-match/multi-match-usage.asciidoc[] - -include::query-dsl/full-text/query-string/query-string-usage.asciidoc[] - -include::query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc[] - -include::query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc[] - -include::query-dsl/geo/distance/distance-units.asciidoc[] - -include::query-dsl/geo/distance/geo-distance-query-usage.asciidoc[] - -include::query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc[] - -include::query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc[] - -include::query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc[] - -include::query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc[] - -include::query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc[] - -include::query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc[] - -include::query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc[] - -include::query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc[] - -include::query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc[] - -include::query-dsl/geo/shape/point/geo-point-usage.asciidoc[] - -include::query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc[] - -include::query-dsl/joining/has-child/has-child-query-usage.asciidoc[] - -include::query-dsl/joining/has-parent/has-parent-query-usage.asciidoc[] - -include::query-dsl/joining/nested/nested-query-usage.asciidoc[] - -include::query-dsl/nest-specific/raw/raw-combine-usage.asciidoc[] - -include::query-dsl/nest-specific/raw/raw-query-usage.asciidoc[] - -include::query-dsl/span/container/span-containing-query-usage.asciidoc[] - -include::query-dsl/span/first/span-first-query-usage.asciidoc[] - -include::query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc[] - -include::query-dsl/span/near/span-near-query-usage.asciidoc[] - -include::query-dsl/span/not/span-not-query-usage.asciidoc[] - -include::query-dsl/span/or/span-or-query-usage.asciidoc[] - -include::query-dsl/span/term/span-term-query-usage.asciidoc[] - -include::query-dsl/span/within/span-within-query-usage.asciidoc[] - -include::query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc[] - -include::query-dsl/specialized/script/script-query-usage.asciidoc[] - -include::query-dsl/specialized/template/template-query-usage.asciidoc[] - -include::query-dsl/term-level/exists/exists-query-usage.asciidoc[] - -include::query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc[] - -include::query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc[] - -include::query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc[] - -include::query-dsl/term-level/ids/ids-query-usage.asciidoc[] - -include::query-dsl/term-level/missing/missing-query-usage.asciidoc[] - -include::query-dsl/term-level/prefix/prefix-query-usage.asciidoc[] - -include::query-dsl/term-level/range/date-range-query-usage.asciidoc[] - -include::query-dsl/term-level/range/numeric-range-query-usage.asciidoc[] - -include::query-dsl/term-level/range/term-range-query-usage.asciidoc[] - -include::query-dsl/term-level/regexp/regexp-query-usage.asciidoc[] - -include::query-dsl/term-level/term/term-query-usage.asciidoc[] - -include::query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc[] - -include::query-dsl/term-level/terms/terms-query-usage.asciidoc[] - -include::query-dsl/term-level/type/type-query-usage.asciidoc[] - -include::query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc[] - -include::search/request/explain-usage.asciidoc[] - -include::search/request/fielddata-fields-usage.asciidoc[] - -include::search/request/fields-usage.asciidoc[] - -include::search/request/from-and-size-usage.asciidoc[] - -include::search/request/highlighting-usage.asciidoc[] - -include::search/request/index-boost-usage.asciidoc[] - -include::search/request/inner-hits-usage.asciidoc[] - -include::search/request/min-score-usage.asciidoc[] - -include::search/request/post-filter-usage.asciidoc[] - -include::search/request/query-usage.asciidoc[] - -include::search/request/script-fields-usage.asciidoc[] - -include::search/request/sort-usage.asciidoc[] - -include::search/request/source-filtering-usage.asciidoc[] - -include::search/request/suggest-usage.asciidoc[] - -include::search/suggesters/suggest-api.asciidoc[] diff --git a/docs/asciidoc/low-level.asciidoc b/docs/asciidoc/low-level.asciidoc index 5f282702bb0..4673d5969f7 100644 --- a/docs/asciidoc/low-level.asciidoc +++ b/docs/asciidoc/low-level.asciidoc @@ -1 +1,13 @@ - \ No newline at end of file +:output-dir: client-concepts/low-level + +[[low-level]] +== Low Level + +include::{output-dir}/connecting.asciidoc[] + +include::{output-dir}/lifetimes.asciidoc[] + +include::{output-dir}/post-data.asciidoc[] + + + diff --git a/docs/asciidoc/query-dsl-usage.asciidoc b/docs/asciidoc/query-dsl-usage.asciidoc new file mode 100644 index 00000000000..117510d6dfe --- /dev/null +++ b/docs/asciidoc/query-dsl-usage.asciidoc @@ -0,0 +1,2 @@ +:includes-from-dirs: + diff --git a/docs/asciidoc/query-dsl.asciidoc b/docs/asciidoc/query-dsl.asciidoc new file mode 100644 index 00000000000..b28b7c831e3 --- /dev/null +++ b/docs/asciidoc/query-dsl.asciidoc @@ -0,0 +1,12 @@ +:output-dir: query-dsl + +[[query-dsl]] +== Query DSL + +include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] + +include::query-dsl-usage.asciidoc[] + + + + diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index eea20759675..e1eb01de828 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -4,6 +4,7 @@ :imagesdir: ../../images +[[bool-queries]] == Bool Queries Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc index b23ea90500d..3bac17ea4f0 100644 --- a/docs/asciidoc/search/request/explain-usage.asciidoc +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -6,14 +6,6 @@ Enables explanation for each hit on how its score was computed. -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "explain": true -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -29,3 +21,11 @@ s => s new SearchRequest { Explain = true } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "explain": true +} +---- + diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index 9104f7cc80a..b4b1c9724df 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -4,18 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "fielddata_fields": [ - "name", - "leadDeveloper", - "startedOn" - ] -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -38,3 +26,15 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "fielddata_fields": [ + "name", + "leadDeveloper", + "startedOn" + ] +} +---- + diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index 86f70bde929..1d539368a7e 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -4,17 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "fields": [ - "name", - "startedOn" - ] -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -36,3 +25,14 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "fields": [ + "name", + "startedOn" + ] +} +---- + diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index cb0fd3e4ea4..7d71ecc7c4a 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -4,15 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "from": 10, - "size": 12 -} ----- - === Object Initializer Syntax Example [source,csharp,method="initializer"] @@ -24,6 +15,15 @@ new SearchRequest() } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "from": 10, + "size": 12 +} +---- + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index f139c394047..ac9ddb3e17d 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -4,70 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "query": { - "match": { - "name.standard": { - "query": "Upton Sons Shield Rice Rowe Roberts" - } - } - }, - "highlight": { - "pre_tags": [ - "" - ], - "post_tags": [ - "" - ], - "fields": { - "name.standard": { - "type": "plain", - "force_source": true, - "fragment_size": 150, - "number_of_fragments": 3, - "no_match_size": 150 - }, - "leadDeveloper.firstName": { - "type": "fvh", - "pre_tags": [ - "" - ], - "post_tags": [ - "" - ], - "highlight_query": { - "match": { - "leadDeveloper.firstName": { - "query": "Kurt Edgardo Naomi Dariana Justice Felton" - } - } - } - }, - "state.offsets": { - "type": "postings", - "pre_tags": [ - "" - ], - "post_tags": [ - "" - ], - "highlight_query": { - "terms": { - "state.offsets": [ - "stable", - "bellyup" - ] - } - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -174,6 +110,70 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "query": { + "match": { + "name.standard": { + "query": "Upton Sons Shield Rice Rowe Roberts" + } + } + }, + "highlight": { + "pre_tags": [ + "" + ], + "post_tags": [ + "" + ], + "fields": { + "name.standard": { + "type": "plain", + "force_source": true, + "fragment_size": 150, + "number_of_fragments": 3, + "no_match_size": 150 + }, + "leadDeveloper.firstName": { + "type": "fvh", + "pre_tags": [ + "" + ], + "post_tags": [ + "" + ], + "highlight_query": { + "match": { + "leadDeveloper.firstName": { + "query": "Kurt Edgardo Naomi Dariana Justice Felton" + } + } + } + }, + "state.offsets": { + "type": "postings", + "pre_tags": [ + "" + ], + "post_tags": [ + "" + ], + "highlight_query": { + "terms": { + "state.offsets": [ + "stable", + "bellyup" + ] + } + } + } + } + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index d0ce262c5a6..2cf494691ca 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -4,17 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "indices_boost": { - "index1": 1.4, - "index2": 1.3 - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -40,3 +29,14 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "indices_boost": { + "index1": 1.4, + "index2": 1.3 + } +} +---- + diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index aa498f9c4ba..97319f7c193 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -4,21 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "min_score": 0.5, - "query": { - "term": { - "name": { - "value": "elasticsearch" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -45,3 +30,18 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "min_score": 0.5, + "query": { + "term": { + "name": { + "value": "elasticsearch" + } + } + } +} +---- + diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index 2cf572360f8..7cd9a779acf 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -4,16 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "post_filter": { - "match_all": {} - } -} ----- - === Object Initializer Syntax Example [source,csharp,method="initializer"] @@ -24,6 +14,16 @@ new SearchRequest() } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "post_filter": { + "match_all": {} + } +} +---- + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index 22aed59b61e..49cfda4ee96 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -6,20 +6,6 @@ The query element within the search request body allows to define a query using the Query DSL. -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "query": { - "term": { - "name": { - "value": "elasticsearch" - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -44,3 +30,17 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "query": { + "term": { + "name": { + "value": "elasticsearch" + } + } + } +} +---- + diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index fe62277e700..eb2d7e5a195 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -4,28 +4,6 @@ :imagesdir: ../../images -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "script_fields": { - "test1": { - "script": { - "inline": "doc['my_field_name'].value * 2" - } - }, - "test2": { - "script": { - "inline": "doc['my_field_name'].value * factor", - "params": { - "factor": 2.0 - } - } - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -67,3 +45,25 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "script_fields": { + "test1": { + "script": { + "inline": "doc['my_field_name'].value * 2" + } + }, + "test2": { + "script": { + "inline": "doc['my_field_name'].value * factor", + "params": { + "factor": 2.0 + } + } + } + } +} +---- + diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index b18e2c361a1..1081ec94e69 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -7,75 +7,6 @@ Allows to add one or more sort on specific fields. Each sort can be reversed as well. The sort is defined on a per field level, with special field name for score to sort by score. -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "sort": [ - { - "startedOn": { - "order": "asc" - } - }, - { - "name": { - "order": "desc" - } - }, - { - "_score": { - "order": "desc" - } - }, - { - "_doc": { - "order": "asc" - } - }, - { - "lastActivity": { - "missing": "_last", - "order": "desc", - "mode": "avg", - "nested_filter": { - "match_all": {} - }, - "nested_path": "tags", - "unmapped_type": "date" - } - }, - { - "_geo_distance": { - "location": [ - { - "lat": 70.0, - "lon": -70.0 - }, - { - "lat": -12.0, - "lon": 12.0 - } - ], - "order": "asc", - "mode": "min" - } - }, - { - "_script": { - "order": "asc", - "type": "number", - "script": { - "params": { - "factor": 1.1 - }, - "inline": "doc['numberOfCommits'].value * factor" - } - } - } - ] -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -160,3 +91,72 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "sort": [ + { + "startedOn": { + "order": "asc" + } + }, + { + "name": { + "order": "desc" + } + }, + { + "_score": { + "order": "desc" + } + }, + { + "_doc": { + "order": "asc" + } + }, + { + "lastActivity": { + "missing": "_last", + "order": "desc", + "mode": "avg", + "nested_filter": { + "match_all": {} + }, + "nested_path": "tags", + "unmapped_type": "date" + } + }, + { + "_geo_distance": { + "location": [ + { + "lat": 70.0, + "lon": -70.0 + }, + { + "lat": -12.0, + "lon": 12.0 + } + ], + "order": "asc", + "mode": "min" + } + }, + { + "_script": { + "order": "asc", + "type": "number", + "script": { + "params": { + "factor": 1.1 + }, + "inline": "doc['numberOfCommits'].value * factor" + } + } + } + ] +} +---- + diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index 5f5e249338c..dec4445f23a 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -8,19 +8,6 @@ Allows to control how the _source field is returned with every hit. By default operations return the contents of the _source field unless you have used the fields parameter or if the source field is disabled. -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "_source": { - "include": [ - "name", - "startedOn" - ] - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -49,6 +36,19 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "_source": { + "include": [ + "name", + "startedOn" + ] + } +} +---- + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index 35308563d6f..23b22b5d0ad 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -25,73 +25,6 @@ payload.Name.Should().Be(Project.Instance.Name); payload.State.Should().NotBeNull(); ---- -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "suggest": { - "my-completion-suggest": { - "completion": { - "analyzer": "simple", - "context": { - "color": "red" - }, - "field": "suggest", - "fuzzy": { - "fuzziness": "AUTO", - "min_length": 1, - "prefix_length": 2, - "transpositions": true, - "unicode_aware": false - }, - "shard_size": 7, - "size": 8 - }, - "text": "Durgan LLC" - }, - "my-phrase-suggest": { - "phrase": { - "collate": { - "query": { - "inline": "{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}", - "params": { - "field_name": "title" - } - }, - "prune": true - }, - "confidence": 10.1, - "direct_generator": [ - { - "field": "description" - } - ], - "field": "name", - "gram_size": 1, - "real_word_error_likelihood": 0.5 - }, - "text": "hello world" - }, - "my-term-suggest": { - "term": { - "analyzer": "standard", - "field": "name", - "max_edits": 1, - "max_inspections": 2, - "max_term_freq": 3.0, - "min_doc_freq": 4.0, - "min_word_len": 5, - "prefix_len": 6, - "shard_size": 7, - "size": 8, - "suggest_mode": "always" - }, - "text": "hello world" - } - } -} ----- - === Fluent DSL Example [source,csharp,method="fluent"] @@ -225,3 +158,70 @@ new SearchRequest } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "suggest": { + "my-completion-suggest": { + "completion": { + "analyzer": "simple", + "context": { + "color": "red" + }, + "field": "suggest", + "fuzzy": { + "fuzziness": "AUTO", + "min_length": 1, + "prefix_length": 2, + "transpositions": true, + "unicode_aware": false + }, + "shard_size": 7, + "size": 8 + }, + "text": "Durgan LLC" + }, + "my-phrase-suggest": { + "phrase": { + "collate": { + "query": { + "inline": "{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}", + "params": { + "field_name": "title" + } + }, + "prune": true + }, + "confidence": 10.1, + "direct_generator": [ + { + "field": "description" + } + ], + "field": "name", + "gram_size": 1, + "real_word_error_likelihood": 0.5 + }, + "text": "hello world" + }, + "my-term-suggest": { + "term": { + "analyzer": "standard", + "field": "name", + "max_edits": 1, + "max_inspections": 2, + "max_term_freq": 3.0, + "min_doc_freq": 4.0, + "min_word_len": 5, + "prefix_len": 6, + "shard_size": 7, + "size": 8, + "suggest_mode": "always" + }, + "text": "hello world" + } + } +} +---- + diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index bfd0aeca2b3..7f5202c4659 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -4,75 +4,13 @@ :imagesdir: ../../images +[[suggest-api]] == Suggest API -[source,javascript,method="expectjson"] -.Example json output ----- -{ - "my-completion-suggest": { - "completion": { - "analyzer": "simple", - "context": { - "color": "red" - }, - "field": "suggest", - "fuzzy": { - "fuzziness": "AUTO", - "min_length": 1, - "prefix_length": 2, - "transpositions": true, - "unicode_aware": false - }, - "shard_size": 7, - "size": 8 - }, - "text": "Durgan LLC" - }, - "my-phrase-suggest": { - "phrase": { - "collate": { - "query": { - "inline": "{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}", - "params": { - "field_name": "title" - } - }, - "prune": true - }, - "confidence": 10.1, - "direct_generator": [ - { - "field": "description" - } - ], - "field": "name", - "gram_size": 1, - "real_word_error_likelihood": 0.5 - }, - "text": "hello world" - }, - "my-term-suggest": { - "term": { - "analyzer": "standard", - "field": "name", - "max_edits": 1, - "max_inspections": 2, - "max_term_freq": 3.0, - "min_doc_freq": 4.0, - "min_word_len": 5, - "prefix_len": 6, - "shard_size": 7, - "size": 8, - "suggest_mode": "always" - }, - "text": "hello world" - } -} ----- - === Fluent DSL Example +=== Fluent DSL Example + [source,csharp,method="fluent"] ---- s => s diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs index 2cb624ff0ed..ddd53c1b29b 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs @@ -78,11 +78,13 @@ public override void Visit(IList elements) if (_topLevel) { _topLevel = false; + Source exampleJson = null; + for (int index = 0; index < elements.Count; index++) { var element = elements[index]; var source = element as Source; - + if (source != null) { // remove empty source blocks @@ -91,6 +93,21 @@ public override void Visit(IList elements) continue; } + var method = source.Attributes.OfType().FirstOrDefault(a => a.Name == "method"); + if (method == null) + { + _newDocument.Elements.Add(element); + continue; + } + + if (method.Value == "expectjson" && + source.Attributes.Count > 1 && + source.Attributes[1].Name == "javascript") + { + exampleJson = source; + continue; + } + // if there is a section title since the last source block, don't add one var lastSourceBlock = _newDocument.Elements.LastOrDefault(e => e is Source); var lastSectionTitle = _newDocument.Elements.OfType().LastOrDefault(e => e.Level == 3); @@ -105,31 +122,37 @@ public override void Visit(IList elements) } } - var method = source.Attributes.OfType().FirstOrDefault(a => a.Name == "method"); - if (method == null) - { - _newDocument.Elements.Add(element); - continue; - } - switch (method.Value) { case "fluent": case "queryfluent": _newDocument.Elements.Add(new SectionTitle("Fluent DSL Example", 3)); + _newDocument.Elements.Add(element); break; case "initializer": case "queryinitializer": _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); + _newDocument.Elements.Add(element); + // Move the example json to after the initializer example + if (exampleJson != null) + { + _newDocument.Elements.Add(exampleJson); + exampleJson = null; + } break; case "expectresponse": _newDocument.Elements.Add(new SectionTitle("Handling Responses", 3)); + _newDocument.Elements.Add(element); + break; + default: + _newDocument.Elements.Add(element); break; } - } - - _newDocument.Elements.Add(element); + else + { + _newDocument.Elements.Add(element); + } } } @@ -152,6 +175,7 @@ public override void Visit(SectionTitle sectionTitle) { if (sectionTitle.Level != 2) { + base.Visit(sectionTitle); return; } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs index 1bf76cd336f..e69c7323998 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs @@ -2,10 +2,16 @@ namespace Nest.Litterateur.Documentation.Files { - public class ImageDocumentationFile : RawDocumentationFile + public class ImageDocumentationFile : DocumentationFile { public ImageDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } + public override void SaveToDocumentationFolder() + { + var docFileName = this.CreateDocumentationLocation(); + this.FileLocation.CopyTo(docFileName.FullName, true); + } + protected override FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs index 5750c9f009a..7d4f4555625 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs @@ -1,5 +1,10 @@ +using System; using System.IO; +using System.Linq; using System.Text.RegularExpressions; +#if !DOTNETCORE +using AsciiDoc; +#endif namespace Nest.Litterateur.Documentation.Files { @@ -11,7 +16,42 @@ public override void SaveToDocumentationFolder() { //we simply do a copy of the markdown file var docFileName = this.CreateDocumentationLocation(); + +#if !DOTNETCORE + var document = Document.Load(FileLocation.FullName); + + // check if this document has generated includes to other files + var includeAttribute = document.Attributes.FirstOrDefault(a => a.Name == "includes-from-dirs"); + + if (includeAttribute == null) + { + this.FileLocation.CopyTo(docFileName.FullName, true); + return; + } + + var thisFileUri = new Uri(docFileName.FullName); + var directories = includeAttribute.Value.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var directory in directories) + { + foreach (var file in Directory.EnumerateFiles(Path.Combine(Program.OutputDirPath, directory), "*.asciidoc", SearchOption.AllDirectories)) + { + var fileInfo = new FileInfo(file); + var referencedFileUri = new Uri(fileInfo.FullName); + var relativePath = thisFileUri.MakeRelativeUri(referencedFileUri); + var include = new Include(relativePath.OriginalString); + + document.Elements.Add(include); + } + } + + using (var visitor = new AsciiDocVisitor(docFileName.FullName)) + { + document.Accept(visitor); + } +#else this.FileLocation.CopyTo(docFileName.FullName, true); +#endif } protected override FileInfo CreateDocumentationLocation() diff --git a/src/CodeGeneration/Nest.Litterateur/LitUp.cs b/src/CodeGeneration/Nest.Litterateur/LitUp.cs index c1029e5429d..e7dea5d9ce6 100644 --- a/src/CodeGeneration/Nest.Litterateur/LitUp.cs +++ b/src/CodeGeneration/Nest.Litterateur/LitUp.cs @@ -5,10 +5,6 @@ using System.Linq; using Nest.Litterateur.Documentation.Files; -#if !DOTNETCORE -using AsciiDoc; -#endif - namespace Nest.Litterateur { public static class LitUp @@ -29,10 +25,12 @@ public static IEnumerable> Input { yield return InputFiles("*.doc.cs"); yield return InputFiles("*UsageTests.cs"); - yield return InputFiles("*.asciidoc"); yield return InputFiles("*.png"); yield return InputFiles("*.gif"); yield return InputFiles("*.jpg"); + // process asciidocs last as they may have generated + // includes to other output asciidocs + yield return InputFiles("*.asciidoc"); } } @@ -44,36 +42,10 @@ public static void Go(string[] args) } #if !DOTNETCORE - // generate the index.asciidoc file from the sections - var indexDoc = new Document - { - Title = new DocumentTitle("Elasticsearch.Net and NEST, the .NET Elasticsearch clients") - { - Attributes = - { - new Anchor("elasticsearch-net-reference", null), - } - } - }; - - indexDoc.Elements.Add(new Include("intro.asciidoc")); - - // TODO: Only the top level sections should be in the index where each top level section should link to other sections - foreach (var section in Sections.GroupBy(s => s.Key).OrderBy(s => s.Min(kv => kv.Value)).ThenBy(s => s.Key)) - { - indexDoc.Elements.Add(new Include(section.Key)); - } - - using (var visitor = new AsciiDocVisitor(Path.Combine(Program.OutputDirPath, "index.asciidoc"))) - { - indexDoc.Accept(visitor); - } - if (Debugger.IsAttached) + Console.WriteLine("Press any key to continue..."); Console.ReadKey(); #endif - - } } } \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index 72f1408c481..eafb66da935 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -30,6 +30,8 @@ public DocumentationFileWalker() : base(SyntaxWalkerDepth.StructuredTrivia) { } private bool InsideMultiLineDocumentation { get; set; } private bool InsideAutoIncludeMethodBlock { get; set; } private bool InsideFluentOrInitializerExample { get; set; } + private bool IncludeMethodBlockContainsLambda { get; set; } + private int EndLine { get; set; } public List Blocks { get; } = new List(); public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node) @@ -121,6 +123,8 @@ public override void VisitMethodDeclaration(MethodDeclarationSyntax node) _propertyOrMethodName = node.Identifier.Text; base.VisitMethodDeclaration(node); this.InsideAutoIncludeMethodBlock = false; + this.IncludeMethodBlockContainsLambda = false; + this.EndLine = 0; } public override void VisitExpressionStatement(ExpressionStatementSyntax node) @@ -128,6 +132,13 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) if (this.InsideAutoIncludeMethodBlock) { var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; + + // this lambda has already been included so skip it + //if (IncludeMethodBlockContainsLambda && this.EndLine >= line) + //{ + // return; + //} + var allchildren = node.DescendantNodesAndTokens(descendIntoTrivia: true); if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) { @@ -142,7 +153,6 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) this.Blocks.Add(new CodeBlock(code, line, Language.CSharp, _propertyOrMethodName)); } else base.VisitExpressionStatement(node); - } public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node) @@ -150,7 +160,8 @@ public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyn if (this.InsideAutoIncludeMethodBlock) { var allchildren = node.DescendantNodesAndTokens(descendIntoTrivia: true); - var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; + var linePositionSpan = node.SyntaxTree.GetLineSpan(node.Span); + var line = linePositionSpan.StartLinePosition.Line; if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) { var walker = new CodeWithDocumentationWalker(ClassDepth, line, _propertyOrMethodName); @@ -161,6 +172,13 @@ public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyn var code = node.WithoutLeadingTrivia().ToFullString(); code = code.RemoveNumberOfLeadingTabsAfterNewline(ClassDepth + 2); this.Blocks.Add(new CodeBlock(code, line, Language.CSharp, _propertyOrMethodName)); + + if (allchildren.Any(a => a.Kind() == SyntaxKind.SimpleLambdaExpression)) + { + // nested lambda inside this local declaration + this.IncludeMethodBlockContainsLambda = true; + this.EndLine = linePositionSpan.EndLinePosition.Line; + } } base.VisitLocalDeclarationStatement(node); } diff --git a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs index 4dde951763e..36cbd524c21 100644 --- a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs @@ -72,9 +72,9 @@ public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba OtherBucketKey = "other_states_of_being", Filters = new NamedFiltersContainer { - { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, - { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, - { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } + { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, + { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, + { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } }, Aggregations = new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } @@ -191,8 +191,7 @@ protected override void ExpectResponse(ISearchResponse response) singleBucket.DocCount.Should().BeGreaterThan(0); } - /** The last bucket is the _other bucket_ */ - results.Last().DocCount.Should().Be(0); + results.Last().DocCount.Should().Be(0); // <1> The last bucket is the _other bucket_ } } diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs index d727a41612f..782732d81e7 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs @@ -121,10 +121,10 @@ public void ComplexFieldNameExpressions() Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); /** - * If you are using elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow + * If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow * you to analyze a string in a number of different ways, these _"virtual"_ sub fields * do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that - * should be mapped. + * should be mapped and <> */ Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); @@ -327,7 +327,7 @@ public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) [U] public void PrecedenceIsAsExpected() { - /** here we provide an explicit rename of a property on connectionsettings using `.Rename()` + /** here we provide an explicit rename of a property on `ConnectionSettings` using `.Rename()` * and all properties that are not mapped verbatim should be uppercased */ var usingSettings = WithConnectionSettings(s => s diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index 5c8a1c3f8f9..a587b089a9e 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -8,7 +8,7 @@ namespace Tests.ClientConcepts.HighLevel.Mapping { - /** :section-number: 3.1 + /** [[auto-map]] * == Auto mapping properties * * When creating a mapping (either when creating an index or via the put mapping API), diff --git a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs index 45d60788dd9..6c3d92ee2db 100644 --- a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs @@ -15,7 +15,7 @@ namespace Tests.ClientConcepts.LowLevel { public class Connecting { - /** :section-number: 1.1 + /** * == Connecting * Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. * @@ -56,7 +56,7 @@ public void InstantiatingAConnectionPoolClient() /** * Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. - * Be sure to read more about <<../connection-pooling/connection-pooling, Connection Pooling and Cluster Failover here>>. + * Be sure to read more about <>. * * === Configuration Options * @@ -82,79 +82,29 @@ public void AvailableOptions() var client = new ElasticLowLevelClient(); var config = new ConnectionConfiguration() - .DisableAutomaticProxyDetection() - /** `DisableAutomaticProxyDetection`: Disable automatic proxy detection. Defaults to true. */ - - .EnableHttpCompression() - /** `EnableHttpCompression`: Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. - * See the {ref_current}/modules-http.html[http module settings] for more info). - */ - - .DisableDirectStreaming() - /** - * By default responses are deserialized off stream to the object you tell it to. - * For debugging purposes it can be very useful to keep a copy of the raw response on the result object. - */; + .DisableAutomaticProxyDetection() // <1> Disable automatic proxy detection. Defaults to `true`. + .EnableHttpCompression() // <2> Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. See the {ref_current}/modules-http.html[http module settings] for more info). + .DisableDirectStreaming(); // <3> By default responses are deserialized directly from the response stream to the object you tell it to. For debugging purposes, it can be very useful to keep a copy of the raw response on the result object, which is what calling this method will do. var result = client.Search>(new { size = 12 }); /** This will only have a value if the client configuration has `DisableDirectStreaming` set */ var raw = result.ResponseBodyInBytes; - /** - * Please note that this only make sense if you need a mapped response and the raw response at the same time. - * If you need a `string` or `byte[]` response simply call: + * Please note that using `.DisableDirectStreaming` only makes sense if you need the mapped response **and** the raw response __at the same time__. + * If you need a only `string` or `byte[]` response simply call */ var stringResult = client.Search(new { }); - + /** other configuration options */ config = config - .GlobalQueryStringParameters(new NameValueCollection()) - /** - * - `GlobalQueryStringParameters`: Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. - */ - - .Proxy(new Uri("http://myproxy"), "username", "pass") - /** - `Proxy`: Sets proxy information on the connection. */ - - .RequestTimeout(TimeSpan.FromSeconds(4)) - /** - `RequestTimeout`: - * Sets the global maximum time a connection may take. - * Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts - * (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). - */ - - .ThrowExceptions() - /** - `ThrowExceptions` - * As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to throw - * exceptions. - * - * There are three category of exceptions that may be thrown: - * - * . **ElasticsearchClientException**: These are known exceptions, either an exception that occurred in the request pipeline - * (such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could - * not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property - * on the response will contain the the actual error that was returned. The inner exception will always contain the - * root causing exception. - * - * . **UnexpectedElasticsearchClientException**: These are unknown exceptions, for instance a response from Elasticsearch not - * properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` - * so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. - * - * . **Development time exceptions**: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown - * when an API in the client is misused. These should not be handled as you want to know about them during development. - * - */ - - .PrettyJson() - /** - * - `PrettyJson`: forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well - */ - - .BasicAuthentication("username", "password") - /** - `BasicAuthentication(username, password)`: sets the HTTP basic authentication credentials to specify with all requests. */; - + .GlobalQueryStringParameters(new NameValueCollection()) // <1> Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. + .Proxy(new Uri("http://myproxy"), "username", "pass") // <2> Sets proxy information on the connection. + .RequestTimeout(TimeSpan.FromSeconds(4)) // <3> Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). + .ThrowExceptions() // <4> As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to <>. + .PrettyJson() // <5> forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well + .BasicAuthentication("username", "password"); // <6> sets the HTTP basic authentication credentials to specify with all requests. /** * NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: */ @@ -163,11 +113,29 @@ public void AvailableOptions() /** *...but this may become tedious when using connection pooling with multiple nodes. + * + * [[thrown-exceptions]] + * === Exceptions + * There are three category of exceptions that may be thrown: + * + * . `ElasticsearchClientException`: These are known exceptions, either an exception that occurred in the request pipeline + * (such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could + * not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property + * on the response will contain the the actual error that was returned. The inner exception will always contain the + * root causing exception. + * + * . `UnexpectedElasticsearchClientException`: These are unknown exceptions, for instance a response from Elasticsearch not + * properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` + * so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. + * + * . Development time exceptions: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown + * when an API in the client is misused. These should not be handled as you want to know about them during development. + * */ } - /** === `OnRequestCompleted` - * You can pass a callback of type `Action<IApiCallDetails>` that can eaves drop every time a response (good or bad) is created. + /** === OnRequestCompleted + * You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. * If you have complex logging needs this is a good place to add that in. */ [U] @@ -195,8 +163,8 @@ [U]public async Task UsingOnRequestCompletedForLogging() var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) // <1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` to make the actual request .DisableDirectStreaming() - .OnRequestCompleted(response => - { + .OnRequestCompleted(response => + { // log out the request if (response.RequestBodyInBytes != null) { @@ -254,6 +222,7 @@ [U]public async Task UsingOnRequestCompletedForLogging() public void ConfiguringSSL() { /** + * [[configuring-ssl]] * === Configuring SSL * SSL must be configured outside of the client using .NET's * http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] diff --git a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs index 74219c99aa2..1b9e112e7d5 100644 --- a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs @@ -40,8 +40,8 @@ public PostingData() [U] public void ImplicitConversions() { - /** Even though the argument for `PostData` on the low level client takes a `PostData` - * You can rely on C# implicit conversion to abstract the notion of PostData completely. + /** Even 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 completely. * You can implicitly convert from the following types * - `string` * - `byte[]` @@ -56,7 +56,7 @@ [U] public void ImplicitConversions() var fromListOfObject = ImplicitlyConvertsFrom(listOfObjects); var fromObject = ImplicitlyConvertsFrom(@object); - /** PostData bytes will always be set if it originated from a byte*/ + /** PostData bytes will always be set if it originated from `byte[]` */ fromByteArray.WrittenBytes.Should().BeSameAs(bytes); fromString.Type.Should().Be(PostType.LiteralString); diff --git a/src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs b/src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs similarity index 67% rename from src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs rename to src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs index 98e8d529567..3e73b56ccec 100644 --- a/src/Tests/QueryDsl/Geo/Distance/DistanceUnits.doc.cs +++ b/src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs @@ -1,8 +1,7 @@ -using Nest; -using Tests.Framework; +using Tests.Framework; using static Tests.Framework.RoundTripper; -namespace Tests.QueryDsl.Geo.Distance +namespace Tests.CommonOptions.DistanceUnit { public class DistanceUnits { @@ -21,10 +20,11 @@ public class DistanceUnits public void Constructor() { var unitComposed = new Nest.Distance(25); - var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); + var unitComposedWithUnits = new Nest.Distance(25, Nest.DistanceUnit.Meters); /** - * `Distance` serializes to a string composed of a factor and distance unit + * `Distance` serializes to a string composed of a factor and distance unit. + * The factor is a double so always has at least one decimal place when serialized */ Expect("25.0m") .WhenSerializing(unitComposed) @@ -57,47 +57,47 @@ public void UsingDifferentUnits() /** ===== Metric *`mm` (Millimeters) */ - Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); + Expect("2.0mm").WhenSerializing(new Nest.Distance(2, Nest.DistanceUnit.Millimeters)); /** *`cm` (Centimeters) */ - Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); + Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, Nest.DistanceUnit.Centimeters)); /** *`m` (Meters) */ - Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); + Expect("400.0m").WhenSerializing(new Nest.Distance(400, Nest.DistanceUnit.Meters)); /** *`km` (Kilometers) */ - Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); + Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilometers)); /** ===== Imperial *`in` (Inches) */ - Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); + Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, Nest.DistanceUnit.Inch)); /** *`ft` (Feet) */ - Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); + Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, Nest.DistanceUnit.Feet)); /** *`yd` (Yards) */ - Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); + Expect("9.0yd").WhenSerializing(new Nest.Distance(9, Nest.DistanceUnit.Yards)); /** *`mi` (Miles) */ - Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); + Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, Nest.DistanceUnit.Miles)); /** *`nmi` or `NM` (Nautical Miles) */ - Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); + Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, Nest.DistanceUnit.NauticalMiles)); } } } \ No newline at end of file diff --git a/src/Tests/aggregations-usage.asciidoc b/src/Tests/aggregations-usage.asciidoc new file mode 100644 index 00000000000..3a605010ed7 --- /dev/null +++ b/src/Tests/aggregations-usage.asciidoc @@ -0,0 +1,6 @@ +:includes-from-dirs: aggregations/bucket,aggregations/metric,aggregations/pipeline + + + + + diff --git a/src/Tests/aggregations.asciidoc b/src/Tests/aggregations.asciidoc new file mode 100644 index 00000000000..d4631347878 --- /dev/null +++ b/src/Tests/aggregations.asciidoc @@ -0,0 +1,13 @@ +:output-dir: aggregations + +[[aggregations]] += Aggregations + +include::{output-dir}/writing-aggregations.asciidoc[] + +include::aggregations-usage.asciidoc[] + + + + + diff --git a/src/Tests/client-concepts.asciidoc b/src/Tests/client-concepts.asciidoc new file mode 100644 index 00000000000..eb7ac6d6167 --- /dev/null +++ b/src/Tests/client-concepts.asciidoc @@ -0,0 +1,12 @@ +[[client-concepts]] += Client Concepts + +include::low-level.asciidoc[] + +include::high-level.asciidoc[] + +include::connection-pooling.asciidoc[] + + + + diff --git a/src/Tests/common-options.asciidoc b/src/Tests/common-options.asciidoc new file mode 100644 index 00000000000..e44f0938f07 --- /dev/null +++ b/src/Tests/common-options.asciidoc @@ -0,0 +1,14 @@ +:output-dir: common-options + +[[common-options]] +== Common Options + +include::{output-dir}/time-unit/time-units.asciidoc[] + +include::{output-dir}/distance-unit/distance-units.asciidoc[] + +include::{output-dir}/date-math/date-math-expressions.asciidoc[] + + + + diff --git a/src/Tests/connection-pooling.asciidoc b/src/Tests/connection-pooling.asciidoc new file mode 100644 index 00000000000..83cf15af019 --- /dev/null +++ b/src/Tests/connection-pooling.asciidoc @@ -0,0 +1,61 @@ +:output-dir:client-concepts/connection-pooling +:building-blocks: {output-dir}/building-blocks +:sniffing: {output-dir}/sniffing +:pinging: {output-dir}/pinging +:round-robin: {output-dir}/round-robin +:failover: {output-dir}/failover +:max-retries: {output-dir}/max-retries +:request-overrides: {output-dir}/request-overrides +:exceptions: {output-dir}/exceptions + +include::{building-blocks}/connection-pooling.asciidoc[] + +include::{building-blocks}/request-pipelines.asciidoc[] + +include::{building-blocks}/transports.asciidoc[] + +include::{building-blocks}/keeping-track-of-nodes.asciidoc[] + +include::{building-blocks}/date-time-providers.asciidoc[] + +include::{sniffing}/on-startup.asciidoc[] + +include::{sniffing}/on-connection-failure.asciidoc[] + +include::{sniffing}/on-stale-cluster-state.asciidoc[] + +include::{sniffing}/role-detection.asciidoc[] + +include::{pinging}/first-usage.asciidoc[] + +include::{pinging}/revival.asciidoc[] + +include::{round-robin}/round-robin.asciidoc[] + +include::{round-robin}/skip-dead-nodes.asciidoc[] + +include::{round-robin}/volatile-updates.asciidoc[] + +include::{failover}/failing-over.asciidoc[] + +include::{max-retries}/respects-max-retry.asciidoc[] + +include::{request-overrides}/disable-sniff-ping-per-request.asciidoc[] + +include::{request-overrides}/request-timeouts-overrides.asciidoc[] + +include::{request-overrides}/respects-max-retry-overrides.asciidoc[] + +include::{request-overrides}/respects-allowed-status-code.asciidoc[] + +include::{request-overrides}/respects-force-node.asciidoc[] + +include::{exceptions}/unexpected-exceptions.asciidoc[] + +include::{exceptions}/unrecoverable-exceptions.asciidoc[] + + + + + + diff --git a/src/Tests/high-level.asciidoc b/src/Tests/high-level.asciidoc new file mode 100644 index 00000000000..222038941c6 --- /dev/null +++ b/src/Tests/high-level.asciidoc @@ -0,0 +1,26 @@ +:output-dir: client-concepts/high-level + +[[high-level]] +== High Level + +include::{output-dir}/inference/field-inference.asciidoc[] + +include::{output-dir}/inference/property-inference.asciidoc[] + +include::{output-dir}/inference/ids-inference.asciidoc[] + +include::{output-dir}/inference/document-paths.asciidoc[] + +include::{output-dir}/inference/indices-paths.asciidoc[] + +include::{output-dir}/inference/features-inference.asciidoc[] + +include::{output-dir}/mapping/auto-map.asciidoc[] + +include::{output-dir}/covariant-hits/covariant-search-results.asciidoc[] + + + + + + diff --git a/src/Tests/index.asciidoc b/src/Tests/index.asciidoc new file mode 100644 index 00000000000..0dbcfe2affd --- /dev/null +++ b/src/Tests/index.asciidoc @@ -0,0 +1,14 @@ +[[elasticsearch-net-reference]] += Elasticsearch.Net and NEST, the .NET Elasticsearch clients + +include::intro.asciidoc[] + +include::client-concepts.asciidoc[] + +include::common-options.asciidoc[] + +include::query-dsl.asciidoc[] + +include::aggregations.asciidoc[] + + diff --git a/src/Tests/low-level.asciidoc b/src/Tests/low-level.asciidoc new file mode 100644 index 00000000000..4673d5969f7 --- /dev/null +++ b/src/Tests/low-level.asciidoc @@ -0,0 +1,13 @@ +:output-dir: client-concepts/low-level + +[[low-level]] +== Low Level + +include::{output-dir}/connecting.asciidoc[] + +include::{output-dir}/lifetimes.asciidoc[] + +include::{output-dir}/post-data.asciidoc[] + + + diff --git a/src/Tests/query-dsl-usage.asciidoc b/src/Tests/query-dsl-usage.asciidoc new file mode 100644 index 00000000000..21ee0ca3e77 --- /dev/null +++ b/src/Tests/query-dsl-usage.asciidoc @@ -0,0 +1,6 @@ +:includes-from-dirs: + + + + + diff --git a/src/Tests/query-dsl.asciidoc b/src/Tests/query-dsl.asciidoc new file mode 100644 index 00000000000..b28b7c831e3 --- /dev/null +++ b/src/Tests/query-dsl.asciidoc @@ -0,0 +1,12 @@ +:output-dir: query-dsl + +[[query-dsl]] +== Query DSL + +include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] + +include::query-dsl-usage.asciidoc[] + + + + diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index 6a1aab144cacf3d14c99c1a26bc9bda27c218936..e1cc4d94e0ce0c8f00cb69925eda46873c4522cc 100644 GIT binary patch delta 5690 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 delta 5682 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 diff --git a/src/lib/dnx451/AsciiDoc.pdb b/src/lib/dnx451/AsciiDoc.pdb index eea737332196bb64efd19533618d6932fcde5ae1..54e5e8df0ac2aaf4bb5cbb591d5a7a0008cb4564 100644 GIT binary patch delta 19915 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≥aypM?1kN@y+p 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 From 4961772db5a70c27ef1605ced5835d57f5e26c3b Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Wed, 16 Mar 2016 16:13:17 +1100 Subject: [PATCH 11/18] Don't write out lambda expressions if inside an already processed method block Generate a Section Title and anchor if an asciidoc does not have one --- .../geo-distance-aggregation-usage.asciidoc | 3 + .../geo-hash-grid-aggregation-usage.asciidoc | 3 + .../global/global-aggregation-usage.asciidoc | 3 + .../histogram-aggregation-usage.asciidoc | 3 + .../ip-range-aggregation-usage.asciidoc | 3 + .../missing-aggregation-usage.asciidoc | 3 + .../nested/nested-aggregation-usage.asciidoc | 3 + .../range/range-aggregation-usage.asciidoc | 3 + .../reverse-nested-aggregation-usage.asciidoc | 3 + .../sampler-aggregation-usage.asciidoc | 3 + ...gnificant-terms-aggregation-usage.asciidoc | 3 + .../terms/terms-aggregation-usage.asciidoc | 3 + .../average-aggregation-usage.asciidoc | 3 + .../cardinality-aggregation-usage.asciidoc | 3 + .../extended-stats-aggregation-usage.asciidoc | 3 + .../geo-bounds-aggregation-usage.asciidoc | 3 + .../metric/max/max-aggregation-usage.asciidoc | 3 + .../metric/min/min-aggregation-usage.asciidoc | 3 + ...ercentile-ranks-aggregation-usage.asciidoc | 3 + .../percentiles-aggregation-usage.asciidoc | 3 + ...scripted-metric-aggregation-usage.asciidoc | 3 + .../stats/stats-aggregation-usage.asciidoc | 3 + .../metric/sum/sum-aggregation-usage.asciidoc | 3 + .../top-hits-aggregation-usage.asciidoc | 3 + .../value-count-aggregation-usage.asciidoc | 3 + .../average-bucket-aggregation-usage.asciidoc | 3 + .../bucket-script-aggregation-usage.asciidoc | 3 + ...bucket-selector-aggregation-usage.asciidoc | 3 + .../cumulative-sum-aggregation-usage.asciidoc | 3 + .../derivative-aggregation-usage.asciidoc | 3 + .../max-bucket-aggregation-usage.asciidoc | 3 + .../min-bucket-aggregation-usage.asciidoc | 3 + ...ng-average-ewma-aggregation-usage.asciidoc | 3 + ...age-holt-linear-aggregation-usage.asciidoc | 3 + ...ge-holt-winters-aggregation-usage.asciidoc | 3 + ...-average-linear-aggregation-usage.asciidoc | 3 + ...-average-simple-aggregation-usage.asciidoc | 3 + ...al-differencing-aggregation-usage.asciidoc | 3 + .../sum-bucket-aggregation-usage.asciidoc | 3 + .../writing-aggregations.asciidoc | 6 +- .../analyzers/analyzer-usage.asciidoc | 3 + .../char-filters/char-filter-usage.asciidoc | 3 + .../token-filters/token-filter-usage.asciidoc | 3 + .../tokenizers/tokenizer-usage.asciidoc | 3 + .../round-robin/volatile-updates.asciidoc | 3 + .../sniffing/role-detection.asciidoc | 34 ---------- .../inference/document-paths.asciidoc | 2 +- .../low-level/connecting.asciidoc | 13 ---- .../code-standards/descriptors.asciidoc | 3 + .../code-standards/elastic-client.asciidoc | 3 + docs/asciidoc/code-standards/queries.asciidoc | 3 + .../serialization/properties.asciidoc | 3 + .../operators/and-operator-usage.asciidoc | 3 + .../operators/not-operator-usage.asciidoc | 3 + .../operators/or-operator-usage.asciidoc | 3 + .../unary-add-operator-usage.asciidoc | 3 + .../compound/and/and-query-usage.asciidoc | 3 + .../bool-dsl-complex-query-usage.asciidoc | 3 + .../compound/bool/bool-query-usage.asciidoc | 3 + .../boosting/boosting-query-usage.asciidoc | 3 + .../constant-score-query-usage.asciidoc | 3 + .../dismax/dismax-query-usage.asciidoc | 3 + .../filtered/filtered-query-usage.asciidoc | 3 + .../function-score-query-usage.asciidoc | 3 + .../indices-no-match-query-usage.asciidoc | 3 + .../indices/indices-query-usage.asciidoc | 3 + .../compound/limit/limit-query-usage.asciidoc | 3 + .../compound/not/not-query-usage.asciidoc | 3 + .../compound/or/or-query-usage.asciidoc | 3 + .../common-terms/common-terms-usage.asciidoc | 3 + .../match/match-phrase-prefix-usage.asciidoc | 3 + .../match/match-phrase-usage.asciidoc | 3 + .../full-text/match/match-usage.asciidoc | 3 + .../multi-match/multi-match-usage.asciidoc | 3 + .../query-string/query-string-usage.asciidoc | 3 + .../simple-query-string-usage.asciidoc | 3 + .../geo-bounding-box-query-usage.asciidoc | 3 + .../geo-distance-range-query-usage.asciidoc | 3 + .../geo-distance-query-usage.asciidoc | 3 + .../geo-hash-cell-query-usage.asciidoc | 3 + .../polygon/geo-polygon-query-usage.asciidoc | 3 + .../circle/geo-shape-circle-usage.asciidoc | 3 + .../envelope/geo-envelope-usage.asciidoc | 3 + .../geo-indexed-shape-usage.asciidoc | 3 + .../geo-line-string-usage.asciidoc | 3 + .../geo-multi-line-string-usage.asciidoc | 3 + .../geo-multi-point-usage.asciidoc | 3 + .../geo/shape/point/geo-point-usage.asciidoc | 3 + .../shape/polygon/geo-polygon-usage.asciidoc | 3 + .../has-child/has-child-query-usage.asciidoc | 3 + .../has-parent-query-usage.asciidoc | 3 + .../nested/nested-query-usage.asciidoc | 3 + .../raw/raw-combine-usage.asciidoc | 3 + .../raw/raw-query-usage.asciidoc | 3 + .../span-containing-query-usage.asciidoc | 3 + .../first/span-first-query-usage.asciidoc | 3 + .../span-multi-term-query-usage.asciidoc | 3 + .../span/near/span-near-query-usage.asciidoc | 3 + .../span/not/span-not-query-usage.asciidoc | 3 + .../span/or/span-or-query-usage.asciidoc | 3 + .../span/term/span-term-query-usage.asciidoc | 3 + .../within/span-within-query-usage.asciidoc | 3 + .../more-like-this-query-usage.asciidoc | 3 + .../script/script-query-usage.asciidoc | 3 + .../template/template-query-usage.asciidoc | 3 + .../exists/exists-query-usage.asciidoc | 3 + .../fuzzy/fuzzy-date-query-usage.asciidoc | 3 + .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 3 + .../fuzzy/fuzzy-query-usage.asciidoc | 3 + .../term-level/ids/ids-query-usage.asciidoc | 3 + .../missing/missing-query-usage.asciidoc | 3 + .../prefix/prefix-query-usage.asciidoc | 3 + .../range/date-range-query-usage.asciidoc | 3 + .../range/numeric-range-query-usage.asciidoc | 3 + .../range/term-range-query-usage.asciidoc | 3 + .../regexp/regexp-query-usage.asciidoc | 3 + .../term-level/term/term-query-usage.asciidoc | 3 + .../terms/terms-lookup-query-usage.asciidoc | 3 + .../terms/terms-query-usage.asciidoc | 3 + .../term-level/type/type-query-usage.asciidoc | 3 + .../wildcard/wildcard-query-usage.asciidoc | 3 + .../search/request/explain-usage.asciidoc | 3 + .../request/fielddata-fields-usage.asciidoc | 3 + .../search/request/fields-usage.asciidoc | 3 + .../request/from-and-size-usage.asciidoc | 3 + .../request/highlighting-usage.asciidoc | 3 + .../search/request/index-boost-usage.asciidoc | 3 + .../search/request/inner-hits-usage.asciidoc | 63 ++++++++++++++++++- .../search/request/min-score-usage.asciidoc | 3 + .../search/request/post-filter-usage.asciidoc | 3 + .../search/request/query-usage.asciidoc | 3 + .../request/script-fields-usage.asciidoc | 3 + .../search/request/sort-usage.asciidoc | 3 + .../request/source-filtering-usage.asciidoc | 3 + .../search/request/suggest-usage.asciidoc | 3 + .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 13 ++++ .../Nest.Litterateur/StringExtensions.cs | 5 ++ .../Walkers/DocumentationFileWalker.cs | 8 +-- .../Aggregations/WritingAggregations.doc.cs | 25 ++++---- .../HighLevel/Inference/DocumentPaths.doc.cs | 2 +- .../Search/Request/InnerHitsUsageTests.cs | 4 +- 141 files changed, 492 insertions(+), 73 deletions(-) diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index e3a2abca421..fcd6fb1d587 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-distance-aggregation-usage]] +== Geo Distance Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index 1746a4b57f4..5ebe2154126 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-hash-grid-aggregation-usage]] +== Geo Hash Grid Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index af9fca32e82..10ed828c857 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[global-aggregation-usage]] +== Global Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index 811f02848ff..cac00c00593 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[histogram-aggregation-usage]] +== Histogram Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index a285f11dd6a..15cd832b7bf 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[ip-range-aggregation-usage]] +== Ip Range Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index 2085e6be383..93bfd8e6217 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[missing-aggregation-usage]] +== Missing Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index dcf81fc4236..632387e0827 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[nested-aggregation-usage]] +== Nested Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index ad652cfc899..21247e68e3c 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[range-aggregation-usage]] +== Range Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index aeff4fd486e..6ee15fab424 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[reverse-nested-aggregation-usage]] +== Reverse Nested Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index b063f9e3e82..661bcdbd803 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[sampler-aggregation-usage]] +== Sampler Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 1e9ba8a8b1a..913b71a70e3 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[significant-terms-aggregation-usage]] +== Significant Terms Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index 9c20d66ea17..c8675569f3f 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[terms-aggregation-usage]] +== Terms Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index 623cbb4082d..6af103b2ce9 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[average-aggregation-usage]] +== Average Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index 7e2227852cc..7fb74f097b2 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[cardinality-aggregation-usage]] +== Cardinality Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index d4f0a201c4a..4b8ddb5a2a0 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[extended-stats-aggregation-usage]] +== Extended Stats Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index 60257c7e25d..da7b9e61d3e 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-bounds-aggregation-usage]] +== Geo Bounds Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index dd35a83a9b8..be2f31d2d28 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[max-aggregation-usage]] +== Max Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index 53089f98b17..422d99a75ca 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[min-aggregation-usage]] +== Min Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index 9adad63d89f..fec9d149234 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[percentile-ranks-aggregation-usage]] +== Percentile Ranks Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index d1dc722f9c9..941149481fb 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[percentiles-aggregation-usage]] +== Percentiles Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index 7e607bff961..f830295838a 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[scripted-metric-aggregation-usage]] +== Scripted Metric Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index 86c99cbfdd5..2b0df3707f0 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[stats-aggregation-usage]] +== Stats Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 863b662a861..954f8e54904 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[sum-aggregation-usage]] +== Sum Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index d3cc0ab59f9..1071aa4cab7 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[top-hits-aggregation-usage]] +== Top Hits Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index 02d4d2fb17b..076fe5f00dd 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[value-count-aggregation-usage]] +== Value Count Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index cef90fd5f4a..ec1e909aad5 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[average-bucket-aggregation-usage]] +== Average Bucket Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index de5023df0ec..6cfda9f6f4d 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[bucket-script-aggregation-usage]] +== Bucket Script Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 7eca62e67ac..2d85270eb70 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[bucket-selector-aggregation-usage]] +== Bucket Selector Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index 92395894887..693f23c738f 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[cumulative-sum-aggregation-usage]] +== Cumulative Sum Aggregation Usage + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index 46a8f502cb2..3ca98cbd3d4 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[derivative-aggregation-usage]] +== Derivative Aggregation Usage + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index 94588f8fbee..b4446a56076 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[max-bucket-aggregation-usage]] +== Max Bucket Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index fbaad557ee0..be90f75acf3 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[min-bucket-aggregation-usage]] +== Min Bucket Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index fe39ffa3f0e..5f68fd1904e 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[moving-average-ewma-aggregation-usage]] +== Moving Average Ewma Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index ac7610e938c..51c44a002a6 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[moving-average-holt-linear-aggregation-usage]] +== Moving Average Holt Linear Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index c4c6849b778..fbc579c8876 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[moving-average-holt-winters-aggregation-usage]] +== Moving Average Holt Winters Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index efdf2c0598e..8250cf6f639 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[moving-average-linear-aggregation-usage]] +== Moving Average Linear Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index 1512121492d..7ba1e2c5c85 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[moving-average-simple-aggregation-usage]] +== Moving Average Simple Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index 655e6ae0eec..749ea9157a4 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[serial-differencing-aggregation-usage]] +== Serial Differencing Aggregation Usage + === Handling Responses [source,csharp,method="expectresponse"] diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index 6c7ebd4ecf5..99d13bf8457 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[sum-bucket-aggregation-usage]] +== Sum Bucket Aggregation Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 57ef0422d23..63ae422f10e 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -1,13 +1,11 @@ -:section-number: 10 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../images -[[aggregations]] -== Aggregations +[[writing-aggregations]] +== Writing Aggregations Aggregations are arguably one of the most powerful features of Elasticsearch. NEST allows you to write your aggregations using diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc index 69b9a8e55fd..9d421b7b711 100644 --- a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[analyzer-usage]] +== Analyzer Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc index a5e4427f018..d6467955899 100644 --- a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[char-filter-usage]] +== Char Filter Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc index 72cce3246a5..ba1b1f42404 100644 --- a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[token-filter-usage]] +== Token Filter Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc index fcf5fc455f7..dafd6599daf 100644 --- a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[tokenizer-usage]] +== Tokenizer Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index 9cf93cb3c21..bed0b0d0902 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[volatile-updates]] +== Volatile Updates + [source,csharp,method="staticpoolwithstandsconcurrentreadandwrites"] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index 396b83f420b..1f7354d2fab 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -39,18 +39,6 @@ var audit = new Auditor(() => Framework.Cluster } }; -pool.Should().NotBeNull(); - -pool.Nodes.Should().HaveCount(10); - -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); - -pool.Should().NotBeNull(); - -pool.Nodes.Should().HaveCount(8); - -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); - await audit.TraceStartup(); ---- @@ -82,22 +70,6 @@ var audit = new Auditor(() => Framework.Cluster } }; -pool.Should().NotBeNull(); - -pool.Nodes.Should().HaveCount(10); - -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); - -pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); - -pool.Should().NotBeNull(); - -pool.Nodes.Should().HaveCount(8); - -pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); - -pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); - await audit.TraceStartup(); ---- @@ -173,12 +145,6 @@ var audit = new Auditor(() => Framework.Cluster pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); } }; -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(10); -pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); -pool.Should().NotBeNull(); -pool.Nodes.Should().HaveCount(8); -pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); await audit.TraceStartup(); ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index 7ecff879cda..9fa339d4c78 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -7,7 +7,7 @@ :imagesdir: ../../../images [[document-paths]] -== DocumentPaths +== Document Paths Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 094d2699e24..456ea35cf93 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -216,19 +216,6 @@ var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) } }); -list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); - -list.Add($"{response.HttpMethod} {response.Uri}"); - -list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); - -list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); - var client = new ElasticClient(settings); var syncResponse = client.Search(s => s diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 403c540ff9d..3aa2d250253 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../images +[[descriptors]] +== Descriptors + Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface [source,csharp,method="descriptorshavetobemarkedwithidescriptor"] diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index bbda2ad5c1a..61132f0f9a5 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../images +[[elastic-client]] +== Elastic Client + [source,csharp,method="consistentinitializerparameternames"] ---- var requestParametersNotNamedRequest = diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index c2272429279..a4522318cf6 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../images +[[queries]] +== Queries + [source,csharp,method="staticqueryexposesall"] ---- var staticProperties = from p in typeof(Query<>).GetMethods() diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index 6923fcd7ee0..baef32efdad 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[properties]] +== Properties + Our Json.NET contract resolver picks up attributes set on the interface [source,csharp,method="seesinterfaceproperties"] diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc index 666762a5b2d..6d547aceb75 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[and-operator-usage]] +== And Operator Usage + [source,csharp,method="combiningmanyusingaggregate"] ---- var lotsOfAnds = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q && Query, q => q); diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc index a23db433fe2..c3754483818 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[not-operator-usage]] +== Not Operator Usage + [source,csharp,method="combiningmanyusingaggregate"] ---- var lotsOfNots = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q || Query, q => q); diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc index a0e6642785d..8c7398f4d6c 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[or-operator-usage]] +== Or Operator Usage + [source,csharp,method="combiningmanyusingaggregate"] ---- var lotsOfOrs = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q || Query, q => q); diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc index 56c66b0128f..41537ca3090 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[unary-add-operator-usage]] +== Unary Add Operator Usage + [source,csharp,method="combiningmanyusingaggregate"] ---- var lotsOfUnaryAdds = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q && +Query, q => q); diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index 4e12c047d43..f2c0b70f55b 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[and-query-usage]] +== And Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc index b9bd6e4a5b2..69b0b1eea6d 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[bool-dsl-complex-query-usage]] +== Bool Dsl Complex Query Usage + [source,csharp,method="queryjson"] ---- new diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc index 2e862c0ef25..7aba910b4c2 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[bool-query-usage]] +== Bool Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc index 5e5b632f003..e7a5cd84fed 100644 --- a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[boosting-query-usage]] +== Boosting Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc index be285d03cd1..0978f647ad3 100644 --- a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[constant-score-query-usage]] +== Constant Score Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc index 8367b124d5c..c5c524c5efa 100644 --- a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[dismax-query-usage]] +== Dismax Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc index 2316168c8f2..6d4bff90e40 100644 --- a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[filtered-query-usage]] +== Filtered Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc index 62995ef5d37..b9c76cf5599 100644 --- a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[function-score-query-usage]] +== Function Score Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc index 4d394c91250..0b9398cb5d3 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[indices-no-match-query-usage]] +== Indices No Match Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc index bf06e671e27..65a64134ba8 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[indices-query-usage]] +== Indices Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc index 068c28c9e5a..b7191261fea 100644 --- a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[limit-query-usage]] +== Limit Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc index f98832a1ccb..ec0b2c6808a 100644 --- a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[not-query-usage]] +== Not Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc index 06b1dbbf33d..c459f7eb9c3 100644 --- a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[or-query-usage]] +== Or Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc index 355154730ec..83e82562840 100644 --- a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[common-terms-usage]] +== Common Terms Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc index f3ecf1e3413..87a117e6d21 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[match-phrase-prefix-usage]] +== Match Phrase Prefix Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc index 4417d715009..737199532e9 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[match-phrase-usage]] +== Match Phrase Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc index 5bfcba2737b..ae33e0db0b2 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[match-usage]] +== Match Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index 58a5ac6be80..59a816ede6c 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[multi-match-usage]] +== Multi Match Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc index 0922949d9c4..9e013f3a112 100644 --- a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[query-string-usage]] +== Query String Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc index e4ac092d9ce..0fb8a28ed17 100644 --- a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[simple-query-string-usage]] +== Simple Query String Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc index 78fab700a05..c7a4deeaafb 100644 --- a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-bounding-box-query-usage]] +== Geo Bounding Box Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc index 63a33838b55..deae85e0cbe 100644 --- a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-distance-range-query-usage]] +== Geo Distance Range Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc index ac15514acd4..04d7119bf77 100644 --- a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-distance-query-usage]] +== Geo Distance Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc index b08cd786607..e34509d09e9 100644 --- a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-hash-cell-query-usage]] +== Geo Hash Cell Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc index f44402f8008..8952ee70180 100644 --- a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[geo-polygon-query-usage]] +== Geo Polygon Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc index 44ef9c04e76..889412e214e 100644 --- a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-shape-circle-usage]] +== Geo Shape Circle Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc index ad56fd20b61..f467a22e227 100644 --- a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-envelope-usage]] +== Geo Envelope Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc index c4db674d238..e93b248f02f 100644 --- a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-indexed-shape-usage]] +== Geo Indexed Shape Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc index d50e8a09890..013c253a4de 100644 --- a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-line-string-usage]] +== Geo Line String Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc index 0bd741f1eaf..2cbdb4d990b 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-multi-line-string-usage]] +== Geo Multi Line String Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc index 7221a432c1d..9ebf1bda6e5 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-multi-point-usage]] +== Geo Multi Point Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc index 5a868d095ef..f6cc8ceb2bb 100644 --- a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-point-usage]] +== Geo Point Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc index 502ff1543fb..2cbac5505f7 100644 --- a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../../images +[[geo-polygon-usage]] +== Geo Polygon Usage + === Object Initializer Syntax Example [source,csharp,method="queryinitializer"] diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc index ef6c4a1e153..8ed18e8cef5 100644 --- a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[has-child-query-usage]] +== Has Child Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc index 851a772c9b8..e2b6a770993 100644 --- a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[has-parent-query-usage]] +== Has Parent Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc index f1a5a6c09ab..dd0b7a4907b 100644 --- a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[nested-query-usage]] +== Nested Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc index a503969d916..dd98e17984f 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[raw-combine-usage]] +== Raw Combine Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc index b6efae1f799..f5dc61e59d4 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[raw-query-usage]] +== Raw Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc index 50300f582a2..12cc776f2bf 100644 --- a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-containing-query-usage]] +== Span Containing Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc index 54c202ce107..e5bf822ef52 100644 --- a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-first-query-usage]] +== Span First Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc index eeddaabb649..b2085cc19df 100644 --- a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-multi-term-query-usage]] +== Span Multi Term Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc index 2befab4cd46..0583bdb4375 100644 --- a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-near-query-usage]] +== Span Near Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc index 5f70aa41eb2..4acc6a8feac 100644 --- a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-not-query-usage]] +== Span Not Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc index 69e055081db..3445a54c792 100644 --- a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-or-query-usage]] +== Span Or Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc index bfa964de25b..a481650186c 100644 --- a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-term-query-usage]] +== Span Term Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc index 111a48780bc..e869871974c 100644 --- a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[span-within-query-usage]] +== Span Within Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc index 0bd3e4835d6..87c2f8624a4 100644 --- a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[more-like-this-query-usage]] +== More Like This Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc index 654c900579d..438d1b9b90e 100644 --- a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[script-query-usage]] +== Script Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc index 4a7d1bce749..8fd8ac63ad1 100644 --- a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[template-query-usage]] +== Template Query Usage + [source,csharp,method="queryjson"] ---- new diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc index b583946f91c..be7705f60dc 100644 --- a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[exists-query-usage]] +== Exists Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc index dea6f12b329..446b36e46d9 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[fuzzy-date-query-usage]] +== Fuzzy Date Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc index ea5f3760e86..1a6b6055e29 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[fuzzy-numeric-query-usage]] +== Fuzzy Numeric Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc index 0c163dfda1a..b256c74e907 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[fuzzy-query-usage]] +== Fuzzy Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc index e6c35860e59..52917ef39dd 100644 --- a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[ids-query-usage]] +== Ids Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc index b2a986dc887..1157e54b450 100644 --- a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[missing-query-usage]] +== Missing Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc index 1eb44e7166d..23dfbccfa36 100644 --- a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[prefix-query-usage]] +== Prefix Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc index 695ceb388c7..e6d9f43444a 100644 --- a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[date-range-query-usage]] +== Date Range Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc index 4f34c36c316..fcfde48504c 100644 --- a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[numeric-range-query-usage]] +== Numeric Range Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc index b855877009c..91a916a4c05 100644 --- a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[term-range-query-usage]] +== Term Range Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc index cfd4962e491..8f138d1115d 100644 --- a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[regexp-query-usage]] +== Regexp Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc index 40868d0848f..fe3f3532793 100644 --- a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[term-query-usage]] +== Term Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc index 5caa1d8d51a..1ea0d3eb828 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[terms-lookup-query-usage]] +== Terms Lookup Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc index 1f8fa5eddbf..58ae3274329 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[terms-query-usage]] +== Terms Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc index 87fbedfc0fd..45e4d940b9e 100644 --- a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[type-query-usage]] +== Type Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc index 6bc1df39f96..19e868b221f 100644 --- a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../../images +[[wildcard-query-usage]] +== Wildcard Query Usage + [source,javascript,method="queryjson"] .Example json output ---- diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc index 3bac17ea4f0..fda74d97064 100644 --- a/docs/asciidoc/search/request/explain-usage.asciidoc +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[explain-usage]] +== Explain Usage + Enables explanation for each hit on how its score was computed. === Fluent DSL Example diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index b4b1c9724df..ac86e8e4ade 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[fielddata-fields-usage]] +== Fielddata Fields Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index 1d539368a7e..86017fb63ed 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[fields-usage]] +== Fields Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index 7d71ecc7c4a..0dddbb6382b 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[from-and-size-usage]] +== From And Size Usage + === Object Initializer Syntax Example [source,csharp,method="initializer"] diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index ac9ddb3e17d..60eb6d1f657 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[highlighting-usage]] +== Highlighting Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index 2cf494691ca..e3a4db4bb26 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[index-boost-usage]] +== Index Boost Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc index 9ddaed19556..589466aa280 100644 --- a/docs/asciidoc/search/request/inner-hits-usage.asciidoc +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[inner-hits-usage]] +== Inner Hits Usage + [source,csharp,method="unknown"] ---- public interface IRoyal @@ -51,7 +54,6 @@ var kings = King.Generator.Generate(2) k.Foes = King.Generator.Generate(2).ToList(); return k; }); -k.Foes = King.Generator.Generate(2).ToList(); var bulk = new BulkDescriptor(); IndexAll(bulk, () => kings, indexChildren: king => IndexAll(bulk, () => Prince.Generator.Generate(2), king.Name, prince => @@ -110,6 +112,32 @@ InnerHits = new NamedInnerHits } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "inner_hits": { + "earls": { + "type": { + "earl": { + "fielddata_fields": [ + "name" + ], + "inner_hits": { + "barons": { + "type": { + "baron": {} + } + } + }, + "size": 5 + } + } + } + } +} +---- + === Fluent DSL Example [source,csharp,method="fluent"] @@ -148,3 +176,36 @@ Query = new HasChildQuery } ---- +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "query": { + "bool": { + "should": [ + { + "has_child": { + "type": "prince", + "query": { + "match_all": {} + }, + "inner_hits": { + "name": "princes" + } + } + }, + { + "nested": { + "query": { + "match_all": {} + }, + "path": "foes", + "inner_hits": {} + } + } + ] + } + } +} +---- + diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index 97319f7c193..f2a20a81f42 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[min-score-usage]] +== Min Score Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index 7cd9a779acf..03746532e91 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[post-filter-usage]] +== Post Filter Usage + === Object Initializer Syntax Example [source,csharp,method="initializer"] diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index 49cfda4ee96..97cc33258f5 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[query-usage]] +== Query Usage + The query element within the search request body allows to define a query using the Query DSL. === Fluent DSL Example diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index eb2d7e5a195..951bd716773 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[script-fields-usage]] +== Script Fields Usage + === Fluent DSL Example [source,csharp,method="fluent"] diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 1081ec94e69..3bdae6f0d0f 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[sort-usage]] +== Sort Usage + Allows to add one or more sort on specific fields. Each sort can be reversed as well. The sort is defined on a per field level, with special field name for score to sort by score. diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index dec4445f23a..765af845398 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[source-filtering-usage]] +== Source Filtering Usage + Allows to control how the _source field is returned with every hit. By default operations return the contents of the _source field unless you have used the fields parameter or if the source field is disabled. diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index 23b22b5d0ad..915797c7a3f 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -4,6 +4,9 @@ :imagesdir: ../../images +[[suggest-usage]] +== Suggest Usage + Allows to add one or more sort on specific fields. Each sort can be reversed as well. The sort is defined on a per field level, with special field name for score to sort by score. diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs index ddd53c1b29b..e070f7ba3a5 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs @@ -70,6 +70,19 @@ public override void Visit(Document document) _newDocument.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}")); } + // see if the document has some kind of top level title. + if (document.Title == null && + document.Elements.Count > 0 && + !document.Elements.OfType().Any(s => s.Level == 2)) + { + var id = Path.GetFileNameWithoutExtension(_destination.Name); + var title = id.LowercaseHyphenToPascal(); + var sectionTitle = new SectionTitle(title, 2); + sectionTitle.Attributes.Add(new Anchor(id)); + + _newDocument.Elements.Add(sectionTitle); + } + base.Visit(document); } diff --git a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs index 16c067dd0b5..a604b9488f4 100644 --- a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs @@ -24,6 +24,11 @@ public static string PascalToHyphen(this string input) , @"[-\s]", "-").TrimEnd('-').ToLower(); } + public static string LowercaseHyphenToPascal(this string lowercaseHyphenatedInput) + { + return Regex.Replace(lowercaseHyphenatedInput.Replace("-", " "), @"\b([a-z])", m => m.Captures[0].Value.ToUpper()); + } + public static string TrimEnd(this string input, string trim) { if (string.IsNullOrEmpty(input)) return string.Empty; diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index eafb66da935..959e08c55f1 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -134,10 +134,10 @@ public override void VisitExpressionStatement(ExpressionStatementSyntax node) var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; // this lambda has already been included so skip it - //if (IncludeMethodBlockContainsLambda && this.EndLine >= line) - //{ - // return; - //} + if (IncludeMethodBlockContainsLambda && this.EndLine >= line) + { + return; + } var allchildren = node.DescendantNodesAndTokens(descendIntoTrivia: true); if (allchildren.Any(a => a.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia)) diff --git a/src/Tests/Aggregations/WritingAggregations.doc.cs b/src/Tests/Aggregations/WritingAggregations.doc.cs index aced4b4f8de..550a07e985c 100644 --- a/src/Tests/Aggregations/WritingAggregations.doc.cs +++ b/src/Tests/Aggregations/WritingAggregations.doc.cs @@ -8,19 +8,18 @@ namespace Tests.Aggregations { - /** :section-number: 10 - * == Aggregations - * - * Aggregations are arguably one of the most powerful features of Elasticsearch. - * NEST allows you to write your aggregations using - * - * - a strict fluent DSL - * - a verbatim object initializer syntax that maps verbatim to the elasticsearch API - * - a more terse object initializer aggregation DSL - * - * Three different ways, yikes that's a lot to take in! Lets go over them one by one and explain when you might - * want to use each. - */ + /** == Writing Aggregations + * + * Aggregations are arguably one of the most powerful features of Elasticsearch. + * NEST allows you to write your aggregations using + * + * - a strict fluent DSL + * - a verbatim object initializer syntax that maps verbatim to the elasticsearch API + * - a more terse object initializer aggregation DSL + * + * Three different ways, yikes that's a lot to take in! Lets go over them one by one and explain when you might + * want to use each. + */ public class Usage : UsageTestBase, SearchRequest> { /** diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs index c6dd613f02c..69d0bad2b2f 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs @@ -8,7 +8,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence public class DocumentPaths { /** :section-number: 2.4 - * == DocumentPaths + * == Document Paths * * Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes * and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path diff --git a/src/Tests/Search/Request/InnerHitsUsageTests.cs b/src/Tests/Search/Request/InnerHitsUsageTests.cs index b160ee41022..6f65982ad4a 100644 --- a/src/Tests/Search/Request/InnerHitsUsageTests.cs +++ b/src/Tests/Search/Request/InnerHitsUsageTests.cs @@ -146,7 +146,7 @@ public GlobalInnerHitsApiTests(OwnIndexCluster cluster, EndpointUsage usage) : b private static IndexName IndexName { get; } = RandomString(); protected override IndexName Index => GlobalInnerHitsApiTests.IndexName; - protected override object ExpectJson { get; } = new + protected override object ExpectJson => new { inner_hits = new { @@ -238,7 +238,7 @@ public QueryInnerHitsApiTests(OwnIndexCluster cluster, EndpointUsage usage) : ba private static IndexName IndexName { get; } = RandomString(); protected override IndexName Index => QueryInnerHitsApiTests.IndexName; - protected override object ExpectJson { get; } = new + protected override object ExpectJson => new { query = new { From 63361069e608527b846466b2a4bbb79c7456f5a1 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Sun, 20 Mar 2016 13:15:35 +1100 Subject: [PATCH 12/18] Create structure that passes doc generation process remove named attribute method - the doc generation process expects a linenumbering attribute in index 2 of a source block's attributes. --- docs/asciidoc/aggregations.asciidoc | 12 +-- .../children-aggregation-mapping.asciidoc | 2 +- .../children-aggregation-usage.asciidoc | 6 +- .../date-histogram-aggregation-usage.asciidoc | 50 ++++++++++-- .../date-range-aggregation-usage.asciidoc | 53 +++++++++--- .../filter/filter-aggregation-usage.asciidoc | 60 +++++++++++--- .../filters-aggregation-usage.asciidoc | 35 ++++---- .../geo-distance-aggregation-usage.asciidoc | 8 +- .../geo-hash-grid-aggregation-usage.asciidoc | 8 +- .../global/global-aggregation-usage.asciidoc | 8 +- .../histogram-aggregation-usage.asciidoc | 8 +- .../ip-range-aggregation-usage.asciidoc | 8 +- .../missing-aggregation-usage.asciidoc | 8 +- .../nested/nested-aggregation-usage.asciidoc | 8 +- .../range/range-aggregation-usage.asciidoc | 8 +- .../reverse-nested-aggregation-usage.asciidoc | 8 +- .../sampler-aggregation-usage.asciidoc | 8 +- ...gnificant-terms-aggregation-usage.asciidoc | 8 +- .../terms/terms-aggregation-usage.asciidoc | 8 +- .../average-aggregation-usage.asciidoc | 8 +- .../cardinality-aggregation-usage.asciidoc | 8 +- .../extended-stats-aggregation-usage.asciidoc | 8 +- .../geo-bounds-aggregation-usage.asciidoc | 8 +- .../metric/max/max-aggregation-usage.asciidoc | 8 +- .../metric/min/min-aggregation-usage.asciidoc | 8 +- ...ercentile-ranks-aggregation-usage.asciidoc | 8 +- .../percentiles-aggregation-usage.asciidoc | 8 +- ...scripted-metric-aggregation-usage.asciidoc | 8 +- .../stats/stats-aggregation-usage.asciidoc | 8 +- .../metric/sum/sum-aggregation-usage.asciidoc | 8 +- .../top-hits-aggregation-usage.asciidoc | 8 +- .../value-count-aggregation-usage.asciidoc | 8 +- .../average-bucket-aggregation-usage.asciidoc | 8 +- .../bucket-script-aggregation-usage.asciidoc | 8 +- ...bucket-selector-aggregation-usage.asciidoc | 8 +- .../cumulative-sum-aggregation-usage.asciidoc | 8 +- .../derivative-aggregation-usage.asciidoc | 8 +- .../max-bucket-aggregation-usage.asciidoc | 8 +- .../min-bucket-aggregation-usage.asciidoc | 8 +- ...ng-average-ewma-aggregation-usage.asciidoc | 8 +- ...age-holt-linear-aggregation-usage.asciidoc | 8 +- ...ge-holt-winters-aggregation-usage.asciidoc | 8 +- ...-average-linear-aggregation-usage.asciidoc | 8 +- ...-average-simple-aggregation-usage.asciidoc | 8 +- ...al-differencing-aggregation-usage.asciidoc | 8 +- .../sum-bucket-aggregation-usage.asciidoc | 8 +- .../writing-aggregations.asciidoc | 8 +- .../analyzers/analyzer-usage.asciidoc | 6 +- .../char-filters/char-filter-usage.asciidoc | 6 +- .../token-filters/token-filter-usage.asciidoc | 6 +- .../tokenizers/tokenizer-usage.asciidoc | 6 +- .../connection-pooling.asciidoc | 49 +++++------ .../date-time-providers.asciidoc | 10 +-- .../keeping-track-of-nodes.asciidoc | 20 ++--- .../request-pipelines.asciidoc | 42 +++++----- .../building-blocks/transports.asciidoc | 6 +- .../exceptions/unexpected-exceptions.asciidoc | 8 +- .../unrecoverable-exceptions.asciidoc | 8 +- .../failover/falling-over.asciidoc | 8 +- .../max-retries/respects-max-retry.asciidoc | 16 ++-- .../pinging/first-usage.asciidoc | 10 +-- .../pinging/revival.asciidoc | 2 +- .../disable-sniff-ping-per-request.asciidoc | 8 +- .../request-timeouts-overrides.asciidoc | 8 +- .../respects-allowed-status-code.asciidoc | 2 +- .../respects-force-node.asciidoc | 2 +- .../respects-max-retry-overrides.asciidoc | 6 +- .../round-robin/round-robin.asciidoc | 8 +- .../round-robin/skip-dead-nodes.asciidoc | 18 ++--- .../round-robin/volatile-updates.asciidoc | 6 +- .../sniffing/on-connection-failure.asciidoc | 8 +- .../sniffing/on-stale-cluster-state.asciidoc | 10 +-- .../sniffing/on-startup.asciidoc | 12 +-- .../sniffing/role-detection.asciidoc | 16 ++-- .../covariant-search-results.asciidoc | 38 +++++---- .../inference/document-paths.asciidoc | 22 +++-- .../inference/field-inference.asciidoc | 76 +++++++++--------- .../inference/ids-inference.asciidoc | 18 ++--- .../inference/indices-paths.asciidoc | 6 +- .../inference/property-inference.asciidoc | 8 +- .../high-level/mapping/auto-map.asciidoc | 44 +++++----- .../low-level/connecting.asciidoc | 31 +++---- .../low-level/lifetimes.asciidoc | 8 +- .../low-level/post-data.asciidoc | 37 +++++---- .../code-standards/descriptors.asciidoc | 4 +- .../code-standards/elastic-client.asciidoc | 12 +-- .../naming-conventions.asciidoc | 10 +-- docs/asciidoc/code-standards/queries.asciidoc | 8 +- .../serialization/properties.asciidoc | 2 +- docs/asciidoc/common-options.asciidoc | 7 +- .../date-math/date-math-expressions.asciidoc | 20 ++--- .../distance-unit/distance-units.asciidoc | 24 +++--- .../time-unit/time-units.asciidoc | 16 ++-- docs/asciidoc/connection-pooling.asciidoc | 2 +- docs/asciidoc/high-level.asciidoc | 13 +++ docs/asciidoc/index.asciidoc | 2 +- docs/asciidoc/intro.asciidoc | 13 +-- docs/asciidoc/low-level.asciidoc | 12 +++ docs/asciidoc/query-dsl.asciidoc | 7 +- .../query-dsl/bool-dsl/bool-dsl.asciidoc | 12 +-- .../operators/and-operator-usage.asciidoc | 10 +-- .../operators/not-operator-usage.asciidoc | 10 +-- .../operators/or-operator-usage.asciidoc | 10 +-- .../unary-add-operator-usage.asciidoc | 12 +-- .../compound/and/and-query-usage.asciidoc | 4 +- .../bool-dsl-complex-query-usage.asciidoc | 8 +- .../compound/bool/bool-query-usage.asciidoc | 4 +- .../boosting/boosting-query-usage.asciidoc | 4 +- .../constant-score-query-usage.asciidoc | 4 +- .../dismax/dismax-query-usage.asciidoc | 4 +- .../filtered/filtered-query-usage.asciidoc | 4 +- .../function-score-query-usage.asciidoc | 4 +- .../indices-no-match-query-usage.asciidoc | 4 +- .../indices/indices-query-usage.asciidoc | 4 +- .../compound/limit/limit-query-usage.asciidoc | 4 +- .../compound/not/not-query-usage.asciidoc | 4 +- .../compound/or/or-query-usage.asciidoc | 4 +- .../common-terms/common-terms-usage.asciidoc | 4 +- .../match/match-phrase-prefix-usage.asciidoc | 4 +- .../match/match-phrase-usage.asciidoc | 4 +- .../full-text/match/match-usage.asciidoc | 4 +- .../multi-match/multi-match-usage.asciidoc | 4 +- .../query-string/query-string-usage.asciidoc | 4 +- .../simple-query-string-usage.asciidoc | 4 +- .../geo-bounding-box-query-usage.asciidoc | 4 +- .../geo-distance-range-query-usage.asciidoc | 4 +- .../geo-distance-query-usage.asciidoc | 4 +- .../geo-hash-cell-query-usage.asciidoc | 4 +- .../polygon/geo-polygon-query-usage.asciidoc | 4 +- .../circle/geo-shape-circle-usage.asciidoc | 2 +- .../envelope/geo-envelope-usage.asciidoc | 2 +- .../geo-indexed-shape-usage.asciidoc | 4 +- .../geo-line-string-usage.asciidoc | 2 +- .../geo-multi-line-string-usage.asciidoc | 2 +- .../geo-multi-point-usage.asciidoc | 2 +- .../geo/shape/point/geo-point-usage.asciidoc | 2 +- .../shape/polygon/geo-polygon-usage.asciidoc | 2 +- .../has-child/has-child-query-usage.asciidoc | 4 +- .../has-parent-query-usage.asciidoc | 4 +- .../nested/nested-query-usage.asciidoc | 4 +- .../raw/raw-combine-usage.asciidoc | 4 +- .../raw/raw-query-usage.asciidoc | 4 +- .../span-containing-query-usage.asciidoc | 4 +- .../first/span-first-query-usage.asciidoc | 4 +- .../span-multi-term-query-usage.asciidoc | 4 +- .../span/near/span-near-query-usage.asciidoc | 4 +- .../span/not/span-not-query-usage.asciidoc | 4 +- .../span/or/span-or-query-usage.asciidoc | 4 +- .../span/term/span-term-query-usage.asciidoc | 4 +- .../within/span-within-query-usage.asciidoc | 4 +- .../more-like-this-query-usage.asciidoc | 4 +- .../script/script-query-usage.asciidoc | 4 +- .../template/template-query-usage.asciidoc | 4 +- .../exists/exists-query-usage.asciidoc | 4 +- .../fuzzy/fuzzy-date-query-usage.asciidoc | 4 +- .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 4 +- .../fuzzy/fuzzy-query-usage.asciidoc | 4 +- .../term-level/ids/ids-query-usage.asciidoc | 4 +- .../missing/missing-query-usage.asciidoc | 4 +- .../prefix/prefix-query-usage.asciidoc | 4 +- .../range/date-range-query-usage.asciidoc | 4 +- .../range/numeric-range-query-usage.asciidoc | 4 +- .../range/term-range-query-usage.asciidoc | 4 +- .../regexp/regexp-query-usage.asciidoc | 4 +- .../term-level/term/term-query-usage.asciidoc | 4 +- .../terms/terms-lookup-query-usage.asciidoc | 4 +- .../terms/terms-query-usage.asciidoc | 4 +- .../term-level/type/type-query-usage.asciidoc | 4 +- .../wildcard/wildcard-query-usage.asciidoc | 4 +- .../search/request/explain-usage.asciidoc | 6 +- .../request/fielddata-fields-usage.asciidoc | 6 +- .../search/request/fields-usage.asciidoc | 6 +- .../request/from-and-size-usage.asciidoc | 6 +- .../request/highlighting-usage.asciidoc | 8 +- .../search/request/index-boost-usage.asciidoc | 6 +- .../search/request/inner-hits-usage.asciidoc | 18 ++--- .../search/request/min-score-usage.asciidoc | 6 +- .../search/request/post-filter-usage.asciidoc | 6 +- .../search/request/query-usage.asciidoc | 6 +- .../request/script-fields-usage.asciidoc | 6 +- .../search/request/sort-usage.asciidoc | 6 +- .../request/source-filtering-usage.asciidoc | 18 ++--- .../search/request/suggest-usage.asciidoc | 8 +- .../search/suggesters/suggest-api.asciidoc | 6 +- .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 8 ++ .../DateHistogramAggregationUsageTests.cs | 2 - .../DateRangeAggregationUsageTests.cs | 7 +- .../Filter/FilterAggregationUsageTests.cs | 11 +-- .../Filters/FiltersAggregationUsageTests.cs | 9 ++- .../BuildingBlocks/ConnectionPooling.Doc.cs | 19 +++-- .../BuildingBlocks/RequestPipelines.doc.cs | 2 +- .../MaxRetries/RespectsMaxRetry.doc.cs | 3 +- .../CovariantSearchResults.doc.cs | 3 +- .../HighLevel/Inference/DocumentPaths.doc.cs | 3 +- .../HighLevel/Inference/FeaturesInference.cs | 3 +- .../HighLevel/Inference/FieldInference.doc.cs | 5 +- .../HighLevel/Inference/IdsInference.doc.cs | 3 +- .../HighLevel/Inference/IndicesPaths.doc.cs | 3 +- .../Inference/PropertyInference.doc.cs | 3 +- .../HighLevel/Mapping/AutoMap.doc.cs | 3 +- .../ClientConcepts/LowLevel/Connecting.doc.cs | 3 +- .../ClientConcepts/LowLevel/Lifetimes.doc.cs | 3 +- .../ClientConcepts/LowLevel/PostData.doc.cs | 12 ++- src/Tests/aggregations.asciidoc | 12 +-- src/Tests/common-options.asciidoc | 7 +- src/Tests/connection-pooling.asciidoc | 2 +- src/Tests/high-level.asciidoc | 13 +++ src/Tests/index.asciidoc | 2 +- src/Tests/intro.asciidoc | 13 +-- src/Tests/low-level.asciidoc | 12 +++ src/Tests/query-dsl.asciidoc | 7 +- src/lib/dnx451/AsciiDoc.dll | Bin 69632 -> 70656 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 241152 -> 245248 bytes 213 files changed, 1023 insertions(+), 857 deletions(-) diff --git a/docs/asciidoc/aggregations.asciidoc b/docs/asciidoc/aggregations.asciidoc index d4631347878..38c5c57c03a 100644 --- a/docs/asciidoc/aggregations.asciidoc +++ b/docs/asciidoc/aggregations.asciidoc @@ -3,11 +3,11 @@ [[aggregations]] = Aggregations -include::{output-dir}/writing-aggregations.asciidoc[] - -include::aggregations-usage.asciidoc[] - - - +[partintro] +-- +Something about aggregations +-- +include::{output-dir}/writing-aggregations.asciidoc[] +include::aggregations-usage.asciidoc[] \ No newline at end of file diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index 4578212341b..71a0641511b 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -12,7 +12,7 @@ To use the child aggregation you have to make sure index with two mapped types, `project` and `commitactivity` and we add a `_parent` mapping from `commitactivity` to `parent` -[source,csharp,method="mappingexample"] +[source,csharp] ---- var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c .Mappings(map => map diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index 01187d93e26..bb284779908 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -14,7 +14,7 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -29,7 +29,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -52,7 +52,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index 963117ae1d4..ec328b430a1 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -17,11 +17,9 @@ as part of the format value. Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. -=== Fluent DSL Example - === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -46,9 +44,9 @@ s => s ) ---- -=== Object Initializer Syntax Example +=== Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -78,12 +76,52 @@ new SearchRequest } ---- +[source,javascript] +.Example json output +---- +{ + "size": 0, + "aggs": { + "projects_started_per_month": { + "date_histogram": { + "field": "startedOn", + "interval": "month", + "min_doc_count": 2, + "format": "yyyy-MM-dd'T'HH:mm:ss||date_optional_time", + "order": { + "_count": "asc" + }, + "extended_bounds": { + "min": "2014-06-06T12:01:02.123", + "max": "2016-06-06T12:01:02.123" + }, + "missing": "2015-06-06T12:01:02.123" + }, + "aggs": { + "project_tags": { + "nested": { + "path": "tags" + }, + "aggs": { + "tags": { + "terms": { + "field": "tags.name" + } + } + } + } + } + } + } +} +---- + === Handling responses Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index 1a9ff074265..ad0f1119412 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -1,13 +1,11 @@ -:sectiontitle: Date Range Aggregation - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net :imagesdir: ../../../images -[[{sectiontitle}]] -== {sectiontitle} +[[date-range-aggregation]] +== Date Range Aggregation A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` and `to` values can be expressed in `DateMath` expressions, and it is also possible to specify a date format by which the from and @@ -15,13 +13,11 @@ to response fields will be returned. IMPORTANT: this aggregation includes the `from` value and excludes the `to` value for each range. -Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] - -=== Fluent DSL Example +Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on Date Range Aggregation] === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -39,9 +35,9 @@ s => s ) ---- -=== Object Initializer Syntax Example +=== Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -60,12 +56,45 @@ new SearchRequest } ---- +[source,javascript] +.Example json output +---- +{ + "aggs": { + "projects_date_ranges": { + "date_range": { + "field": "startedOn", + "ranges": [ + { + "to": "now", + "from": "2015-06-06T12:01:02.123||+2d" + }, + { + "to": "now+1d-30m/h" + }, + { + "from": "2012-05-05||+1d-1m" + } + ] + }, + "aggs": { + "project_tags": { + "terms": { + "field": "tags" + } + } + } + } + } +} +---- + === Handling Responses Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); @@ -78,7 +107,7 @@ We specified three ranges so we expect to have three of them in the response === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- dateHistogram.Buckets.Count.Should().Be(3); diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index 1492782b522..cc6503a9a07 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -12,11 +12,9 @@ Often this will be used to narrow down the current aggregation context to a spec Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] -=== Fluent DSL Example - === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -29,9 +27,9 @@ s => s ) ---- -=== Object Initializer Syntax Example +=== Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -44,12 +42,37 @@ new SearchRequest } ---- +[source,javascript] +.Example json output +---- +{ + "aggs": { + "bethels_projects": { + "filter": { + "term": { + "leadDeveloper.firstName": { + "value": "pierce" + } + } + }, + "aggs": { + "project_tags": { + "terms": { + "field": "curatedTags.name" + } + } + } + } + } +} +---- + === Handling Responses Using the `.Aggs` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); @@ -62,14 +85,15 @@ tags.Buckets.Should().NotBeEmpty(); ---- [[empty-filter]] +[float] == Empty Filter When the collection of filters is empty or all are conditionless, NEST will serialize them to an empty object. -=== Fluent DSL Example +=== Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -83,9 +107,9 @@ s => s ) ---- -=== Object Initializer Syntax Example +=== Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -99,9 +123,21 @@ new SearchRequest } ---- -=== Handling Response +[source,javascript] +.Example json output +---- +{ + "aggs": { + "empty_filter": { + "filter": {} + } + } +} +---- + +=== Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filter("empty_filter").DocCount.Should().BeGreaterThan(0); diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index db7f59924b1..06e9ddb6971 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -14,11 +14,12 @@ that do not match any filter, these will be collected in the _other bucket_. Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. [[named-filters]] +[float] == Named filters === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -39,7 +40,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -59,7 +60,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -109,7 +110,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); @@ -130,11 +131,12 @@ namedResult.DocCount.Should().Be(0); ---- [[anonymous-filters]] +[float] == Anonymous filters === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -154,7 +156,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -176,7 +178,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -225,7 +227,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); @@ -239,11 +241,12 @@ results.Last().DocCount.Should().Be(0); //<1> <1> The last bucket is the _other bucket_ [[empty-filters]] +[float] == Empty Filters === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -255,7 +258,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -266,7 +269,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -282,7 +285,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); @@ -293,7 +296,7 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -307,7 +310,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -321,7 +324,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -337,7 +340,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filters("conditionless_filters").Buckets.Should().BeEmpty(); diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index fcd6fb1d587..29d8efdf8e6 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -27,7 +27,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -45,7 +45,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -77,7 +77,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var ringsAroundAmsterdam = response.Aggs.GeoDistance("rings_around_amsterdam"); diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index 5ebe2154126..0e817451db7 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -24,7 +24,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -38,7 +38,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -57,7 +57,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var myGeoHashGrid = response.Aggs.GeoHash("my_geohash_grid"); diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index 10ed828c857..d953b5db31e 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -25,7 +25,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -39,7 +39,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -60,7 +60,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var allProjects = response.Aggs.Global("all_projects"); diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index cac00c00593..ead573835cd 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -24,7 +24,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -38,7 +38,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -59,7 +59,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commits = response.Aggs.Histogram("commits"); diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index 15cd832b7bf..6f905c04ec0 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -25,7 +25,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -41,7 +41,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -65,7 +65,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var ipRanges = response.Aggs.IpRange("ip_ranges"); diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index 93bfd8e6217..f491207773a 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -32,7 +32,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -48,7 +48,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsWithoutDesc = response.Aggs.Missing("projects_without_a_description"); diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index 632387e0827..8fe1697c02e 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -26,7 +26,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -41,7 +41,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -64,7 +64,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var tags = response.Aggs.Nested("tags"); diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index 21247e68e3c..9bb0e9fd873 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -26,7 +26,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -43,7 +43,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -71,7 +71,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitRanges = response.Aggs.Range("commit_ranges"); diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index 6ee15fab424..d74428c9599 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -35,7 +35,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -57,7 +57,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -92,7 +92,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var tags = response.Aggs.Nested("tags"); diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index 661bcdbd803..d8adff2d033 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -27,7 +27,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -43,7 +43,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -67,7 +67,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var sample = response.Aggs.Sampler("sample"); diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 913b71a70e3..8f1b68f86b5 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -26,7 +26,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -43,7 +43,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -64,7 +64,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var sigNames = response.Aggs.SignificantTerms("significant_names"); diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index c8675569f3f..2c9f91b38cd 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -33,7 +33,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -60,7 +60,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -96,7 +96,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var states = response.Aggs.Terms("states"); diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index 6af103b2ce9..5f682b88559 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -26,7 +26,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -65,7 +65,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitsAvg = response.Aggs.Average("average_commits"); diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index 7fb74f097b2..a5d667cd13a 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -22,7 +22,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -33,7 +33,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -50,7 +50,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectCount = response.Aggs.Cardinality("state_count"); diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 4b8ddb5a2a0..93b66aece4f 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitStats = response.Aggs.ExtendedStats("commit_stats"); diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index da7b9e61d3e..a156cb36937 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -22,7 +22,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -33,7 +33,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -50,7 +50,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var viewport = response.Aggs.GeoBounds("viewport"); diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index be2f31d2d28..06fcfc5842e 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var max = response.Aggs.Max("max_commits"); diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index 422d99a75ca..76eb78e1ebb 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var min = response.Aggs.Max("min_commits"); diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index fec9d149234..2740ff6fb1c 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -29,7 +29,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -46,7 +46,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -73,7 +73,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitsOutlier = response.Aggs.PercentileRanks("commits_outlier"); diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index 941149481fb..8f3a08348e4 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -29,7 +29,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -46,7 +46,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -74,7 +74,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitsOutlier = response.Aggs.Percentiles("commits_outlier"); diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index f830295838a..ce36db3e8fc 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -24,7 +24,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -38,7 +38,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -65,7 +65,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var sumTheHardWay = response.Aggs.ScriptedMetric("sum_the_hard_way"); diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index 2b0df3707f0..ef2904020f8 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitStats = response.Aggs.Stats("commit_stats"); diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 954f8e54904..968e2fac7d9 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitsSum = response.Aggs.Sum("commits_sum"); diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index 1071aa4cab7..a7f72d4bf52 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -53,7 +53,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -93,7 +93,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -148,7 +148,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var states = response.Aggs.Terms("states"); diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index 076fe5f00dd..f33d2244339 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(a => a @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var commitCount = response.Aggs.ValueCount("commit_count"); diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index ec1e909aad5..4612eb1787d 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -50,7 +50,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -81,7 +81,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index 6cfda9f6f4d..1dfb654e956 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -45,7 +45,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -77,7 +77,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -129,7 +129,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 2d85270eb70..4e176279a11 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -34,7 +34,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -56,7 +56,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -91,7 +91,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index 693f23c738f..5c63328d90f 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); @@ -23,7 +23,7 @@ commitsDerivative.Value.Should().NotBe(null); === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -45,7 +45,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -61,7 +61,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index 3ca98cbd3d4..99678677cd8 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); @@ -23,7 +23,7 @@ commitsDerivative.Value.Should().NotBe(null); === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -45,7 +45,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -61,7 +61,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index b4446a56076..8dde063be22 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -31,7 +31,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -46,7 +46,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -76,7 +76,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index be90f75acf3..21cfd395fe9 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -31,7 +31,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -46,7 +46,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -76,7 +76,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index 5f68fd1904e..f0b8d34c50e 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -36,7 +36,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -58,7 +58,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -92,7 +92,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index 51c44a002a6..ac263b7bda9 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -37,7 +37,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -60,7 +60,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -95,7 +95,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index fbc579c8876..1ace862ad63 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -42,7 +42,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -70,7 +70,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -110,7 +110,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); ---- diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index 8250cf6f639..81ac24db151 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -35,7 +35,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -55,7 +55,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -88,7 +88,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index 7ba1e2c5c85..95415163e02 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -36,7 +36,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -57,7 +57,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -91,7 +91,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index 749ea9157a4..c159a8e2435 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); @@ -23,7 +23,7 @@ commits.Value.Should().NotBe(null); === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -46,7 +46,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -65,7 +65,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index 99d13bf8457..cf3b70f0461 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Size(0) @@ -31,7 +31,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -46,7 +46,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -76,7 +76,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 63ae422f10e..eade42c8ecc 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -28,7 +28,7 @@ It benefits from types that are carried over to sub aggregations === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Aggregations(aggs => aggs @@ -47,7 +47,7 @@ The object initializer syntax (OIS) is a one-to-one mapping with how aggregation have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one mapping, being dictionary based in C means it can grow exponentially in complexity rather quickly. -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -68,7 +68,7 @@ It also allows you to combine multiple aggregations using bitwise AND (`&&`) ope Compare the following example with the previous vanilla OIS syntax -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -87,7 +87,7 @@ An advanced scenario may involve an existing collection of aggregation functions on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor (`childAggs` below) in turn, returning the descriptor after each function application. -[source,csharp,method="fluent"] +[source,csharp] ---- var aggregations = new List, IAggregationContainer>> //<1> { diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc index 9d421b7b711..35935e3ae46 100644 --- a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -9,19 +9,19 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- FluentExample ---- === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- InitializerExample ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc index d6467955899..a31cae8bc77 100644 --- a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -9,19 +9,19 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- FluentExample ---- === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- InitializerExample ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc index ba1b1f42404..9285e22a10c 100644 --- a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -9,19 +9,19 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- FluentExample ---- === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- InitializerExample ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc index dafd6599daf..989b51f9d42 100644 --- a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -9,19 +9,19 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- FluentExample ---- === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- InitializerExample ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index b4c155d2a75..e3fd25e8347 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -1,5 +1,3 @@ -:section-number: 4.1 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -12,19 +10,20 @@ Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which NEST can use to issue client calls on. There are 3 types of connection pool -* <> +* <> -* <> +* <> -* <> +* <> +[[single-node-connection-pool]] === SingleNodeConnectionPool The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always ready to go. -[source,csharp,method="singlenode"] +[source,csharp] ---- var uri = new Uri("http://localhost:9201"); var pool = new SingleNodeConnectionPool(uri); @@ -35,14 +34,14 @@ node.Uri.Port.Should().Be(9201); This type of pool is hardwired to opt out of sniffing -[source,csharp,method="singlenode"] +[source,csharp] ---- pool.SupportsReseeding.Should().BeFalse(); ---- and pinging -[source,csharp,method="singlenode"] +[source,csharp] ---- pool.SupportsPinging.Should().BeFalse(); ---- @@ -50,7 +49,7 @@ pool.SupportsPinging.Should().BeFalse(); When you use the low ceremony `ElasticClient` constructor that takes a single `Uri`, We default to using `SingleNodeConnectionPool` -[source,csharp,method="singlenode"] +[source,csharp] ---- var client = new ElasticClient(uri); @@ -59,7 +58,7 @@ client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ---- +[[static-connection-pool]] + === StaticConnectionPool The static connection pool is great if you have a known small sized cluster and do no want to enable sniffing to find out the cluster topology. -[source,csharp,method="static"] +[source,csharp] ---- var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ---- a connection pool can be seeded using an enumerable of `Uri`s -[source,csharp,method="static"] +[source,csharp] ---- var pool = new StaticConnectionPool(uris); ---- Or using an enumerable of `Node`s -[source,csharp,method="static"] +[source,csharp] ---- var nodes = uris.Select(u => new Node(u)); @@ -103,14 +104,14 @@ pool = new StaticConnectionPool(nodes); This type of pool is hardwired to opt out of sniffing -[source,csharp,method="static"] +[source,csharp] ---- pool.SupportsReseeding.Should().BeFalse(); ---- but supports pinging when enabled -[source,csharp,method="static"] +[source,csharp] ---- pool.SupportsPinging.Should().BeTrue(); ---- @@ -118,26 +119,28 @@ pool.SupportsPinging.Should().BeTrue(); To create a client using this static connection pool, pass the connection pool to the `ConnectionSettings` you pass to `ElasticClient` -[source,csharp,method="static"] +[source,csharp] ---- var client = new ElasticClient(new ConnectionSettings(pool)); client.ConnectionSettings.ConnectionPool.Should().BeOfType(); ---- +[[sniffing-connection-pool]] + === SniffingConnectionPool A subclass of `StaticConnectionPool` that allows itself to be reseeded at run time. It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. -[source,csharp,method="sniffing"] +[source,csharp] ---- var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ---- a connection pool can be seeded using an enumerable of `Uri` -[source,csharp,method="sniffing"] +[source,csharp] ---- var pool = new SniffingConnectionPool(uris); ---- @@ -147,7 +150,7 @@ A major benefit here is you can include known node roles when seeding and NEST can use this information to favour sniffing on master eligible nodes first and take master only nodes out of rotation for issuing client calls on. -[source,csharp,method="sniffing"] +[source,csharp] ---- var nodes = uris.Select(u=>new Node(u)); @@ -156,14 +159,14 @@ pool = new SniffingConnectionPool(nodes); This type of pool is hardwired to opt in to sniffing -[source,csharp,method="sniffing"] +[source,csharp] ---- pool.SupportsReseeding.Should().BeTrue(); ---- and pinging -[source,csharp,method="sniffing"] +[source,csharp] ---- pool.SupportsPinging.Should().BeTrue(); ---- @@ -171,7 +174,7 @@ pool.SupportsPinging.Should().BeTrue(); To create a client using the sniffing connection pool pass the connection pool to the `ConnectionSettings` you pass to `ElasticClient` -[source,csharp,method="sniffing"] +[source,csharp] ---- var client = new ElasticClient(new ConnectionSettings(pool)); diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index b3197bbfaf1..ce6e66997b9 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -13,14 +13,14 @@ Not typically something you'll have to pass to the client but all calls to `Syst in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. -[source,csharp,method="defaultnowbehaviour"] +[source,csharp] ---- var dateTimeProvider = DateTimeProvider.Default; ---- dates are always returned in UTC -[source,csharp,method="defaultnowbehaviour"] +[source,csharp] ---- dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); ---- @@ -29,7 +29,7 @@ Another responsibility of this interface is to calculate the time a node has to based on the number of attempts to revive it. For very advanced use cases, this might be something of interest to provide a custom implementation for. -[source,csharp,method="deadtimeoutcalculation"] +[source,csharp] ---- var dateTimeProvider = DateTimeProvider.Default; ---- @@ -37,7 +37,7 @@ var dateTimeProvider = DateTimeProvider.Default; The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the default values for `timeout` and `maxTimeout` are -[source,csharp,method="deadtimeoutcalculation"] +[source,csharp] ---- var timeout = TimeSpan.FromMinutes(1); @@ -53,7 +53,7 @@ image::{imagesdir}/timeoutplot.png[dead timeout] The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. -[source,csharp,method="deadtimeoutcalculation"] +[source,csharp] ---- var timeouts = Enumerable.Range(0, 30) .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index d5cb51399e3..73fd67953c7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -13,7 +13,7 @@ A `Node` can be instantiated by passing it a `Uri` -[source,csharp,method="creating"] +[source,csharp] ---- var node = new Node(new Uri("http://localhost:9200")); @@ -23,7 +23,7 @@ node.Uri.Port.Should().Be(9200); By default master eligible and holds data is presumed to be true -[source,csharp,method="creating"] +[source,csharp] ---- node.MasterEligible.Should().BeTrue(); @@ -32,7 +32,7 @@ node.HoldsData.Should().BeTrue(); Is resurrected is true on first usage, hints to the transport that a ping might be useful -[source,csharp,method="creating"] +[source,csharp] ---- node.IsResurrected.Should().BeTrue(); ---- @@ -45,7 +45,7 @@ a known cluster topology. passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy -[source,csharp,method="buildingpaths"] +[source,csharp] ---- var node = new Node(new Uri("http://test.example/elasticsearch")); @@ -56,7 +56,7 @@ node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); We force paths to end with a forward slash so that they can later be safely combined -[source,csharp,method="buildingpaths"] +[source,csharp] ---- var combinedPath = new Uri(node.Uri, "index/type/_search"); @@ -65,7 +65,7 @@ combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); which is exactly what the `CreatePath` method does on `Node` -[source,csharp,method="buildingpaths"] +[source,csharp] ---- combinedPath = node.CreatePath("index/type/_search"); @@ -74,7 +74,7 @@ combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); === Marking Nodes -[source,csharp,method="marknodes"] +[source,csharp] ---- var node = new Node(new Uri("http://localhost:9200")); @@ -86,7 +86,7 @@ node.IsAlive.Should().BeTrue(); every time a node is marked dead the number of attempts should increase and the passed datetime should be exposed. -[source,csharp,method="marknodes"] +[source,csharp] ---- var deadUntil = DateTime.Now.AddMinutes(1); @@ -101,7 +101,7 @@ node.DeadUntil.Should().Be(deadUntil); however when marking a node alive, the `DeadUntil` property should be reset and `FailedAttempts` reset to 0 -[source,csharp,method="marknodes"] +[source,csharp] ---- node.MarkAlive(); @@ -116,7 +116,7 @@ node.IsAlive.Should().BeTrue(); Nodes are considered equal if they have the same endpoint, no matter what other metadata is associated -[source,csharp,method="equality"] +[source,csharp] ---- var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 601a8884fc2..9d28ee21c1d 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -12,14 +12,14 @@ Every request is executed in the context of a `RequestPipeline` when using the default `ITransport` implementation. -[source,csharp,method="requestpipeline"] +[source,csharp] ---- var settings = TestClient.CreateSettings(); ---- When calling Request/RequestAsync on Transport the whole coordination of the request is deferred to a new instance in a `using` block. -[source,csharp,method="requestpipeline"] +[source,csharp] ---- var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); @@ -29,7 +29,7 @@ pipeline.GetType().Should().Implement(); However the transport does not instantiate `RequestPipeline` directly; it uses a pluggable `IRequestPipelineFactory` to create it -[source,csharp,method="requestpipeline"] +[source,csharp] ---- var requestPipelineFactory = new RequestPipelineFactory(); @@ -46,12 +46,12 @@ requestPipeline.GetType().Should().Implement(); you can pass your own `IRequestPipeline` implementation to the transport when instantiating a client allowing you to have requests executed on your own custom request pipeline -[source,csharp,method="requestpipeline"] +[source,csharp] ---- var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); ---- -[source,csharp,method="createpipeline"] +[source,csharp] ---- var pool = setupPool(new[] { TestClient.CreateNode(), TestClient.CreateNode(9201) }); @@ -60,7 +60,7 @@ var settings = new ConnectionSettings(pool, TestClient.CreateConnection()); settings = settingsSelector?.Invoke(settings) ?? settings; ---- -[source,csharp,method="firstusagecheck"] +[source,csharp] ---- var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); @@ -71,7 +71,7 @@ var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris)); Here we have setup three pipelines using three different connection pools, lets see how they behave -[source,csharp,method="firstusagecheck"] +[source,csharp] ---- singleNodePipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); @@ -83,14 +83,14 @@ sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeTrue(); Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() You can however disable this on ConnectionSettings -[source,csharp,method="firstusagecheck"] +[source,csharp] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnStartup(false)); sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); ---- -[source,csharp,method="sniffsonconnectionfailure"] +[source,csharp] ---- var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); @@ -108,14 +108,14 @@ sniffingPipeline.SniffsOnConnectionFailure.Should().BeTrue(); Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() You can however disable this on ConnectionSettings -[source,csharp,method="sniffsonconnectionfailure"] +[source,csharp] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnConnectionFault(false)); sniffingPipeline.SniffsOnConnectionFailure.Should().BeFalse(); ---- -[source,csharp,method="sniffsonstalecluster"] +[source,csharp] ---- var dateTime = new TestableDateTimeProvider(); @@ -140,14 +140,14 @@ sniffingPipeline.StaleClusterState.Should().BeFalse(); go one hour into the future -[source,csharp,method="sniffsonstalecluster"] +[source,csharp] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- connection pools that do not support reseeding never go stale -[source,csharp,method="sniffsonstalecluster"] +[source,csharp] ---- singleNodePipeline.StaleClusterState.Should().BeFalse(); @@ -156,15 +156,15 @@ staticPipeline.StaleClusterState.Should().BeFalse(); the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source,csharp,method="sniffsonstalecluster"] +[source,csharp] ---- sniffingPipeline.StaleClusterState.Should().BeTrue(); ---- A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout. -See the <> for more details, here we assert that our request pipeline exposes this propertly +See the <> for more details, here we assert that our request pipeline exposes this propertly -[source,csharp,method="istakingtoolong"] +[source,csharp] ---- var dateTime = new TestableDateTimeProvider(); @@ -183,14 +183,14 @@ sniffingPipeline.IsTakingTooLong.Should().BeFalse(); go one hour into the future -[source,csharp,method="istakingtoolong"] +[source,csharp] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- connection pools that do not support reseeding never go stale -[source,csharp,method="istakingtoolong"] +[source,csharp] ---- singleNodePipeline.IsTakingTooLong.Should().BeTrue(); @@ -199,14 +199,14 @@ staticPipeline.IsTakingTooLong.Should().BeTrue(); the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source,csharp,method="istakingtoolong"] +[source,csharp] ---- sniffingPipeline.IsTakingTooLong.Should().BeTrue(); ---- request pipeline exposes the DateTime it started, here we assert it started 2 hours in the past -[source,csharp,method="istakingtoolong"] +[source,csharp] ---- (dateTime.Now() - singleNodePipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); @@ -215,7 +215,7 @@ request pipeline exposes the DateTime it started, here we assert it started 2 ho (dateTime.Now() - sniffingPipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); ---- -[source,csharp,method="setssniffpathusingtotimespan"] +[source,csharp] ---- var dateTime = new TestableDateTimeProvider(); diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index c83dedb609d..545c4b01e9c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -20,14 +20,14 @@ This is the minimum `ITransport` needs to report back for the client to function e.g in the low level client, transport is instantiated like this: -[source,csharp,method="interfaceexplained"] +[source,csharp] ---- var lowLevelTransport = new Transport(new ConnectionConfiguration()); ---- and in the high level client, like this: -[source,csharp,method="interfaceexplained"] +[source,csharp] ---- var highlevelTransport = new Transport(new ConnectionSettings()); @@ -39,7 +39,7 @@ The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the d many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. If you feel this need, {github}/issues[please let us know] as we'd love to learn why you've go down this route! -[source,csharp,method="interfaceexplained"] +[source,csharp] ---- var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index fce1c34f396..df1d640d52d 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -12,7 +12,7 @@ out the client as an UnexpectedElasticsearchClientException, regardless whether An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. -[source,csharp,method="unexpectedexceptionsbubbleout"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -48,7 +48,7 @@ in the pipeline the unexpected exception is not lost, here a call to 9200 fails It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we can still see the audit trail for the whole coordinated request. -[source,csharp,method="willfailoverknowconnectionexceptionbutnotunexpected"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -86,7 +86,7 @@ An unexpected hard exception on ping and sniff is something we *do* try to revov Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. However the client call on 9201 throws a hard exception we can not recover from -[source,csharp,method="pingunexceptedexceptiondoesfailover"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -98,7 +98,7 @@ var audit = new Auditor(() => Framework.Cluster ); ---- -[source,csharp,method="pingunexceptedexceptiondoesfailover"] +[source,csharp] ---- audit = await audit.TraceUnexpectedException( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 1c315d7b5e2..81bef90f201 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -15,7 +15,7 @@ both a client that throws and one that returns an invalid response with an `.Ori The following are recoverable exceptions -[source,csharp,method="somepipelinefailuresarerecoverable"] +[source,csharp] ---- var recoverablExceptions = new[] { @@ -28,7 +28,7 @@ recoverablExceptions.Should().OnlyContain(e => e.Recoverable); and the unrecoverable exceptions -[source,csharp,method="somepipelinefailuresarerecoverable"] +[source,csharp] ---- var unrecoverableExceptions = new[] { @@ -46,7 +46,7 @@ unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); As an example, let's set up a 10 node cluster that will always succeed when pinged but will fail with a 401 response when making client calls -[source,csharp,method="badauthenticationisunrecoverable"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -60,7 +60,7 @@ var audit = new Auditor(() => Framework.Cluster Here we make a client call and determine that the first audit event was a successful ping, followed by a bad response as a result of a bad authentication response -[source,csharp,method="badauthenticationisunrecoverable"] +[source,csharp] ---- audit = await audit.TraceElasticsearchException( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index c8ecc076371..166f6fc4f66 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -10,7 +10,7 @@ When using connection pooling and the pool has sufficient nodes a request will be retried if the call to a node throws an exception or returns a 502 or 503 -[source,csharp,method="exceptionfallsovertonextnode"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -31,7 +31,7 @@ audit = await audit.TraceCall( Will be treated as an error that requires retrying -[source,csharp,method="http502fallsover"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -53,7 +53,7 @@ audit = await audit.TraceCall( Will be treated as an error that requires retrying -[source,csharp,method="http503fallsover"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -73,7 +73,7 @@ audit = await audit.TraceCall( If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. -[source,csharp,method="httpteapotdoesnotfallover"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index d38daa49726..5cd23461c0b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -4,14 +4,16 @@ :imagesdir: ../../../images +[[max-retries]] + [[max-retries]] -== MaxRetries +== Max Retries By default retry as many times as we have nodes. However retries still respect the request timeout. Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds -[source,csharp,method="defaultmaxisnumberofnodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -39,7 +41,7 @@ audit = await audit.TraceCall( When you have a 100 node cluster you might want to ensure a fixed number of retries. Remember that the actual number of requests is initial attempt + set number of retries -[source,csharp,method="fixedmaximumnumberofretries"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -64,7 +66,7 @@ In our previous test we simulated very fast failures, in the real world a call m Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted -[source,csharp,method="respectsoveralrequesttimeout"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -88,7 +90,7 @@ Here we simulate calls taking 3 seconds, a request time out of 2 and an overall We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 wins over the configured request timeout -[source,csharp,method="respectsmaxretrytimeoutoverrequesttimeout"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -112,7 +114,7 @@ audit = await audit.TraceCall( If your retry policy expands beyond available nodes we won't retry the same node twice -[source,csharp,method="retriesarelimitedbynodesinpool"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(2) @@ -135,7 +137,7 @@ This makes setting any retry setting on a single node connection pool a NOOP, th Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. -[source,csharp,method="doesnotretryonsinglenodeconnectionpool"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index d2be9120876..9d3b8440ea3 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -15,7 +15,7 @@ This allows us to fail and fallover to a healthy node faster A cluster with 2 nodes where the second node fails on ping -[source,csharp,method="pingfailsfallsovertohealthynodewithoutping"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(2) @@ -33,7 +33,7 @@ It fails so we wrap over to node 9200 which we've already pinged Finally we assert that the connectionpool has one node that is marked as dead -[source,csharp,method="pingfailsfallsovertohealthynodewithoutping"] +[source,csharp] ---- await audit.TraceCalls( new ClientCall { @@ -54,7 +54,7 @@ new ClientCall { A cluster with 4 nodes where the second and third pings fail -[source,csharp,method="pingfailsfallsovermultipletimestohealthynode"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -74,7 +74,7 @@ we haven't used it before and it succeeds Finally we assert that the connectionpool has two nodes that are marked as dead -[source,csharp,method="pingfailsfallsovermultipletimestohealthynode"] +[source,csharp] ---- await audit.TraceCalls( new ClientCall { @@ -97,7 +97,7 @@ new ClientCall { A healthy cluster of 4 (min master nodes of 3 of course!) -[source,csharp,method="allnodesarepingedonlyonfirstuseprovidedtheyarehealthy"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 29472c2c06e..016bdb0b1d1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -12,7 +12,7 @@ When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK -[source,csharp,method="pingafterrevival"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(3) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 4f16cde4420..4999fb9a9fb 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -17,7 +17,7 @@ but we disable the sniffing on our first request so we only see the ping and the Let's set up the cluster and configure clients to **always** sniff on startup -[source,csharp,method="disablesniff"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -35,7 +35,7 @@ does not disable sniffing on a per request basis And after that no sniff on startup will happen again -[source,csharp,method="disablesniff"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall(r => r.DisableSniffing()) //<1> @@ -65,7 +65,7 @@ new ClientCall() Now, let's disable pinging on the request -[source,csharp,method="disableping"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -88,7 +88,7 @@ audit = await audit.TraceCall( Finally, let's demonstrate disabling both sniff and ping on the request -[source,csharp,method="disablesniffandping"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index fcd8e5e2e49..6bfb4465926 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -15,7 +15,7 @@ we set up a 10 node cluster with a global time out of 20 seconds. Each call on a node takes 10 seconds. So we can only try this call on 2 nodes before the max request time out kills the client call. -[source,csharp,method="respectsrequesttimeoutoverride"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -29,7 +29,7 @@ var audit = new Auditor(() => Framework.Cluster On the second request we specify a request timeout override to 60 seconds We should now see more nodes being tried. -[source,csharp,method="respectsrequesttimeoutoverride"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { @@ -60,7 +60,7 @@ we set up a 10 node cluster with a global time out of 20 seconds. Each call on a node takes 10 seconds. So we can only try this call on 2 nodes before the max request time out kills the client call. -[source,csharp,method="respectsconnecttimeoutoverride"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -77,7 +77,7 @@ calls always take 20, so we should see a single ping failure On the second request we set a request ping timeout override of 2seconds We should now see more nodes being tried before the request timeout is hit. -[source,csharp,method="respectsconnecttimeoutoverride"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 19a18a7dfab..2659cd5c66b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -9,7 +9,7 @@ [[allowed-status-codes]] == Allowed status codes -[source,csharp,method="canoverridebadresponse"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 63659f79d5f..0281d781a49 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -12,7 +12,7 @@ Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` request configuration. This will ignore the pool and not retry. -[source,csharp,method="onlycallsforcednode"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index 11b0497085f..bd77566dbe7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -13,7 +13,7 @@ By default retry as many times as we have nodes. However retries still respect t Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds -[source,csharp,method="defaultmaxisnumberofnodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -35,7 +35,7 @@ audit = await audit.TraceCall( When you have a 100 node cluster you might want to ensure a fixed number of retries. Remember that the actual number of requests is initial attempt + set number of retries -[source,csharp,method="fixedmaximumnumberofretries"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -59,7 +59,7 @@ This makes setting any retry setting on a single node connection pool a NOOP, th Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. -[source,csharp,method="doesnotretryonsinglenodeconnectionpool"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index ed1d320833b..c6d40229360 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -15,7 +15,7 @@ Each connection pool round robins over the `live` nodes, to evenly distribute th over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. -[source,csharp,method="eachviewstartsatnexpositionandwrapsover"] +[source,csharp] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); var staticPool = new StaticConnectionPool(uris, randomize: false); @@ -33,7 +33,7 @@ Thread B calls GetNext() second without a local cursor and therefor starts at 1. After this each thread should walk the nodes in successive order using their local cursor e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. -[source,csharp,method="assertcreateview"] +[source,csharp] ---- var startingPositions = Enumerable.Range(0, NumberOfNodes) .Select(i => pool.CreateView().First()) @@ -55,7 +55,7 @@ Lets up the ante: We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 comes 9200 again -[source,csharp,method="assertcreateview"] +[source,csharp] ---- var threadedStartPositions = new ConcurrentBag(); @@ -71,7 +71,7 @@ t.Join(); Each thread reported the first node it started off lets make sure we see each node twice as the first node because we started `NumberOfNodes * 2` threads -[source,csharp,method="assertcreateview"] +[source,csharp] ---- var grouped = threadedStartPositions.GroupBy(p => p).ToList(); diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index d490c9c92a1..8f487c62761 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -15,7 +15,7 @@ GetNext is implemented in a lock free thread safe fashion, meaning each callee g over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. -[source,csharp,method="eachviewseesnextbutskipsthedeadnode"] +[source,csharp] ---- var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); @@ -32,7 +32,7 @@ node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); ---- -[source,csharp,method="eachviewskipsaheadwithone"] +[source,csharp] ---- var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); var pool = new StaticConnectionPool(seeds, randomize: false); @@ -46,7 +46,7 @@ node.Uri.Port.Should().Be(9202); After we marked the first node alive again, we expect it to be hit again -[source,csharp,method="eachviewseesnextbutskipsthedeadnode"] +[source,csharp] ---- seeds.First().MarkAlive(); @@ -63,7 +63,7 @@ node = pool.CreateView().First(); node.Uri.Port.Should().Be(9200); ---- -[source,csharp,method="viewseesresurrectednodes"] +[source,csharp] ---- var dateTimeProvider = new TestableDateTimeProvider(); @@ -84,7 +84,7 @@ node.Uri.Port.Should().Be(9202); If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected -[source,csharp,method="viewseesresurrectednodes"] +[source,csharp] ---- dateTimeProvider.ChangeTime(d => d.AddDays(2)); @@ -105,7 +105,7 @@ n.IsResurrected.Should().BeTrue(); A cluster with 2 nodes where the second node fails on ping -[source,csharp,method="fallsoverdeadnodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -126,7 +126,7 @@ Finally we assert that the connectionpool has one node that is marked as dead The next call goes to 9203 which fails so we should wrap over -[source,csharp,method="fallsoverdeadnodes"] +[source,csharp] ---- await audit.TraceCalls( new ClientCall { @@ -164,7 +164,7 @@ new ClientCall { A cluster with 2 nodes where the second node fails on ping -[source,csharp,method="picksadifferentnodeeachtimeanodeisdown"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -180,7 +180,7 @@ After all our registered nodes are marked dead we want to sample a single dead n each time to quickly see if the cluster is back up. We do not want to retry all 4 nodes -[source,csharp,method="picksadifferentnodeeachtimeanodeisdown"] +[source,csharp] ---- await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index bed0b0d0902..82798a9ba28 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -7,7 +7,7 @@ [[volatile-updates]] == Volatile Updates -[source,csharp,method="staticpoolwithstandsconcurrentreadandwrites"] +[source,csharp] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); @@ -18,7 +18,7 @@ Action callStatic = () => this.AssertCreateView(staticPool); callStatic.ShouldNotThrow(); ---- -[source,csharp,method="sniffingpoolwithstandsconcurrentreadandwrites"] +[source,csharp] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); var sniffingPool = new SniffingConnectionPool(uris, randomize: false); @@ -26,7 +26,7 @@ Action callSniffing = () => this.AssertCreateView(sniffingPool); callSniffing.ShouldNotThrow(); ---- -[source,csharp,method="assertcreateview"] +[source,csharp] ---- var threads = Enumerable.Range(0, 50) .Select(i => CreateReadAndUpdateThread(pool)) diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index a40eb4355ca..144f2a93b8e 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -26,7 +26,7 @@ still fails once After this second failure on 9201 another sniff will be returned a cluster that no longer fails but looks completely different (9210-9212) we should be able to handle this -[source,csharp,method="doesasniffafterconnectionfailure"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(5) @@ -55,7 +55,7 @@ Our pool should now have three nodes We assert we do a sniff on the first master node in our updated cluster -[source,csharp,method="doesasniffafterconnectionfailure"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { @@ -91,7 +91,7 @@ new ClientCall { Here we set up our cluster exactly the same as the previous setup Only we enable pinging (default is true) and make the ping fail -[source,csharp,method="doesasniffafterconnectionfailureonping"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(5) @@ -121,7 +121,7 @@ We assert we do a sniff on the first master node in our updated cluster 9210 was already pinged after the sniff returned the new nodes -[source,csharp,method="doesasniffafterconnectionfailureonping"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index 0460c3ecfd7..b17dff4f9b6 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -14,7 +14,7 @@ In addition to sniffing on startup and sniffing on failures, sniffing periodical clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes but without sniffing periodically it will never find the nodes that have been added to help out with load -[source,csharp,method="asniffonstartuphappens"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -42,7 +42,7 @@ var audit = new Auditor(() => Framework.Cluster healty cluster all nodes return healthy responses -[source,csharp,method="asniffonstartuphappens"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { { HealthyResponse, 9200 } }, @@ -65,14 +65,14 @@ audit = await audit.TraceCalls( Now let's forward the clock 31 minutes, our sniff lifespan should now go state and the first call should do a sniff which discovered we scaled up to a 100 nodes! -[source,csharp,method="asniffonstartuphappens"] +[source,csharp] ---- audit.ChangeTime(d => d.AddMinutes(31)); ---- a sniff is done first and it prefers the first node master node -[source,csharp,method="asniffonstartuphappens"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { @@ -88,7 +88,7 @@ audit.ChangeTime(d => d.AddMinutes(31)); a sniff is done first and it prefers the first node master node -[source,csharp,method="asniffonstartuphappens"] +[source,csharp] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index 225e5d33499..69798367b95 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -11,7 +11,7 @@ Connection pools that return true for `SupportsReseeding` by default sniff on startup. -[source,csharp,method="asniffonstartuphappensonce"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -39,7 +39,7 @@ await audit.TraceCalls( ); ---- -[source,csharp,method="sniffonstartuptakesnewclusterstate"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -59,7 +59,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method="snifftriesallnodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -86,7 +86,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method="sniffprefersmasternodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(new[] { @@ -107,7 +107,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method="sniffprefersmasternodesbutstillfailsover"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(new[] { @@ -131,7 +131,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method="asniffonstartuphappens"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index 1f7354d2fab..4546a188faa 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -12,7 +12,7 @@ When we sniff the custer state we detect the role of the node whether its master eligible and holds data We use this information when selecting a node to perform an API call on. -[source,csharp,method="detectsdatanodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -42,7 +42,7 @@ var audit = new Auditor(() => Framework.Cluster await audit.TraceStartup(); ---- -[source,csharp,method="detectsfqdn"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -73,7 +73,7 @@ var audit = new Auditor(() => Framework.Cluster await audit.TraceStartup(); ---- -[source,csharp,method="sniffpicksuproles"] +[source,csharp] ---- var node = SniffAndReturnNode(); @@ -88,21 +88,21 @@ node.MasterEligible.Should().BeTrue(); node.HoldsData.Should().BeFalse(); ---- -[source,csharp,method="sniffandreturnnode"] +[source,csharp] ---- var pipeline = CreatePipeline(); pipeline.Sniff(); ---- -[source,csharp,method="sniffandreturnnodeasync"] +[source,csharp] ---- var pipeline = CreatePipeline(); await pipeline.SniffAsync(); ---- -[source,csharp,method="createpipeline"] +[source,csharp] ---- this._settings = this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; @@ -111,7 +111,7 @@ var pipeline = new RequestPipeline(this._settings, DateTimeProvider.Default, new new SearchRequestParameters()); ---- -[source,csharp,method="assertsniffresponse"] +[source,csharp] ---- var nodes = this._settings.ConnectionPool.Nodes; @@ -120,7 +120,7 @@ nodes.Should().NotBeEmpty().And.HaveCount(1); var node = nodes.First(); ---- -[source,csharp,method="detectsmasternodes"] +[source,csharp] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index b78e05a30f2..cc484ba3ac2 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -1,5 +1,3 @@ -:section-number: 4.1 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -16,7 +14,7 @@ but the actual instance type of the result can be that of the subclass directly Let's look at an example; Imagine we want to search over multiple types that all implement `ISearchResult` -[source,csharp,method="unknown"] +[source,csharp] ---- public interface ISearchResult { @@ -26,7 +24,7 @@ public interface ISearchResult We have three implementations of `ISearchResult` namely `A`, `B` and `C` -[source,csharp,method="unknown"] +[source,csharp] ---- public class A : ISearchResult { @@ -53,7 +51,7 @@ The most straightforward way to search over multiple types is to type the response to the parent interface or base class and pass the actual types we want to search over using `.Type()` -[source,csharp,method="usingtypes"] +[source,csharp] ---- var result = this._client.Search(s => s .Type(Types.Type(typeof(A), typeof(B), typeof(C))) @@ -67,7 +65,7 @@ hits that have "_type" : "a` will be serialized to `A` and so forth Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method="usingtypes"] +[source,csharp] ---- result.IsValid.Should().BeTrue(); @@ -77,7 +75,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method="usingtypes"] +[source,csharp] ---- var aDocuments = result.Documents.OfType(); @@ -90,7 +88,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method="usingtypes"] +[source,csharp] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -102,7 +100,7 @@ cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to -[source,csharp,method="usingconcretetypeselector"] +[source,csharp] ---- var result = this._client.Search(s => s .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) @@ -119,7 +117,7 @@ here for each hit we'll call the delegate passed to ConcreteTypeSelector where Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method="usingconcretetypeselector"] +[source,csharp] ---- result.IsValid.Should().BeTrue(); @@ -129,7 +127,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method="usingconcretetypeselector"] +[source,csharp] ---- var aDocuments = result.Documents.OfType(); @@ -146,7 +144,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method="usingconcretetypeselector"] +[source,csharp] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -160,7 +158,7 @@ Scroll also supports CovariantSearchResponses The Scroll API is a continuation of the previous Search example so Types() are lost. You can hint at the types using `.CovariantTypes()` -[source,csharp,method="usingcovarianttypesonscroll"] +[source,csharp] ---- var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) @@ -173,7 +171,7 @@ hits that have "_type" : "a` will be serialized to `A` and so forth Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method="usingcovarianttypesonscroll"] +[source,csharp] ---- result.IsValid.Should().BeTrue(); @@ -183,7 +181,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method="usingcovarianttypesonscroll"] +[source,csharp] ---- var aDocuments = result.Documents.OfType(); @@ -200,7 +198,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method="usingcovarianttypesonscroll"] +[source,csharp] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -211,7 +209,7 @@ cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); The more low level concrete type selector can also be specified on scroll -[source,csharp,method="usingconcretetypeselectoronscroll"] +[source,csharp] ---- var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) @@ -227,7 +225,7 @@ As before, within the delegate passed to `.ConcreteTypeSelector` Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method="usingconcretetypeselectoronscroll"] +[source,csharp] ---- result.IsValid.Should().BeTrue(); @@ -237,7 +235,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method="usingconcretetypeselectoronscroll"] +[source,csharp] ---- var aDocuments = result.Documents.OfType(); @@ -254,7 +252,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method="usingconcretetypeselectoronscroll"] +[source,csharp] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index 9fa339d4c78..65859fb3d09 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -1,5 +1,3 @@ -:section-number: 2.4 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -17,7 +15,7 @@ to your document more succintly here we create a new document path based on Project with the id 1 -[source,csharp,method="fromid"] +[source,csharp] ---- IDocumentPath path = new DocumentPath(1); @@ -28,7 +26,7 @@ Expect(1).WhenSerializing(path.Id); You can still override the inferred index and type name -[source,csharp,method="fromid"] +[source,csharp] ---- path = new DocumentPath(1).Type("project1"); @@ -39,7 +37,7 @@ Expect("project1").WhenSerializing(path.Index); and there is also a static way to describe such paths -[source,csharp,method="fromid"] +[source,csharp] ---- path = DocumentPath.Id(1); @@ -52,14 +50,14 @@ Expect(1).WhenSerializing(path.Id); if you have an instance of your document you can use it as well generate document paths -[source,csharp,method="fromobject"] +[source,csharp] ---- var project = new Project { Name = "hello-world" }; ---- here we create a new document path based on the instance of `Project`, project -[source,csharp,method="fromobject"] +[source,csharp] ---- IDocumentPath path = new DocumentPath(project); @@ -72,7 +70,7 @@ Expect("hello-world").WhenSerializing(path.Id); You can still override the inferred index and type name -[source,csharp,method="fromobject"] +[source,csharp] ---- path = new DocumentPath(project).Type("project1"); @@ -85,7 +83,7 @@ Expect("project1").WhenSerializing(path.Index); and again, there is also a static way to describe such paths -[source,csharp,method="fromobject"] +[source,csharp] ---- path = DocumentPath.Id(project); @@ -100,14 +98,14 @@ DocumentPath p = project; === An example with requests -[source,csharp,method="usingwithrequests"] +[source,csharp] ---- var project = new Project { Name = "hello-world" }; ---- we can see an example of how `DocumentPath` helps your describe your requests more tersely -[source,csharp,method="usingwithrequests"] +[source,csharp] ---- var request = new IndexRequest(2) { Document = project }; @@ -117,7 +115,7 @@ request = new IndexRequest(project) { }; when comparing with the full blown constructor and passing document manually, `DocumentPath`'s benefits become apparent. -[source,csharp,method="usingwithrequests"] +[source,csharp] ---- request = new IndexRequest(IndexName.From(), TypeName.From(), 2) { diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index 660f1a74847..a6d79b098cd 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -1,5 +1,3 @@ -:section-number: 2.1 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -16,14 +14,14 @@ These expressions are assigned to a type called `Field` and there are several wa Using the constructor directly is possible but rather involved -[source,csharp,method="usingconstructors"] +[source,csharp] ---- var fieldString = new Field { Name = "name" }; ---- especially when using C expressions since these can not be simply new'ed -[source,csharp,method="usingconstructors"] +[source,csharp] ---- Expression> expression = p => p.Name; @@ -35,14 +33,14 @@ Expect("name") Therefore you can also implicitly convert strings and expressions to `Field`s -[source,csharp,method="implicitconversion"] +[source,csharp] ---- Field fieldString = "name"; ---- but for expressions this is still rather involved -[source,csharp,method="implicitconversion"] +[source,csharp] ---- Expression> expression = p => p.Name; @@ -55,14 +53,14 @@ Expect("name") to ease creating `Field`s from expressions there is a static Property class you can use -[source,csharp,method="usingstaticpropertyfield"] +[source,csharp] ---- Field fieldString = "name"; ---- but for expressions this is still rather involved -[source,csharp,method="usingstaticpropertyfield"] +[source,csharp] ---- var fieldExpression = Infer.Field(p => p.Name); ---- @@ -70,14 +68,14 @@ var fieldExpression = Infer.Field(p => p.Name); this can be even shortened even further using static imports in c 6 i.e. `using static Nest.Static;` -[source,csharp,method="usingstaticpropertyfield"] +[source,csharp] ---- fieldExpression = Field(p => p.Name); ---- Now this is much much terser then our first example using the constructor! -[source,csharp,method="usingstaticpropertyfield"] +[source,csharp] ---- Expect("name") .WhenSerializing(fieldString) @@ -88,7 +86,7 @@ By default, NEST will camel-case all field names to be more _javascript-y_ using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior -[source,csharp,method="defaultfieldnameinferrer"] +[source,csharp] ---- var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); @@ -97,14 +95,14 @@ setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); However string are *always* passed along verbatim -[source,csharp,method="defaultfieldnameinferrer"] +[source,csharp] ---- setup.Expect("NaMe").WhenSerializing("NaMe"); ---- if you want the same behavior for expressions simply do nothing in the default inferrer -[source,csharp,method="defaultfieldnameinferrer"] +[source,csharp] ---- setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); @@ -115,14 +113,14 @@ setup.Expect("Name").WhenSerializing(Field(p => p.Name)); You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ---- When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ---- @@ -130,7 +128,7 @@ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); NOTE: Similarly, LINQ's `.First()` method also works remember these are expressions and not actual code that will be executed -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); @@ -141,7 +139,7 @@ Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.Fir An indexer on a dictionary is assumed to describe a property name -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); @@ -150,7 +148,7 @@ Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metad A cool feature here is that we'll evaluate variables passed to an indexer -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- var variable = "var"; @@ -162,9 +160,9 @@ Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[va If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow you to analyze a string in a number of different ways, these _"virtual" sub fields do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that -should be mapped and <> +should be mapped and link:../mapping/auto-map[how they are mapped] -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); @@ -181,14 +179,14 @@ Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.M You can even chain `.Suffix()` calls to any depth! -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ---- Variables passed to suffix will be evaluated as well -[source,csharp,method="complexfieldnameexpressions"] +[source,csharp] ---- var suffix = "unanalyzed"; @@ -202,7 +200,7 @@ to a list of fields. Here we have a list of expressions -[source,csharp,method="appendingsuffixtoexpressions"] +[source,csharp] ---- var expressions = new List>> { @@ -215,7 +213,7 @@ var expressions = new List>> and we want to append the suffix "raw" to each -[source,csharp,method="appendingsuffixtoexpressions"] +[source,csharp] ---- var fieldExpressions = expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); @@ -233,7 +231,7 @@ Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); When using NEST's property attributes you can specify a new name for the properties -[source,csharp,method="unknown"] +[source,csharp] ---- public class BuiltIn { @@ -242,7 +240,7 @@ public class BuiltIn } ---- -[source,csharp,method="builtinannotiatons"] +[source,csharp] ---- Expect("naam").WhenSerializing(Field(p => p.Name)); ---- @@ -251,7 +249,7 @@ Starting with NEST 2.x we also ask the serializer if it can resolve the property Here we ask the default `JsonNetSerializer` to resolve a property name and it takes the `JsonPropertyAttribute` into account -[source,csharp,method="unknown"] +[source,csharp] ---- public class SerializerSpecific { @@ -260,7 +258,7 @@ public class SerializerSpecific } ---- -[source,csharp,method="serializerspecificannotations"] +[source,csharp] ---- Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ---- @@ -268,7 +266,7 @@ Expect("nameInJson").WhenSerializing(Field(p => p.Name)); If both a NEST property attribute and a serializer specific attribute are present on a property, NEST takes precedence -[source,csharp,method="unknown"] +[source,csharp] ---- public class Both { @@ -278,7 +276,7 @@ public class Both } ---- -[source,csharp,method="nestattributetakesprecedence"] +[source,csharp] ---- Expect("naam").WhenSerializing(Field(p => p.Name)); @@ -291,7 +289,7 @@ Expect(new Resolution of field names is cached per connection settings instance. To demonstrate, take the following simple POCOs -[source,csharp,method="unknown"] +[source,csharp] ---- class A { public C C { get; set; } } @@ -300,7 +298,7 @@ class B { public C C { get; set; } } class C { public string Name { get; set; } } ---- -[source,csharp,method="expressionsarecachedbutseedifferenttypes"] +[source,csharp] ---- var connectionSettings = TestClient.CreateSettings(forceInMemory: true); @@ -314,7 +312,7 @@ var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); Here we have to similary shaped expressions on coming from A and on from B that will resolve to the same field name, as expected -[source,csharp,method="expressionsarecachedbutseedifferenttypes"] +[source,csharp] ---- fieldNameOnA.Should().Be("c.name"); @@ -324,7 +322,7 @@ fieldNameOnB.Should().Be("c.name"); now we create a new connectionsettings with a remap for C on class A to `d` now when we resolve the field path for A will be different -[source,csharp,method="expressionsarecachedbutseedifferenttypes"] +[source,csharp] ---- var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s .InferMappingFor(m => m @@ -345,7 +343,7 @@ fieldNameOnB.Should().Be("c.name"); however we didn't break inferrence on the first client instance using its separate connectionsettings -[source,csharp,method="expressionsarecachedbutseedifferenttypes"] +[source,csharp] ---- fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); @@ -368,7 +366,7 @@ To wrap up, the precedence in which field names are inferred is: The following example class will demonstrate this precedence -[source,csharp,method="unknown"] +[source,csharp] ---- class Precedence { @@ -399,7 +397,7 @@ class Precedence Here we create a custom serializer that renames any property named `AskSerializer` to `ask` -[source,csharp,method="unknown"] +[source,csharp] ---- class CustomSerializer : JsonNetSerializer { @@ -417,7 +415,7 @@ class CustomSerializer : JsonNetSerializer here we provide an explicit rename of a property on `ConnectionSettings` using `.Rename()` and all properties that are not mapped verbatim should be uppercased -[source,csharp,method="precedenceisasexpected"] +[source,csharp] ---- var usingSettings = WithConnectionSettings(s => s @@ -440,7 +438,7 @@ usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => The same naming rules also apply when indexing a document -[source,csharp,method="precedenceisasexpected"] +[source,csharp] ---- usingSettings.Expect(new [] { diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index 335cc289fe0..48a2fe0e1c8 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -1,5 +1,3 @@ -:section-number: 2.3 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -24,7 +22,7 @@ This is a special box type that you can implicitly convert to from the following Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` -[source,csharp,method="canimplicitlyconverttoid"] +[source,csharp] ---- Id idFromInt = 1; Id idFromLong = 2L; @@ -43,7 +41,7 @@ There is no implicit conversion from any object to Id but we can call `Id.From`. Imagine your codebase has the following type that we want to index into Elasticsearch -[source,csharp,method="unknown"] +[source,csharp] ---- class MyDTO { @@ -56,7 +54,7 @@ class MyDTO By default NEST will try to find a property called `Id` on the class using reflection and create a cached fast func delegate based on the properties getter -[source,csharp,method="cangetidfromdocument"] +[source,csharp] ---- var dto = new MyDTO { @@ -71,7 +69,7 @@ Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); Using the connection settings you can specify a different property that NEST should use to infer the document Id. Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property -[source,csharp,method="cangetidfromdocument"] +[source,csharp] ---- WithConnectionSettings(x => x .InferMappingFor(m => m @@ -85,7 +83,7 @@ IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance with different inference rules -[source,csharp,method="cangetidfromdocument"] +[source,csharp] ---- WithConnectionSettings(x => x .InferMappingFor(m => m @@ -99,7 +97,7 @@ WithConnectionSettings(x => x Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` to the name of the property that should be used for the document id -[source,csharp,method="unknown"] +[source,csharp] ---- [ElasticsearchType(IdProperty = nameof(Name))] class MyOtherDTO @@ -112,7 +110,7 @@ class MyOtherDTO Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` -[source,csharp,method="cangetidfromattribute"] +[source,csharp] ---- var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; @@ -125,7 +123,7 @@ This attribute *is* cached statically/globally, however an inference rule on the still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance that will infer the document id from the property `OtherName`: -[source,csharp,method="cangetidfromattribute"] +[source,csharp] ---- WithConnectionSettings(x => x .InferMappingFor(m => m diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index 56c0715f441..5f3697fe05e 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -1,5 +1,3 @@ -:section-number: 2.5 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -14,7 +12,7 @@ In nest this is encoded using `Indices` Several types implicitly convert to `Indices` -[source,csharp,method="implicitconversionfromstring"] +[source,csharp] ---- Nest.Indices singleIndexFromString = "name"; Nest.Indices multipleIndicesFromString = "name1, name2"; @@ -40,7 +38,7 @@ allWithOthersFromString.Match( to ease creating Field's from expressions there is a static Property class you can use -[source,csharp,method="usingstaticpropertyfield"] +[source,csharp] ---- var all = Nest.Indices.All; diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index 8aa6a57c511..b5de8285d7a 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -1,5 +1,3 @@ -:section-number: 2.2 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -11,7 +9,7 @@ Property names resolve to the last token. An example using the `.Suffix()` extension -[source,csharp,method="propertynamesareresolvedtolasttokenusingsuffix"] +[source,csharp] ---- Expression> expression = p => p.Name.Suffix("raw"); Expect("raw").WhenSerializing(expression); @@ -19,7 +17,7 @@ Expect("raw").WhenSerializing(expression); And an example using the `.ApplySuffix()` extension on lambda expressions -[source,csharp,method="propertynamesareresolvedtolasttokenusingapplysuffix"] +[source,csharp] ---- Expression> expression = p => p.Name; @@ -31,7 +29,7 @@ Expect("raw").WhenSerializing(expression); Property names cannot contain a `.` in order to prevent the potential for collision with a field that may have {ref_current}/_multi_fields.html[`multi_fields`] -[source,csharp,method="stringscontainingdotsisanexception"] +[source,csharp] ---- Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); ---- diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index e78ce57d252..7a18e25b20d 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[[auto-mapping-properties]] +[[auto-map]] == Auto mapping properties When creating a mapping (either when creating an index or via the put mapping API), @@ -17,7 +17,7 @@ For these examples, we'll define two POCOS, `Company`, which has a name and a collection of Employees, and `Employee` which has various properties of different types, and itself has a collection of `Employee` types. -[source,csharp,method="unknown"] +[source,csharp] ---- public class Company { @@ -42,7 +42,7 @@ public class Employee To create a mapping for our Company type, we can use the fluent API and map each property explicitly -[source,csharp,method="mappingmanually"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -75,7 +75,7 @@ This is all fine and dandy and useful for some use cases however in most cases this can become verbose and wieldy. The majority of the time you simply just want to map *all* the properties of a POCO in a single go. -[source,csharp,method="mappingmanually"] +[source,csharp] ---- var expected = new { @@ -121,7 +121,7 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work -[source,csharp,method="usingautomap"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -144,7 +144,7 @@ In this example, * Employees as an object and the remaining string properties as strings. -[source,csharp,method="usingautomap"] +[source,csharp] ---- var expected = new { @@ -248,7 +248,7 @@ Here we are using AutoMap() to automatically map our company type, but then we'r overriding our employee property and making it a `nested` type, since by default, AutoMap() will infer objects as `object`. -[source,csharp,method="overridingautomappedproperties"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -297,7 +297,7 @@ It is also possible to define your mappings using attributes on your POCOS. Whe use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. Here we define the same two types but this time using attributes. -[source,csharp,method="unknown"] +[source,csharp] ---- [ElasticsearchType(Name = "company")] public class CompanyWithAttributes @@ -338,7 +338,7 @@ public class EmployeeWithAttributes Then map the types by calling `.AutoMap()` -[source,csharp,method="usingautomapwithattributes"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -485,7 +485,7 @@ Just as we were able to override the inferred properties in our earlier example, mappings also take precedence over attributes. Therefore we can also override any mappings applied via any attributes defined on the POCO -[source,csharp,method="overridingautomappedattributes"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -660,7 +660,7 @@ Properties on a POCO can be ignored in a few ways: This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` -[source,csharp,method="unknown"] +[source,csharp] ---- [ElasticsearchType(Name = "company")] public class CompanyWithAttributesAndPropertiesToIgnore @@ -679,7 +679,7 @@ public class CompanyWithAttributesAndPropertiesToIgnore All of the properties except `Name` have been ignored in the mapping -[source,csharp,method="ignoringproperties"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -729,7 +729,7 @@ the need to do this, so you can control the recursion depth of `.AutoMap()`. Let's introduce a very simple class, `A`, which itself has a property Child of type `A`. -[source,csharp,method="unknown"] +[source,csharp] ---- public class A { @@ -739,7 +739,7 @@ public class A By default, `.AutoMap()` only goes as far as depth 1 -[source,csharp,method="controllingrecursiondepth"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -749,7 +749,7 @@ var descriptor = new CreateIndexDescriptor("myindex") Thus we do not map properties on the second occurrence of our Child property -[source,csharp,method="controllingrecursiondepth"] +[source,csharp] ---- var expected = new { @@ -774,7 +774,7 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); Now lets specify a maxRecursion of 3 -[source,csharp,method="controllingrecursiondepth"] +[source,csharp] ---- var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -784,7 +784,7 @@ var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") `.AutoMap()` has now mapped three levels of our Child property -[source,csharp,method="controllingrecursiondepth"] +[source,csharp] ---- var expectedWithMaxRecursion = new { @@ -839,7 +839,7 @@ does nothing and acts as a blank canvas for you to implement your own visiting m For instance, lets create a custom visitor that disables doc values for numeric and boolean types. (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) -[source,csharp,method="unknown"] +[source,csharp] ---- public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor { @@ -859,7 +859,7 @@ public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor Now we can pass an instance of our custom visitor to `.AutoMap()` -[source,csharp,method="usingacustompropertyvisitor"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -872,7 +872,7 @@ and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBoo it will apply the transformation defined in each `Visit()` respectively, which in this example disables {ref_current}/doc-values.html[doc values]. -[source,csharp,method="usingacustompropertyvisitor"] +[source,csharp] ---- var expected = new { @@ -919,7 +919,7 @@ You can even take the visitor approach a step further, and instead of visiting o directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types to an Elasticsearch string (`IStringProperty`). -[source,csharp,method="unknown"] +[source,csharp] ---- public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { @@ -928,7 +928,7 @@ public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor } ---- -[source,csharp,method="usingacustompropertyvisitoronpropertyinfo"] +[source,csharp] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 456ea35cf93..769ad663baa 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -9,11 +9,12 @@ Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. +[[connection-strategies]] === Choosing the right Connection Strategy If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` -[source,csharp,method="instantiateusingalldefaults"] +[source,csharp] ---- var client = new ElasticLowLevelClient(); ---- @@ -23,7 +24,7 @@ you will need to pass in some instance of `IConnectionConfigurationValues`. The easiest way to do this is: -[source,csharp,method="instantiatingasinglenodeclient"] +[source,csharp] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -36,7 +37,7 @@ This will still be a non-failover connection, meaning if that `node` goes down t To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. -[source,csharp,method="instantiatingaconnectionpoolclient"] +[source,csharp] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -54,7 +55,7 @@ Be sure to read more about <>(new { size = 12 }); This will only have a value if the client configuration has `DisableDirectStreaming` set -[source,csharp,method="availableoptions"] +[source,csharp] ---- var raw = result.ResponseBodyInBytes; ---- @@ -95,14 +96,14 @@ var raw = result.ResponseBodyInBytes; Please note that using `.DisableDirectStreaming` only makes sense if you need the mapped response **and** the raw response __at the same time__. If you need a only `string` or `byte[]` response simply call -[source,csharp,method="availableoptions"] +[source,csharp] ---- var stringResult = client.Search(new { }); ---- other configuration options -[source,csharp,method="availableoptions"] +[source,csharp] ---- config = config .GlobalQueryStringParameters(new NameValueCollection()) //<1> @@ -124,7 +125,7 @@ config = config NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: -[source,csharp,method="availableoptions"] +[source,csharp] ---- var uri = new Uri("http://username:password@localhost:9200"); @@ -133,6 +134,7 @@ var settings = new ConnectionConfiguration(uri); ...but this may become tedious when using connection pooling with multiple nodes. +[[thrown-exceptions]] === Exceptions There are three category of exceptions that may be thrown: @@ -155,7 +157,7 @@ when an API in the client is misused. These should not be handled as you want t You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. If you have complex logging needs this is a good place to add that in. -[source,csharp,method="onrequestcompletediscalled"] +[source,csharp] ---- var counter = 0; @@ -180,7 +182,7 @@ Here's an example of using `OnRequestCompleted()` for complex logging. Remember, to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` -[source,csharp,method="usingonrequestcompletedforlogging"] +[source,csharp] ---- var list = new List(); @@ -246,6 +248,7 @@ list.ShouldAllBeEquivalentTo(new [] ---- <1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` to make the actual request +[[configuring-ssl]] === Configuring SSL SSL must be configured outside of the client using .NET's @@ -255,7 +258,7 @@ property. The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: -[source,csharp,method="configuringssl"] +[source,csharp] ---- ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; ---- @@ -274,7 +277,7 @@ Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSetti You can inject contract resolved converters by implementing the ContractConverters property This can be much faster then registering them on JsonSerializerSettings.Converters -[source,csharp,method="unknown"] +[source,csharp] ---- public class MyJsonNetSerializer : JsonNetSerializer { @@ -296,7 +299,7 @@ public int CallToContractConverter { get; set; } = 0; You can then register a factory on `ConnectionSettings` to create an instance of your subclass instead. This is **_called once per instance_** of ConnectionSettings. -[source,csharp,method="modifyjsonserializersettingsiscalled"] +[source,csharp] ---- var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index b395f62bafd..72b2c7628e1 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -1,5 +1,3 @@ -:section-number: 1.2 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -26,7 +24,7 @@ Elasticsearch 1.x and 2.x in the same application as the former would require NE Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types -[source,csharp,method="unknown"] +[source,csharp] ---- class AConnectionSettings : ConnectionSettings { @@ -66,7 +64,7 @@ class AConnection : InMemoryConnection `ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` -[source,csharp,method="initialdisposestate"] +[source,csharp] ---- var connection = new AConnection(); var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); @@ -78,7 +76,7 @@ connection.IsDisposed.Should().BeFalse(); Disposing `ConnectionSettings` will dispose the `IConnectionPool` and `IConnection` it has a hold of -[source,csharp,method="disposingsettingsdisposesmovingparts"] +[source,csharp] ---- var connection = new AConnection(); diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index e8c59fb26a3..c2b9f198987 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -1,5 +1,3 @@ -:section-number: 1.3 - :ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current :github: https://github.com/elastic/elasticsearch-net @@ -9,10 +7,11 @@ [[post-data]] == Post data -The low level client allows you to post a `string` or `byte[]` array directly. On top of this if you pass a collection of `strings` or `objects` -they will be serialized in Elasticsearch's special bulk/multi format. +The low level client allows you to post a `string` or `byte[]` array directly. On top of this, +if you pass a collection of `string`s or `object`s they will be serialized +using Elasticsearch's special bulk/multi format. -Even though the argument for `PostData` on the low level client takes a `PostData` +Even 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 completely. You can implicitly convert from the following types @@ -26,7 +25,7 @@ You can implicitly convert from the following types * `object` -[source,csharp,method="implicitconversions"] +[source,csharp] ---- var fromString = ImplicitlyConvertsFrom(@string); @@ -38,19 +37,19 @@ var fromObject = ImplicitlyConvertsFrom(@object); PostData bytes will always be set if it originated from `byte[]` -[source,csharp,method="implicitconversions"] +[source,csharp] ---- fromByteArray.WrittenBytes.Should().BeSameAs(bytes); ---- -[source,csharp,method="writescorrectlyusingbothlowandhighlevelsettings"] +[source,csharp] ---- await this.AssertOn(new ConnectionSettings()); await this.AssertOn(new ConnectionConfiguration()); ---- -[source,csharp,method="implicitconversions"] +[source,csharp] ---- fromString.Type.Should().Be(PostType.LiteralString); fromByteArray.Type.Should().Be(PostType.ByteArray); @@ -71,7 +70,7 @@ fromObject.Type.Should().Be(PostType.Serializable); Although each implicitly types behaves slightly differently -[source,csharp,method="asserton"] +[source,csharp] ---- await Post(() => @string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); @@ -81,7 +80,7 @@ await Post(() => bytes, writes: bytes, storesBytes: true, settings: settings); When passing a list of strings we assume its a list of valid serialized json that we join with newlinefeeds making sure there is a trailing linefeed -[source,csharp,method="asserton"] +[source,csharp] ---- await Post(() => listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); ---- @@ -89,21 +88,21 @@ await Post(() => listOfStrings, writes: multiStringJson, storesBytes: true, sett When passing a list of object we assume its a list of objects we need to serialize individually to json and join with newlinefeeds aking sure there is a trailing linefeed -[source,csharp,method="asserton"] +[source,csharp] ---- await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); ---- In all other cases postdata is serialized as is. -[source,csharp,method="asserton"] +[source,csharp] ---- await Post(() => @object, writes: objectJson, storesBytes: false, settings: settings); ---- If you want to maintain a copy of the request that went out use the following settings -[source,csharp,method="asserton"] +[source,csharp] ---- settings = new ConnectionSettings().DisableDirectStreaming(); ---- @@ -111,26 +110,26 @@ settings = new ConnectionSettings().DisableDirectStreaming(); by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream so we can get hold of the serialized bytes -[source,csharp,method="asserton"] +[source,csharp] ---- await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); ---- this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` -[source,csharp,method="asserton"] +[source,csharp] ---- await Post(() => @object, writes: objectJson, storesBytes: true, settings: settings); ---- -[source,csharp,method="post"] +[source,csharp] ---- PostAssert(postData(), writes, storesBytes, settings); await PostAssertAsync(postData(), writes, storesBytes, settings); ---- -[source,csharp,method="postassert"] +[source,csharp] ---- postData.Write(ms, settings); @@ -143,7 +142,7 @@ postData.WrittenBytes.Should().NotBeNull(); postData.WrittenBytes.Should().BeNull(); ---- -[source,csharp,method="postassertasync"] +[source,csharp] ---- await postData.WriteAsync(ms, settings); diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 3aa2d250253..ca16da3c95d 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -9,7 +9,7 @@ Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface -[source,csharp,method="descriptorshavetobemarkedwithidescriptor"] +[source,csharp] ---- var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() @@ -23,7 +23,7 @@ descriptors.Should().BeEmpty(); Methods taking a func should have that func return an interface -[source,csharp,method="selectorsreturninterface"] +[source,csharp] ---- var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index 61132f0f9a5..264e1c2aa7f 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -7,7 +7,7 @@ [[elastic-client]] == Elastic Client -[source,csharp,method="consistentinitializerparameternames"] +[source,csharp] ---- var requestParametersNotNamedRequest = from m in typeof(IElasticClient).GetMethods() @@ -19,7 +19,7 @@ var requestParametersNotNamedRequest = requestParametersNotNamedRequest.Should().BeEmpty(); ---- -[source,csharp,method="initializerrequestsarenotoptional"] +[source,csharp] ---- var requestParameters = (from m in typeof(IElasticClient).GetMethods() @@ -30,7 +30,7 @@ var requestParameters = requestParameter.HasDefaultValue.Should().BeFalse(); ---- -[source,csharp,method="concreteclientoptionalparametersmatchinterfaceclient"] +[source,csharp] ---- var concreteMethodParametersDoNotMatchInterface = new List(); @@ -56,7 +56,7 @@ concreteMethodParametersDoNotMatchInterface.Add( concreteMethodParametersDoNotMatchInterface.Should().BeEmpty(); ---- -[source,csharp,method="consistentoptionalparametersforsyncandasyncmethods"] +[source,csharp] ---- var methodGroups = from methodInfo in typeof(IElasticClient).GetMethods() @@ -82,7 +82,7 @@ asyncMethod.Parameter.HasDefaultValue.Should().Be(syncMethod.Parameter.HasDefaul $"sync and async versions of {asyncMethod.MethodType} '{nameof(ElasticClient)}{methodGroup.Key}' should match"); ---- -[source,csharp,method="consistentfluentparameternames"] +[source,csharp] ---- var fluentParametersNotNamedSelector = from m in typeof (IElasticClient).GetMethods() @@ -93,7 +93,7 @@ var fluentParametersNotNamedSelector = fluentParametersNotNamedSelector.Should().BeEmpty(); ---- -[source,csharp,method="unknown"] +[source,csharp] ---- private class MethodWithRequestParameter { diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 18e7a9dc7f8..2bf7257b534 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -13,7 +13,7 @@ NEST uses the following naming conventions (with _some_ exceptions). Abstract class names should end with a `Base` suffix -[source,csharp,method="abstractclassnamesendwithbase"] +[source,csharp] ---- var exceptions = new[] { @@ -29,7 +29,7 @@ abstractClasses.Should().BeEmpty(); Class names that end with `Base` suffix are abstract -[source,csharp,method="classnamecontainsbaseshouldbeabstract"] +[source,csharp] ---- var exceptions = new[] { typeof(DateMath) }; @@ -47,7 +47,7 @@ baseClassesNotAbstract.Should().BeEmpty(); Request class names should end with `Request` -[source,csharp,method="requestclassnamesendwithrequest"] +[source,csharp] ---- var types = typeof(IRequest).Assembly().GetTypes(); @@ -63,7 +63,7 @@ requests.Should().BeEmpty(); Response class names should end with `Response` -[source,csharp,method="responseclassnamesendwithresponse"] +[source,csharp] ---- var types = typeof(IRequest).Assembly().GetTypes(); @@ -81,7 +81,7 @@ e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => There are a few exceptions to this rule, most notably the `Cat` prefixed requests and the `Exists` requests. -[source,csharp,method="paritybetweenrequestsandresponses"] +[source,csharp] ---- var exceptions = new[] //<1> { diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index a4522318cf6..7f85834d595 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -7,7 +7,7 @@ [[queries]] == Queries -[source,csharp,method="staticqueryexposesall"] +[source,csharp] ---- var staticProperties = from p in typeof(Query<>).GetMethods() let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name @@ -18,7 +18,7 @@ var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("Geo staticProperties.Distinct().Should().Contain(placeHolders.Distinct()); ---- -[source,csharp,method="fluentdescriptorexposesall"] +[source,csharp] ---- var fluentMethods = from p in typeof(QueryContainerDescriptor<>).GetMethods() let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name @@ -29,7 +29,7 @@ var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("Geo fluentMethods.Distinct().Should().Contain(placeHolders.Distinct()); ---- -[source,csharp,method="visitorvisitsall"] +[source,csharp] ---- var skipQueryImplementations = new[] { typeof(IFieldNameQuery), typeof(IFuzzyQuery<,>), typeof(IConditionlessQuery) }; @@ -52,7 +52,7 @@ var missingTypes = from q in queries missingTypes.Should().BeEmpty(); ---- -[source,csharp,method="interfacepropertiesmustbemarkedexplicitly"] +[source,csharp] ---- var properties = from p in QueryProperties let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index baef32efdad..8f8c908902e 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -9,7 +9,7 @@ Our Json.NET contract resolver picks up attributes set on the interface -[source,csharp,method="seesinterfaceproperties"] +[source,csharp] ---- var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(pool, new InMemoryConnection()); diff --git a/docs/asciidoc/common-options.asciidoc b/docs/asciidoc/common-options.asciidoc index e44f0938f07..5e99213dd2a 100644 --- a/docs/asciidoc/common-options.asciidoc +++ b/docs/asciidoc/common-options.asciidoc @@ -1,7 +1,12 @@ :output-dir: common-options [[common-options]] -== Common Options += Common Options + +[partintro] +-- +Something about the convenience types for working with time and distance units and date math expressions +-- include::{output-dir}/time-unit/time-units.asciidoc[] diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index 5a04dd6a7e1..5359dd44348 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -38,7 +38,7 @@ Be sure to read the elasticsearch documentation {datemath}[on this subject here] You can create simple expressions using any of the static methods on `DateMath` -[source,csharp,method="simpleexpressions"] +[source,csharp] ---- Expect("now").WhenSerializing(Nest.DateMath.Now); @@ -47,21 +47,21 @@ Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTim strings implicitly convert to `DateMath` -[source,csharp,method="simpleexpressions"] +[source,csharp] ---- Expect("now").WhenSerializing("now"); ---- but are lenient to bad math expressions -[source,csharp,method="simpleexpressions"] +[source,csharp] ---- var nonsense = "now||*asdaqwe"; ---- the resulting date math will assume the whole string is the anchor -[source,csharp,method="simpleexpressions"] +[source,csharp] ---- Expect(nonsense).WhenSerializing(nonsense) .Result(dateMath => ((IDateMath)dateMath) @@ -74,14 +74,14 @@ Expect(nonsense).WhenSerializing(nonsense) `DateTime` also implicitly convert to simple date math expressions -[source,csharp,method="simpleexpressions"] +[source,csharp] ---- var date = new DateTime(2015, 05, 05); ---- the anchor will be an actual `DateTime`, even after a serialization/deserialization round trip -[source,csharp,method="simpleexpressions"] +[source,csharp] ---- Expect("2015-05-05T00:00:00").WhenSerializing(date) .Result(dateMath => ((IDateMath)dateMath) @@ -96,21 +96,21 @@ Expect("2015-05-05T00:00:00").WhenSerializing(date) Ranges can be chained on to simple expressions -[source,csharp,method="complexexpressions"] +[source,csharp] ---- Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); ---- Including multiple operations -[source,csharp,method="complexexpressions"] +[source,csharp] ---- Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); ---- A rounding value can be chained to the end of the expression, after which no more ranges can be appended -[source,csharp,method="complexexpressions"] +[source,csharp] ---- Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); ---- @@ -118,7 +118,7 @@ Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeS When anchoring dates, a `||` needs to be appended as clear separator between the anchor and ranges. Again, multiple ranges can be chained -[source,csharp,method="complexexpressions"] +[source,csharp] ---- Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); ---- diff --git a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc index a662dca20f1..818a5eda9e4 100644 --- a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc +++ b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc @@ -19,7 +19,7 @@ NEST uses `Distance` to strongly type distance units and there are several ways The most straight forward way to construct a `Distance` is through its constructor -[source,csharp,method="constructor"] +[source,csharp] ---- var unitComposed = new Nest.Distance(25); var unitComposedWithUnits = new Nest.Distance(25, Nest.DistanceUnit.Meters); @@ -28,7 +28,7 @@ var unitComposedWithUnits = new Nest.Distance(25, Nest.DistanceUnit.Meters); `Distance` serializes to a string composed of a factor and distance unit. The factor is a double so always has at least one decimal place when serialized -[source,csharp,method="constructor"] +[source,csharp] ---- Expect("25.0m") .WhenSerializing(unitComposed) @@ -40,7 +40,7 @@ Expect("25.0m") Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. If no `DistanceUnit` is specified, the default distance unit is meters -[source,csharp,method="implicitconversion"] +[source,csharp] ---- Nest.Distance distanceString = "25"; @@ -59,28 +59,28 @@ A number of distance units are supported, from millimeters to nautical miles `mm` (Millimeters) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("2.0mm").WhenSerializing(new Nest.Distance(2, Nest.DistanceUnit.Millimeters)); ---- `cm` (Centimeters) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, Nest.DistanceUnit.Centimeters)); ---- `m` (Meters) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("400.0m").WhenSerializing(new Nest.Distance(400, Nest.DistanceUnit.Meters)); ---- `km` (Kilometers) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilometers)); ---- @@ -89,35 +89,35 @@ Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilomet `in` (Inches) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, Nest.DistanceUnit.Inch)); ---- `ft` (Feet) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, Nest.DistanceUnit.Feet)); ---- `yd` (Yards) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("9.0yd").WhenSerializing(new Nest.Distance(9, Nest.DistanceUnit.Yards)); ---- `mi` (Miles) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, Nest.DistanceUnit.Miles)); ---- `nmi` or `NM` (Nautical Miles) -[source,csharp,method="usingdifferentunits"] +[source,csharp] ---- Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, Nest.DistanceUnit.NauticalMiles)); ---- diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index 6e2cf5c5e35..38fd60e1977 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -18,7 +18,7 @@ NEST uses `Time` to strongly type this and there are several ways to construct o The most straight forward way to construct a `Time` is through its constructor -[source,csharp,method="constructor"] +[source,csharp] ---- var unitString = new Time("2d"); var unitComposed = new Time(2, Nest.TimeUnit.Day); @@ -38,7 +38,7 @@ When serializing Time constructed from the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` -[source,csharp,method="constructor"] +[source,csharp] ---- Expect("2d") .WhenSerializing(unitString) @@ -49,7 +49,7 @@ Expect("2d") The `Milliseconds` property on `Time` is calculated even when not using the constructor that takes a double -[source,csharp,method="constructor"] +[source,csharp] ---- unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); @@ -62,7 +62,7 @@ unitString.Milliseconds.Should().Be(1000*60*60*24*2); Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` -[source,csharp,method="implicitconversion"] +[source,csharp] ---- Time oneAndHalfYear = "1.5y"; @@ -77,7 +77,7 @@ Expect("2w").WhenSerializing(twoWeeks); Expect("2d").WhenSerializing(twoDays); ---- -[source,csharp,method="equalityandcomparable"] +[source,csharp] ---- Time oneAndHalfYear = "1.5y"; @@ -89,7 +89,7 @@ Time twoDays = 1000*60*60*24*2; Again, the `Milliseconds` property is calculated on `Time`, allowing you to do comparisons -[source,csharp,method="equalityandcomparable"] +[source,csharp] ---- oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); @@ -114,7 +114,7 @@ twoDays.Should().BeLessThan(twoWeeks); And assert equality -[source,csharp,method="equalityandcomparable"] +[source,csharp] ---- twoDays.Should().Be(new Time("2d")); @@ -130,7 +130,7 @@ twoDays.Should().Be(new Time("2d")); Time units are specified as a union of either a `DateInterval` or `Time`, both of which implicitly convert to the `Union` of these two. -[source,csharp,method="usinginterval"] +[source,csharp] ---- Expect("month").WhenSerializing>(DateInterval.Month); diff --git a/docs/asciidoc/connection-pooling.asciidoc b/docs/asciidoc/connection-pooling.asciidoc index 83cf15af019..759505a124d 100644 --- a/docs/asciidoc/connection-pooling.asciidoc +++ b/docs/asciidoc/connection-pooling.asciidoc @@ -1,4 +1,4 @@ -:output-dir:client-concepts/connection-pooling +:output-dir: client-concepts/connection-pooling :building-blocks: {output-dir}/building-blocks :sniffing: {output-dir}/sniffing :pinging: {output-dir}/pinging diff --git a/docs/asciidoc/high-level.asciidoc b/docs/asciidoc/high-level.asciidoc index 222038941c6..6cab2b234d9 100644 --- a/docs/asciidoc/high-level.asciidoc +++ b/docs/asciidoc/high-level.asciidoc @@ -3,6 +3,19 @@ [[high-level]] == High Level +A high level client that provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL +and takes advantage of specific .NET features such as covariant results. + +NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> + +There are a number of conventions that NEST uses for inference of + +- Field and Property names +- Document ids +- Building a URI path to a document +- Building a URI path to one or more indices +- Inferring + include::{output-dir}/inference/field-inference.asciidoc[] include::{output-dir}/inference/property-inference.asciidoc[] diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 0dbcfe2affd..212cd2f5d73 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -1,5 +1,5 @@ [[elasticsearch-net-reference]] -= Elasticsearch.Net and NEST, the .NET Elasticsearch clients += Elasticsearch.Net and NEST: the .NET Elasticsearch clients include::intro.asciidoc[] diff --git a/docs/asciidoc/intro.asciidoc b/docs/asciidoc/intro.asciidoc index 897e079d6ba..0b41b0b3bd4 100644 --- a/docs/asciidoc/intro.asciidoc +++ b/docs/asciidoc/intro.asciidoc @@ -1,6 +1,7 @@ :github: https://github.com/elastic/elasticsearch-net :stackoverflow: http://stackoverflow.com +[[introduction]] == Introduction You've reached the documentation page for `Elasticsearch.Net` and `NEST`. The two official .NET clients for Elasticsearch. So why two clients I hear you say? @@ -13,10 +14,10 @@ enough so that **all** the Elasticsearch API endpoints are represented as method Please read the getting started guide for both. === Who's using Nest -* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). -* http://www.7digital.com[7digital.com] (run NEST on mono). -* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). -* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. +- {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). +- http://www.7digital.com[7digital.com] (run NEST on mono). +- https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). +- http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] === Other resources @@ -29,10 +30,10 @@ with their https://github.com/searchbox-io/.net-sample[demo project] === Questions, bugs, comments, requests -All of these are more then welcome on the {github}/issues[github issues pages]! We try to to at least reply within the same day. +All of these are more then welcome on the {github}/issues[github issues pages]! We try to at least reply within the same day. We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or -{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow] +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow], as well as https://discuss.elastic.co[discussions on our discourse site] === License diff --git a/docs/asciidoc/low-level.asciidoc b/docs/asciidoc/low-level.asciidoc index 4673d5969f7..78b02a70ded 100644 --- a/docs/asciidoc/low-level.asciidoc +++ b/docs/asciidoc/low-level.asciidoc @@ -3,6 +3,18 @@ [[low-level]] == Low Level +The low level client, `ElasticLowLevelClient`, is a low level, dependency free client that has no +opinions about how you build and represent your requests and responses. + +It can be installed from the Package Manager Console inside Visual Studio using + +[source, shell] +---- +Install-Package Elasticsearch.Net +---- + +Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[`Elasticsearch.Net`] in the Package Manager GUI. + include::{output-dir}/connecting.asciidoc[] include::{output-dir}/lifetimes.asciidoc[] diff --git a/docs/asciidoc/query-dsl.asciidoc b/docs/asciidoc/query-dsl.asciidoc index b28b7c831e3..76eedce8e11 100644 --- a/docs/asciidoc/query-dsl.asciidoc +++ b/docs/asciidoc/query-dsl.asciidoc @@ -1,7 +1,12 @@ :output-dir: query-dsl [[query-dsl]] -== Query DSL += Query DSL + +[partintro] +-- +Something about the query DSL +-- include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index e1eb01de828..47cea117308 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -10,7 +10,7 @@ Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses -[source,csharp,method="verboseway"] +[source,csharp] ---- var searchResults = this.Client.Search(s => s .Query(q => q @@ -35,7 +35,7 @@ image::{imagesdir}/hadouken-indentation.jpg[dead indent] For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. The previous example now becomes the following with the fluent API -[source,csharp,method="usingoperator"] +[source,csharp] ---- var searchResults = this.Client.Search(s => s .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) @@ -44,7 +44,7 @@ var searchResults = this.Client.Search(s => s or, using the object initializer syntax -[source,csharp,method="usingoperator"] +[source,csharp] ---- searchResults = this.Client.Search(new SearchRequest { @@ -99,7 +99,7 @@ bool |___term .... -[source,csharp,method="joinsmustwithmustnot"] +[source,csharp] ---- Assert( q => q.Query() && q.Query() && q.Query() && !q.Query(), @@ -157,7 +157,7 @@ Here we demonstrate that two locked `bool` queries are not combined neither are two `bool` queries where either the left or the right query is locked -[source,csharp,method="assertdoesnotjoinontolockedbool"] +[source,csharp] ---- c.Bool.Should.Should().HaveCount(2); @@ -168,7 +168,7 @@ nestedBool.Bool.Should.Should().HaveCount(1); nestedBool.Bool.Name.Should().Be(firstName); ---- -[source,csharp,method="assert"] +[source,csharp] ---- assert(fluent.InvokeQuery(new QueryContainerDescriptor())); diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc index 6d547aceb75..f136ee3242d 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -7,14 +7,14 @@ [[and-operator-usage]] == And Operator Usage -[source,csharp,method="combiningmanyusingaggregate"] +[source,csharp] ---- var lotsOfAnds = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q && Query, q => q); LotsOfAnds(lotsOfAnds); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +[source,csharp] ---- QueryContainer container = null; @@ -23,7 +23,7 @@ container &= Query; LotsOfAnds(container); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +[source,csharp] ---- var container = new QueryContainer(); @@ -32,7 +32,7 @@ container &= Query; LotsOfAnds(container); ---- -[source,csharp,method="lotsofands"] +[source,csharp] ---- lotsOfAnds.Should().NotBeNull(); @@ -41,7 +41,7 @@ lotsOfAnds.Bool.Should().NotBeNull(); lotsOfAnds.Bool.Must.Should().NotBeEmpty().And.HaveCount(100); ---- -[source,csharp,method="and"] +[source,csharp] ---- ReturnsBool(Query && Query, q => q.Query() && q.Query(), b => { diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc index c3754483818..133d6f59bcd 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -7,14 +7,14 @@ [[not-operator-usage]] == Not Operator Usage -[source,csharp,method="combiningmanyusingaggregate"] +[source,csharp] ---- var lotsOfNots = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q || Query, q => q); LotsOfNots(lotsOfNots); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +[source,csharp] ---- QueryContainer container = null; @@ -23,7 +23,7 @@ container |= Query; LotsOfNots(container); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +[source,csharp] ---- var container = new QueryContainer(); @@ -32,7 +32,7 @@ container |= Query; LotsOfNots(container); ---- -[source,csharp,method="lotsofnots"] +[source,csharp] ---- lotsOfNots.Should().NotBeNull(); @@ -41,7 +41,7 @@ lotsOfNots.Bool.Should().NotBeNull(); lotsOfNots.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); ---- -[source,csharp,method="not"] +[source,csharp] ---- ReturnsBool(!Query && !Query, q => !q.Query() && !q.Query(), b => { diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc index 8c7398f4d6c..61b7a569850 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -7,14 +7,14 @@ [[or-operator-usage]] == Or Operator Usage -[source,csharp,method="combiningmanyusingaggregate"] +[source,csharp] ---- var lotsOfOrs = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q || Query, q => q); LotsOfOrs(lotsOfOrs); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +[source,csharp] ---- QueryContainer container = null; @@ -23,7 +23,7 @@ container |= Query; LotsOfOrs(container); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +[source,csharp] ---- var container = new QueryContainer(); @@ -32,7 +32,7 @@ container |= Query; LotsOfOrs(container); ---- -[source,csharp,method="lotsofors"] +[source,csharp] ---- lotsOfOrs.Should().NotBeNull(); @@ -41,7 +41,7 @@ lotsOfOrs.Bool.Should().NotBeNull(); lotsOfOrs.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); ---- -[source,csharp,method="or"] +[source,csharp] ---- ReturnsBool(Query || Query, q => q.Query() || q.Query(), b => { diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc index 41537ca3090..7ce758c31bb 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -7,14 +7,14 @@ [[unary-add-operator-usage]] == Unary Add Operator Usage -[source,csharp,method="combiningmanyusingaggregate"] +[source,csharp] ---- var lotsOfUnaryAdds = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q && +Query, q => q); LotsOfUnaryAdds(lotsOfUnaryAdds); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +[source,csharp] ---- QueryContainer container = null; @@ -23,7 +23,7 @@ container &= +Query; LotsOfUnaryAdds(container); ---- -[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +[source,csharp] ---- var container = new QueryContainer(); @@ -32,7 +32,7 @@ container &= +Query; LotsOfUnaryAdds(container); ---- -[source,csharp,method="lotsofunaryadds"] +[source,csharp] ---- lotsOfUnaryAdds.Should().NotBeNull(); @@ -41,7 +41,7 @@ lotsOfUnaryAdds.Bool.Should().NotBeNull(); lotsOfUnaryAdds.Bool.Filter.Should().NotBeEmpty().And.HaveCount(100); ---- -[source,csharp,method="combindingmanyboolfiltersusingorsshouldflatten"] +[source,csharp] ---- var container = new QueryContainer(); @@ -52,7 +52,7 @@ var c = container as IQueryContainer; c.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); ---- -[source,csharp,method="unaryadd"] +[source,csharp] ---- ReturnsBool(+Query && +Query, q => +q.Query() && +q.Query(), b => { diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index f2c0b70f55b..1668a42e3fc 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -7,7 +7,7 @@ [[and-query-usage]] == And Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -32,7 +32,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new AndQuery() { diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc index 69b0b1eea6d..4337f66928f 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -7,7 +7,7 @@ [[bool-dsl-complex-query-usage]] == Bool Dsl Complex Query Usage -[source,csharp,method="queryjson"] +[source,csharp] ---- new { @@ -67,7 +67,7 @@ new === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- Query && Query //second bool @@ -82,7 +82,7 @@ Query && Query && (base.QueryInitializer)) ---- -[source,csharp,method="assertshape"] +[source,csharp] ---- container.Bool.Should().NotBeNull(); @@ -131,7 +131,7 @@ mustNotsBool.Should().NotBeNull(); mustNotsBool.MustNot.Should().HaveCount(2); //one of the three must nots was conditionless ---- -[source,csharp,method="asssertshape"] +[source,csharp] ---- this.AssertShape(this.QueryInitializer); ---- diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc index 7aba910b4c2..7d6c00be7dd 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -7,7 +7,7 @@ [[bool-query-usage]] == Bool Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -40,7 +40,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new BoolQuery() { diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc index e7a5cd84fed..2dce428df0f 100644 --- a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -7,7 +7,7 @@ [[boosting-query-usage]] == Boosting Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -31,7 +31,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new BoostingQuery() { diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc index 0978f647ad3..cbacc576cc4 100644 --- a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -7,7 +7,7 @@ [[constant-score-query-usage]] == Constant Score Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -25,7 +25,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new ConstantScoreQuery() { diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc index c5c524c5efa..d81f9d925a2 100644 --- a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -7,7 +7,7 @@ [[dismax-query-usage]] == Dismax Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -33,7 +33,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new DisMaxQuery() { diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc index 6d4bff90e40..669de744e80 100644 --- a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -7,7 +7,7 @@ [[filtered-query-usage]] == Filtered Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -30,7 +30,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new FilteredQuery() { diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc index b9c76cf5599..e66783d641a 100644 --- a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -7,7 +7,7 @@ [[function-score-query-usage]] == Function Score Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -88,7 +88,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new FunctionScoreQuery() { diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc index 0b9398cb5d3..99785e232c3 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -7,7 +7,7 @@ [[indices-no-match-query-usage]] == Indices No Match Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -27,7 +27,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new IndicesQuery() { diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc index 65a64134ba8..eac9c0facde 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -7,7 +7,7 @@ [[indices-query-usage]] == Indices Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -31,7 +31,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new IndicesQuery() { diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc index b7191261fea..53ccae233be 100644 --- a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -7,7 +7,7 @@ [[limit-query-usage]] == Limit Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -21,7 +21,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new LimitQuery { diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc index ec0b2c6808a..c7b11df6810 100644 --- a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -7,7 +7,7 @@ [[not-query-usage]] == Not Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -32,7 +32,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new NotQuery() { diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc index c459f7eb9c3..c03456414ab 100644 --- a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -7,7 +7,7 @@ [[or-query-usage]] == Or Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -32,7 +32,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new OrQuery() { diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc index 83e82562840..dbe47dd5d8e 100644 --- a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -7,7 +7,7 @@ [[common-terms-usage]] == Common Terms Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -29,7 +29,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new CommonTermsQuery() { diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc index 87a117e6d21..5d4f532df1e 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -7,7 +7,7 @@ [[match-phrase-prefix-usage]] == Match Phrase Prefix Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -35,7 +35,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new MatchPhrasePrefixQuery { diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc index 737199532e9..266a5cc97ea 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -7,7 +7,7 @@ [[match-phrase-usage]] == Match Phrase Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -35,7 +35,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new MatchPhraseQuery { diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc index ae33e0db0b2..c592c6231d0 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -7,7 +7,7 @@ [[match-usage]] == Match Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -34,7 +34,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new MatchQuery { diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index 59a816ede6c..4fcf3b0e86e 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -7,7 +7,7 @@ [[multi-match-usage]] == Multi Match Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -37,7 +37,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new MultiMatchQuery { diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc index 9e013f3a112..7bafe33fc63 100644 --- a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -7,7 +7,7 @@ [[query-string-usage]] == Query String Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -48,7 +48,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new QueryStringQuery { diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc index 0fb8a28ed17..6a7558ba504 100644 --- a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -7,7 +7,7 @@ [[simple-query-string-usage]] == Simple Query String Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -33,7 +33,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SimpleQueryStringQuery { diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc index c7a4deeaafb..01d5587519c 100644 --- a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -7,7 +7,7 @@ [[geo-bounding-box-query-usage]] == Geo Bounding Box Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -34,7 +34,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoBoundingBoxQuery { diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc index deae85e0cbe..09b052a0f20 100644 --- a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -7,7 +7,7 @@ [[geo-distance-range-query-usage]] == Geo Distance Range Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -33,7 +33,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoDistanceRangeQuery { diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc index 04d7119bf77..7788884d30f 100644 --- a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -7,7 +7,7 @@ [[geo-distance-query-usage]] == Geo Distance Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -30,7 +30,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoDistanceQuery { diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc index e34509d09e9..8f8d6807e2e 100644 --- a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -7,7 +7,7 @@ [[geo-hash-cell-query-usage]] == Geo Hash Cell Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -26,7 +26,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoHashCellQuery { diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc index 8952ee70180..8e8498fdc6f 100644 --- a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -7,7 +7,7 @@ [[geo-polygon-query-usage]] == Geo Polygon Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -35,7 +35,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoPolygonQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc index 889412e214e..eeffd525250 100644 --- a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapeCircleQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc index f467a22e227..816c32f8773 100644 --- a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapeEnvelopeQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc index e93b248f02f..9f1dce81b18 100644 --- a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -7,7 +7,7 @@ [[geo-indexed-shape-usage]] == Geo Indexed Shape Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoIndexedShapeQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc index 013c253a4de..fe4963633ef 100644 --- a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapeLineStringQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc index 2cbdb4d990b..a03ecf55b7e 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapeMultiLineStringQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc index 9ebf1bda6e5..f3354832e5c 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapeMultiPointQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc index f6cc8ceb2bb..9aa1c7eaae4 100644 --- a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapePointQuery { diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc index 2cbac5505f7..252ee65cdd2 100644 --- a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new GeoShapePolygonQuery { diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc index 8ed18e8cef5..447ae857dd5 100644 --- a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -7,7 +7,7 @@ [[has-child-query-usage]] == Has Child Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -30,7 +30,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new HasChildQuery { diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc index e2b6a770993..871de853fb3 100644 --- a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -7,7 +7,7 @@ [[has-parent-query-usage]] == Has Parent Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new HasParentQuery { diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc index dd0b7a4907b..d51592548e2 100644 --- a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -7,7 +7,7 @@ [[nested-query-usage]] == Nested Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -27,7 +27,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new NestedQuery { diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc index dd98e17984f..ec76753e7c8 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -7,7 +7,7 @@ [[raw-combine-usage]] == Raw Combine Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -32,7 +32,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new RawQuery(RawTermQuery) && new TermQuery { Field = "x", Value = "y" } diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc index f5dc61e59d4..baa817e6656 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -7,7 +7,7 @@ [[raw-query-usage]] == Raw Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -19,7 +19,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new RawQuery(RawTermQuery) ---- diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc index 12cc776f2bf..65913dee504 100644 --- a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-containing-query-usage]] == Span Containing Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -34,7 +34,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanContainingQuery { diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc index e5bf822ef52..72d0c668170 100644 --- a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-first-query-usage]] == Span First Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanFirstQuery { diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc index b2085cc19df..7eb10ed85fd 100644 --- a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-multi-term-query-usage]] == Span Multi Term Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -27,7 +27,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanMultiTermQuery { diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc index 0583bdb4375..075ded4b988 100644 --- a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-near-query-usage]] == Span Near Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -46,7 +46,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanNearQuery { diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc index 4acc6a8feac..83c36eec47c 100644 --- a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-not-query-usage]] == Span Not Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -37,7 +37,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanNotQuery { diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc index 3445a54c792..c8e2d30bdec 100644 --- a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-or-query-usage]] == Span Or Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -43,7 +43,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanOrQuery { diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc index a481650186c..0200123444f 100644 --- a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-term-query-usage]] == Span Term Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -23,7 +23,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanTermQuery { diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc index e869871974c..cbfea519677 100644 --- a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -7,7 +7,7 @@ [[span-within-query-usage]] == Span Within Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -34,7 +34,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new SpanWithinQuery { diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc index 87c2f8624a4..99db1c33c50 100644 --- a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -7,7 +7,7 @@ [[more-like-this-query-usage]] == More Like This Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -48,7 +48,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new MoreLikeThisQuery { diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc index 438d1b9b90e..faa6fa0244b 100644 --- a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -7,7 +7,7 @@ [[script-query-usage]] == Script Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -24,7 +24,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new ScriptQuery { diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc index 8fd8ac63ad1..62c52762f3e 100644 --- a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -7,7 +7,7 @@ [[template-query-usage]] == Template Query Usage -[source,csharp,method="queryjson"] +[source,csharp] ---- new { @@ -28,7 +28,7 @@ template = new === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new TemplateQuery { diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc index be7705f60dc..00e43fef34c 100644 --- a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -7,7 +7,7 @@ [[exists-query-usage]] == Exists Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -21,7 +21,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new ExistsQuery { diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc index 446b36e46d9..31b1b0a2c4d 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -7,7 +7,7 @@ [[fuzzy-date-query-usage]] == Fuzzy Date Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new FuzzyDateQuery { diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc index 1a6b6055e29..bf5258b4ff0 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -7,7 +7,7 @@ [[fuzzy-numeric-query-usage]] == Fuzzy Numeric Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new FuzzyNumericQuery { diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc index b256c74e907..ea6d5656dc0 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -7,7 +7,7 @@ [[fuzzy-query-usage]] == Fuzzy Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new FuzzyQuery { diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc index 52917ef39dd..7de48d9906f 100644 --- a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -7,7 +7,7 @@ [[ids-query-usage]] == Ids Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -30,7 +30,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new IdsQuery { diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc index 1157e54b450..aa2ee79493f 100644 --- a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -7,7 +7,7 @@ [[missing-query-usage]] == Missing Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -23,7 +23,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new MissingQuery { diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc index 23dfbccfa36..ea0ed815b9c 100644 --- a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -7,7 +7,7 @@ [[prefix-query-usage]] == Prefix Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -24,7 +24,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new PrefixQuery { diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc index e6d9f43444a..d473cfbbd0f 100644 --- a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -7,7 +7,7 @@ [[date-range-query-usage]] == Date Range Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -28,7 +28,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new DateRangeQuery { diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc index fcfde48504c..e635e8b51a7 100644 --- a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -7,7 +7,7 @@ [[numeric-range-query-usage]] == Numeric Range Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -26,7 +26,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new NumericRangeQuery { diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc index 91a916a4c05..a983edd09da 100644 --- a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -7,7 +7,7 @@ [[term-range-query-usage]] == Term Range Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -26,7 +26,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new TermRangeQuery { diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc index 8f138d1115d..3f67103763a 100644 --- a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -7,7 +7,7 @@ [[regexp-query-usage]] == Regexp Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -25,7 +25,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new RegexpQuery { diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc index fe3f3532793..ba19b2c31fd 100644 --- a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -7,7 +7,7 @@ [[term-query-usage]] == Term Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -23,7 +23,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new TermQuery { diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc index 1ea0d3eb828..d5284bbb43a 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -7,7 +7,7 @@ [[terms-lookup-query-usage]] == Terms Lookup Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -26,7 +26,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new TermsQuery { diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc index 58ae3274329..4db3031ad70 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -7,7 +7,7 @@ [[terms-query-usage]] == Terms Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -26,7 +26,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new TermsQuery { diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc index 45e4d940b9e..bc6d60b8ddd 100644 --- a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -7,7 +7,7 @@ [[type-query-usage]] == Type Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -21,7 +21,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new TypeQuery { diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc index 19e868b221f..55e02f8fad4 100644 --- a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -7,7 +7,7 @@ [[wildcard-query-usage]] == Wildcard Query Usage -[source,javascript,method="queryjson"] +[source,javascript] .Example json output ---- { @@ -24,7 +24,7 @@ === Object Initializer Syntax Example -[source,csharp,method="queryinitializer"] +[source,csharp] ---- new WildcardQuery { diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc index fda74d97064..93165b70a96 100644 --- a/docs/asciidoc/search/request/explain-usage.asciidoc +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -11,7 +11,7 @@ Enables explanation for each hit on how its score was computed. === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Explain() @@ -19,12 +19,12 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { Explain = true } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index ac86e8e4ade..14568bb4a10 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .FielddataFields(fs => fs @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -29,7 +29,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index 86017fb63ed..db46b6e9093 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Fields(fs => fs @@ -20,7 +20,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -28,7 +28,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index 0dddbb6382b..fe4a86b80a3 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -18,7 +18,7 @@ new SearchRequest() } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -29,7 +29,7 @@ new SearchRequest() === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .From(10) diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index 60eb6d1f657..55b36c6bec2 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Query(q => q @@ -60,7 +60,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -113,7 +113,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -179,7 +179,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); highlight.Should().Contain(""); diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index e3a4db4bb26..05e71818874 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .IndicesBoost(b => b @@ -20,7 +20,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -32,7 +32,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc index 589466aa280..09b816231ba 100644 --- a/docs/asciidoc/search/request/inner-hits-usage.asciidoc +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -7,7 +7,7 @@ [[inner-hits-usage]] == Inner Hits Usage -[source,csharp,method="unknown"] +[source,csharp] ---- public interface IRoyal { @@ -15,7 +15,7 @@ string Name { get; set; } } ---- -[source,csharp,method="indexall"] +[source,csharp] ---- var current = create(); @@ -28,7 +28,7 @@ bulk.Index(i => i.Document(royal1).Index(this._index).Parent(parent)); indexChildren(royal); ---- -[source,csharp,method="seed"] +[source,csharp] ---- var create = this._client.CreateIndex(this._index, c => c .Settings(s => s @@ -70,7 +70,7 @@ this._client.Refresh(this._index); === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Index(Index) @@ -87,7 +87,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest(Index, typeof(Duke)) { @@ -112,7 +112,7 @@ InnerHits = new NamedInnerHits } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -140,7 +140,7 @@ InnerHits = new NamedInnerHits === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Index(Index) @@ -158,7 +158,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest(Index, typeof(King)) { @@ -176,7 +176,7 @@ Query = new HasChildQuery } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index f2a20a81f42..0dae179eadf 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .MinScore(0.5) @@ -20,7 +20,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -33,7 +33,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index 03746532e91..b652d34172a 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -9,7 +9,7 @@ === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest() { @@ -17,7 +17,7 @@ new SearchRequest() } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -29,7 +29,7 @@ new SearchRequest() === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .PostFilter(f => f.MatchAll()) diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index 97cc33258f5..c8621871eb3 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -11,7 +11,7 @@ The query element within the search request body allows to define a query using === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Query(q => q @@ -21,7 +21,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -33,7 +33,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index 951bd716773..dd087a27bb8 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -9,7 +9,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .ScriptFields(sf=>sf @@ -27,7 +27,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -48,7 +48,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 3bdae6f0d0f..806b1a11633 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -12,7 +12,7 @@ The sort is defined on a per field level, with special field name for score to s === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Sort(ss => ss @@ -50,7 +50,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -94,7 +94,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index 765af845398..981f31df0f4 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -13,7 +13,7 @@ By default operations return the contents of the _source field unless === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Source(so => so @@ -28,7 +28,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -39,7 +39,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { @@ -54,7 +54,7 @@ new SearchRequest === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- response.IsValid.Should().BeTrue(); document.Name.Should().NotBeNull(); @@ -62,7 +62,7 @@ document.StartedOn.Should().NotBe(default(DateTime)); document.Description.Should().BeNull(); ---- -[source,csharp,method="unknown"] +[source,csharp] ---- internal class WithSourceFilterProperty { @@ -71,7 +71,7 @@ internal class WithSourceFilterProperty } ---- -[source,csharp,method="candeserializeboolean"] +[source,csharp] ---- var o = base.Deserialize("{ \"_source\": false }"); @@ -82,7 +82,7 @@ o.SourceFilter.Should().NotBeNull(); o.SourceFilter.Exclude.Should().Contain("*"); ---- -[source,csharp,method="candeserializearray"] +[source,csharp] ---- var o = base.Deserialize("{ \"_source\": [\"obj.*\"] }"); @@ -93,7 +93,7 @@ o.SourceFilter.Should().NotBeNull(); o.SourceFilter.Include.Should().Contain("obj.*"); ---- -[source,csharp,method="candeserializestring"] +[source,csharp] ---- var o = base.Deserialize("{ \"_source\": \"obj.*\" }"); @@ -104,7 +104,7 @@ o.SourceFilter.Should().NotBeNull(); o.SourceFilter.Include.Should().Contain("obj.*"); ---- -[source,csharp,method="candeserializeobject"] +[source,csharp] ---- var o = base.Deserialize("{ \"_source\": { \"include\": [\"obj.*\"], \"exclude\": [\"foo.*\"] } }"); diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index 915797c7a3f..4bf549170ca 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -12,7 +12,7 @@ The sort is defined on a per field level, with special field name for score to s === Handling Responses -[source,csharp,method="expectresponse"] +[source,csharp] ---- var myCompletionSuggest = response.Suggest["my-completion-suggest"]; myCompletionSuggest.Should().NotBeNull(); @@ -30,7 +30,7 @@ payload.State.Should().NotBeNull(); === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Suggest(ss => ss @@ -87,7 +87,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SearchRequest { @@ -161,7 +161,7 @@ new SearchRequest } ---- -[source,javascript,method="expectjson"] +[source,javascript] .Example json output ---- { diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index 7f5202c4659..46a7da9556c 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -11,7 +11,7 @@ === Fluent DSL Example -[source,csharp,method="fluent"] +[source,csharp] ---- s => s .Term("my-term-suggest", t => t @@ -66,7 +66,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method="initializer"] +[source,csharp] ---- new SuggestRequest { @@ -145,7 +145,7 @@ new SuggestRequest Get the suggestions for a suggester by indexing into the `.Suggestions` on the response -[source,csharp,method="expectresponse"] +[source,csharp] ---- var myCompletionSuggest = response.Suggestions["my-completion-suggest"]; diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs index e070f7ba3a5..78174292a71 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs @@ -181,6 +181,14 @@ public override void Visit(Source source) source.Attributes.Add(new Title("Example json output")); } + // remove method attributes as the elastic doc generation doesn't like them; it + // expects a linenumbering in the index 2 position of a source block + var methodAttribute = source.Attributes.FirstOrDefault(a => a.Name == "method"); + if (methodAttribute != null) + { + source.Attributes.Remove(methodAttribute); + } + base.Visit(source); } diff --git a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs index 0d2928a298d..0e93b4cb277 100644 --- a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs @@ -65,7 +65,6 @@ public DateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage } }; - /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Size(0) .Aggregations(aggs => aggs @@ -88,7 +87,6 @@ public DateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage ) ); - /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { diff --git a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs index c48414bb192..d51c010faa5 100644 --- a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs @@ -8,15 +8,14 @@ namespace Tests.Aggregations.Bucket.DateRange { - /** :sectiontitle: Date Range Aggregation - * == {sectiontitle} + /**== Date Range Aggregation * A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` * and `to` values can be expressed in `DateMath` expressions, and it is also possible to specify a date format by which the from and * to response fields will be returned. * * IMPORTANT: this aggregation includes the `from` value and excludes the `to` value for each range. * - * Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] + * Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on Date Range Aggregation] */ public class DateRangeAggregationUsageTests : AggregationUsageTestBase { @@ -46,7 +45,6 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : } }; - /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .DateRange("projects_date_ranges", date => date @@ -62,7 +60,6 @@ public DateRangeAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ) ); - /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { diff --git a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs index a306e685c14..d7a0d3cc5ed 100644 --- a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs @@ -9,8 +9,7 @@ namespace Tests.Aggregations.Bucket.Filter { - /** - * == Filter Aggregation + /**== Filter Aggregation * Defines a single bucket of all the documents in the current document set context that match a specified filter. * Often this will be used to narrow down the current aggregation context to a specific set of documents. * @@ -45,7 +44,6 @@ public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : bas } }; - /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filter("bethels_projects", date => date @@ -56,7 +54,6 @@ public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : bas ) ); - /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -85,7 +82,8 @@ protected override void ExpectResponse(ISearchResponse response) } } - /** == Empty Filter + /**[float] + * == Empty Filter * When the collection of filters is empty or all are conditionless, NEST will serialize them * to an empty object. */ @@ -106,7 +104,6 @@ public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) } }; - /** === Fluent DSL Example */ protected override Func, ISearchRequest> Fluent => s => s .Aggregations(aggs => aggs .Filter("empty_filter", date => date @@ -118,7 +115,6 @@ public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) ) ); - /** === Object Initializer Syntax Example */ protected override SearchRequest Initializer => new SearchRequest { @@ -131,7 +127,6 @@ public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) } }; - /** === Handling Response */ protected override void ExpectResponse(ISearchResponse response) { response.IsValid.Should().BeTrue(); diff --git a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs index 36cbd524c21..294d0314c30 100644 --- a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs @@ -17,7 +17,8 @@ namespace Tests.Aggregations.Bucket.Filters * Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. */ - /** == Named filters **/ + /**[float] + * == Named filters **/ public class FiltersAggregationUsageTests : AggregationUsageTestBase { public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -110,7 +111,8 @@ protected override void ExpectResponse(ISearchResponse response) } } - /** == Anonymous filters **/ + /**[float] + *== Anonymous filters **/ public class AnonymousUsage : AggregationUsageTestBase { public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -195,7 +197,8 @@ protected override void ExpectResponse(ISearchResponse response) } } - /** == Empty Filters */ + /**[float] + * == Empty Filters */ public class EmptyFiltersAggregationUsageTests : AggregationUsageTestBase { public EmptyFiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs index 2cf8634877a..524f9d7b2ec 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs @@ -9,17 +9,18 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class ConnectionPooling { - /** :section-number: 4.1 - * == Connection Pooling + /** == Connection Pooling * Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which * NEST can use to issue client calls on. There are 3 types of connection pool * - * - <> - * - <> - * - <> + * - <> + * - <> + * - <> */ - /** === SingleNodeConnectionPool + /** + * [[single-node-connection-pool]] + * === SingleNodeConnectionPool * The simplest of all connection pools, this takes a single `Uri` and uses that to connect to elasticsearch for all the calls * It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always * ready to go. @@ -51,7 +52,8 @@ [U] public void SingleNode() client.ConnectionSettings.ConnectionPool.Should().BeOfType(); } - /** === StaticConnectionPool + /**[[static-connection-pool]] + * === StaticConnectionPool * The static connection pool is great if you have a known small sized cluster and do no want to enable * sniffing to find out the cluster topology. */ @@ -79,7 +81,8 @@ [U] public void Static() client.ConnectionSettings.ConnectionPool.Should().BeOfType(); } - /** === SniffingConnectionPool + /**[[sniffing-connection-pool]] + * === SniffingConnectionPool * A subclass of `StaticConnectionPool` that allows itself to be reseeded at run time. * It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. */ diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs index 67383907390..55e0fcf2a2e 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/RequestPipelines.doc.cs @@ -118,7 +118,7 @@ public void SniffsOnStaleCluster() /** A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout. - * See the <> for more details, here we assert that our request pipeline exposes this propertly + * See the <> for more details, here we assert that our request pipeline exposes this propertly */ [U] public void IsTakingTooLong() diff --git a/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs index 27b11b32ebe..32883c7461c 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.ConnectionPooling.MaxRetries { public class RespectsMaxRetry { - /** == MaxRetries + /**[[max-retries]] + * == Max Retries * By default retry as many times as we have nodes. However retries still respect the request timeout. * Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can * but give up after 20 seconds diff --git a/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs b/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs index 57100865841..e6a1480b6ab 100644 --- a/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/CovariantHits/CovariantSearchResults.doc.cs @@ -8,8 +8,7 @@ namespace Tests.ClientConcepts.HighLevel.CovariantHits { public class CovariantSearchResults { - /** :section-number: 4.1 - * == Covariant Search Results + /**== Covariant Search Results * * NEST directly supports returning covariant result sets. * Meaning a result can be typed to an interface or base class diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs index 69d0bad2b2f..d8c6953120a 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/DocumentPaths.doc.cs @@ -7,8 +7,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class DocumentPaths { - /** :section-number: 2.4 - * == Document Paths + /**== Document Paths * * Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes * and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs index e10103d928a..b0e1af88864 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs @@ -8,8 +8,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FeaturesInference { - /** :section-number: 2.6 - * == Features + /**== Features * Some URIs in Elasticsearch take a `Feature` enum. * Within NEST, route values on the URI are represented as classes that implement an interface, `IUrlParameter`. * Since enums _cannot_ implement interfaces in C#, a route parameter that would be of type `Feature` is represented using the `Features` class that diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs index 782732d81e7..21dcc4d62d0 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs @@ -19,8 +19,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FieldInferrence { - /** :section-number: 2.1 - * == Strongly typed Field Access + /**== Strongly typed Field Access * * Several places in the elasticsearch API expect the path to a field from your original source document as a string. * NEST allows you to use C# expressions to strongly type these field path strings. @@ -124,7 +123,7 @@ public void ComplexFieldNameExpressions() * If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow * you to analyze a string in a number of different ways, these _"virtual"_ sub fields * do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that - * should be mapped and <> + * should be mapped and link:../mapping/auto-map[how they are mapped] */ Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs index ea89238e9f8..a8b0e478a77 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs @@ -7,8 +7,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IdsInference { - /** :section-number: 2.3 - * == Id Inference + /**== Id Inference * * === Implicit Conversions * diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs index 099ae95dfc7..a7cbfd93972 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs @@ -6,8 +6,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IndicesPaths { - /** :section-number: 2.5 - * == Indices paths + /**== Indices paths * * Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices * In nest this is encoded using `Indices` diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs index 29cb08ba7a3..ec6b0de0b2a 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs @@ -8,8 +8,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence.PropertyNames { - /** :section-number: 2.2 - * == Property Names */ + /**== Property Names */ public class PropertyNames { /** diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index a587b089a9e..66496564eae 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -8,7 +8,8 @@ namespace Tests.ClientConcepts.HighLevel.Mapping { - /** [[auto-map]] + /** + * [[auto-map]] * == Auto mapping properties * * When creating a mapping (either when creating an index or via the put mapping API), diff --git a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs index 6c3d92ee2db..ba6ca6a3b5f 100644 --- a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs @@ -15,8 +15,7 @@ namespace Tests.ClientConcepts.LowLevel { public class Connecting { - /** - * == Connecting + /**== Connecting * Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. * * [[connection-strategies]] diff --git a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs index 338f2aa4697..d10fa231fba 100644 --- a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs @@ -13,8 +13,7 @@ namespace Tests.ClientConcepts.LowLevel { public class Lifetimes { - /** :section-number: 1.2 - * == Lifetimes + /**== Lifetimes * * If you are using an IOC container its always useful to know the best practices around the lifetime of your objects * diff --git a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs index 1b9e112e7d5..cb78b2bcbe4 100644 --- a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs @@ -13,10 +13,10 @@ namespace Tests.ClientConcepts.LowLevel { public class PostingData { - /** :section-number: 1.3 - * == Post data - * The low level client allows you to post a `string` or `byte[]` array directly. On top of this if you pass a collection of `strings` or `objects` - * they will be serialized in Elasticsearch's special bulk/multi format. + /**== Post data + * The low level client allows you to post a `string` or `byte[]` array directly. On top of this, + * if you pass a collection of `string`s or `object`s they will be serialized + * using Elasticsearch's special bulk/multi format. */ private readonly string @string = "fromString"; private readonly byte[] bytes = Utf8Bytes("fromByteArray"); @@ -40,7 +40,7 @@ public PostingData() [U] public void ImplicitConversions() { - /** Even though the argument for `PostData` on the low level client takes a `PostData` + /** Even 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 completely. * You can implicitly convert from the following types * - `string` @@ -78,8 +78,6 @@ [U] public void ImplicitConversions() fromListOfString.Type.Should().Be(PostType.EnumerableOfString); fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); fromObject.Type.Should().Be(PostType.Serializable); - - } [U] public async Task WritesCorrectlyUsingBothLowAndHighLevelSettings() diff --git a/src/Tests/aggregations.asciidoc b/src/Tests/aggregations.asciidoc index d4631347878..38c5c57c03a 100644 --- a/src/Tests/aggregations.asciidoc +++ b/src/Tests/aggregations.asciidoc @@ -3,11 +3,11 @@ [[aggregations]] = Aggregations -include::{output-dir}/writing-aggregations.asciidoc[] - -include::aggregations-usage.asciidoc[] - - - +[partintro] +-- +Something about aggregations +-- +include::{output-dir}/writing-aggregations.asciidoc[] +include::aggregations-usage.asciidoc[] \ No newline at end of file diff --git a/src/Tests/common-options.asciidoc b/src/Tests/common-options.asciidoc index e44f0938f07..5e99213dd2a 100644 --- a/src/Tests/common-options.asciidoc +++ b/src/Tests/common-options.asciidoc @@ -1,7 +1,12 @@ :output-dir: common-options [[common-options]] -== Common Options += Common Options + +[partintro] +-- +Something about the convenience types for working with time and distance units and date math expressions +-- include::{output-dir}/time-unit/time-units.asciidoc[] diff --git a/src/Tests/connection-pooling.asciidoc b/src/Tests/connection-pooling.asciidoc index 83cf15af019..759505a124d 100644 --- a/src/Tests/connection-pooling.asciidoc +++ b/src/Tests/connection-pooling.asciidoc @@ -1,4 +1,4 @@ -:output-dir:client-concepts/connection-pooling +:output-dir: client-concepts/connection-pooling :building-blocks: {output-dir}/building-blocks :sniffing: {output-dir}/sniffing :pinging: {output-dir}/pinging diff --git a/src/Tests/high-level.asciidoc b/src/Tests/high-level.asciidoc index 222038941c6..6cab2b234d9 100644 --- a/src/Tests/high-level.asciidoc +++ b/src/Tests/high-level.asciidoc @@ -3,6 +3,19 @@ [[high-level]] == High Level +A high level client that provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL +and takes advantage of specific .NET features such as covariant results. + +NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> + +There are a number of conventions that NEST uses for inference of + +- Field and Property names +- Document ids +- Building a URI path to a document +- Building a URI path to one or more indices +- Inferring + include::{output-dir}/inference/field-inference.asciidoc[] include::{output-dir}/inference/property-inference.asciidoc[] diff --git a/src/Tests/index.asciidoc b/src/Tests/index.asciidoc index 0dbcfe2affd..212cd2f5d73 100644 --- a/src/Tests/index.asciidoc +++ b/src/Tests/index.asciidoc @@ -1,5 +1,5 @@ [[elasticsearch-net-reference]] -= Elasticsearch.Net and NEST, the .NET Elasticsearch clients += Elasticsearch.Net and NEST: the .NET Elasticsearch clients include::intro.asciidoc[] diff --git a/src/Tests/intro.asciidoc b/src/Tests/intro.asciidoc index 897e079d6ba..0b41b0b3bd4 100644 --- a/src/Tests/intro.asciidoc +++ b/src/Tests/intro.asciidoc @@ -1,6 +1,7 @@ :github: https://github.com/elastic/elasticsearch-net :stackoverflow: http://stackoverflow.com +[[introduction]] == Introduction You've reached the documentation page for `Elasticsearch.Net` and `NEST`. The two official .NET clients for Elasticsearch. So why two clients I hear you say? @@ -13,10 +14,10 @@ enough so that **all** the Elasticsearch API endpoints are represented as method Please read the getting started guide for both. === Who's using Nest -* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). -* http://www.7digital.com[7digital.com] (run NEST on mono). -* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). -* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. +- {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). +- http://www.7digital.com[7digital.com] (run NEST on mono). +- https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). +- http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] === Other resources @@ -29,10 +30,10 @@ with their https://github.com/searchbox-io/.net-sample[demo project] === Questions, bugs, comments, requests -All of these are more then welcome on the {github}/issues[github issues pages]! We try to to at least reply within the same day. +All of these are more then welcome on the {github}/issues[github issues pages]! We try to at least reply within the same day. We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or -{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow] +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow], as well as https://discuss.elastic.co[discussions on our discourse site] === License diff --git a/src/Tests/low-level.asciidoc b/src/Tests/low-level.asciidoc index 4673d5969f7..78b02a70ded 100644 --- a/src/Tests/low-level.asciidoc +++ b/src/Tests/low-level.asciidoc @@ -3,6 +3,18 @@ [[low-level]] == Low Level +The low level client, `ElasticLowLevelClient`, is a low level, dependency free client that has no +opinions about how you build and represent your requests and responses. + +It can be installed from the Package Manager Console inside Visual Studio using + +[source, shell] +---- +Install-Package Elasticsearch.Net +---- + +Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[`Elasticsearch.Net`] in the Package Manager GUI. + include::{output-dir}/connecting.asciidoc[] include::{output-dir}/lifetimes.asciidoc[] diff --git a/src/Tests/query-dsl.asciidoc b/src/Tests/query-dsl.asciidoc index b28b7c831e3..76eedce8e11 100644 --- a/src/Tests/query-dsl.asciidoc +++ b/src/Tests/query-dsl.asciidoc @@ -1,7 +1,12 @@ :output-dir: query-dsl [[query-dsl]] -== Query DSL += Query DSL + +[partintro] +-- +Something about the query DSL +-- include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index e1cc4d94e0ce0c8f00cb69925eda46873c4522cc..1b6eb5b04c2ab2210ea54acdaf9375aa1d2aea45 100644 GIT binary patch literal 70656 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%0AP zC*P9oiJmF&1HlyHK9B5QNoNuKam4+Wzb^+<(U&9s705nDI#1!3gFg{(2)yJ?AUXuu zy{1fT2V`cJ&%w-&(AMzrR}q34dp`C=zu| zP0jP$B1q_ld=W)BUM7M>;kG0Z#KOMbF22m$?Kv1BW!>j1f{1RvP=biNvqA(pfA^u* z2qHmI1{-Wf5N@|?O$50hQE6lmY`>{b1VPzlC_?mLbIS-a?Kkj>AQ-gi2r`}QG#NoU z*h?pZOtAk}1ex~V^hXd3ip1T!C5oVXcB1T>Te1pc)5Hjgce3qF1Zj7(zzFf(%`PLv zcQ*-&5I-#&8%K%n?}F`b{t`jbI1Vp@q`Og0g!t*8c|;J3dM|Z%1&W~G-F+@X{QM3g z5rn*LT_Xs1djv%gDA?RJf|R!vSpb(nLArX5S=hT*t{!>l(&6b6p8#MWD%qa zx3rHW=ALCL5{~oDx^LF;xZ*xTd;jov1ZYOW}$t20=l_TF7 zdGF`DkGkU2hFxA-JhyHt6G9_6|8usx+xm#P>>SwYjA)%#KVp`hr8{3-aNkO|BBPnR~_v@;2_w*@E#|g5RSc#&ty;*6Z z^JNFNIz4>3K@MLoO;KB8TT_WP@Nn&(JG>q$+T^^d(hP5H-)%&%{MPpUL1_xy9TQ8; zfd3p&Lc;D0M~SKC`_1SHx5zQ!C0=WC)z1i8Y-z@~`A-?qEpPSCd|r>HI*)x|*VBBx zVCK2KUTH;eJlph^c*TgQyTfm3DYuY&b~kjNtD{$dFFnWGez{Z&yr=q7QZIN;k1p))VkJyop7#T`^_X(lwzZQ@kM^?7t_ zU`y2XEzA1+>$?(K$9g<>*3F=YYLo*Tr1(bh*nJw{4XJbIS3?H$TJYMA{jPQXvfuGv zxvLR(;5BJ)xJ&W-;BUq|epxa%ljn7L-M=F~Z+e~c`A3!mj_0-OVEh|+4J%6_Zh)61 zh<^aQfpzKuZ)Bb61g7!D@mALvz@vT+|3zNs4#ZzcWLf697rrdhI1QoU_`LPy6+YWu zVUH}QxCp~{z<(LPAO6ii;>c%VvYg}~UI`DwKb^n?eg-{z;$KXnJK--z*)I6+VNVvn z2l0pEKTSS%#Xpiv%5py0=5IHAiOWytK=LcgCLcksEDOE~`3(N)*jtI;jdb?FUyPn1 z__7RzpUxQ4+Zq2F^vbf6vDm#m{yQ6Z%f!2*FUH@8VBe1TeenC^zkojg|6Sx{Y02ZH zFH0ULQ4ZVUXONR++h3EuEFXP{^he;AVb>`9J|sQ}e;d;4i~j_f*d2cw>56Rw@TJ1H z#=bKAf1*#9AHRJ_Ii>kOUd?+zM_3a(>z!;7)KC zxEuT&`~utq?ghUD_ksI?oZIjKco4{$s>{K{;1RF_JPIBI@=edL!7A`Lcmg~Lo&ryU zXTY;S&i0XxqZaHBMuP*uf#4u828;yf~2I|0cKofJc1I0<|ooD5C@r-IYK>0lxF0XPGk3C;p%gLA+l za4t9xoDUWQ={J7}E(8~Wi@_z}N8nPh1pF9W1}+CzfGfdIz*XRCa1FQ?TnDZPH-H<# zPr*{~GjJ2Q87u?0fLpxzX11ud%-Wkec*oZEARk#5Ih8ygNMN* zU_d=G32WDVrzU<)AU z18fE48?|jfZ?G-s1GWQw!S-MW&=2$nGI-kw3;<;v`%Bf)-P6i9;%$buZG0kvR%Fd7^H z4g?2*F<>k>7>ons!6D#KFaaC}CIWe}bU2s{jsQo3qren!G&lxK1=Bzsm=5Z}4A1~( zf@8rfa2#j^vq2M>1LlHe&;pJJ^FS+T1M|TN;6$(hoCLlPP6nrdQ^9HAbg&To0Gt8N z1ZRP>!8u?NI2W7;&IgOZ1>lF^LU0kd7+eB=1TFmRY;Bs&UxDxyXTm}A9+;6ev ib+8(|0p0}Px$jEgyAt@W1imYQ?@Hji68OJe0{;z(l2t_j literal 241152 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

JrotQpg4np%w|GaZ+oXU9L~Z_~`xJfD1X0^ib@ zIFyHz-mJ<&*k@ z&5<-O(-@;MO6yP>qwx1ylfu265S1_^vpLr`&Z|9i51Y~eU=^8d1hxS^sL%kQ9GDEu z1m*(|0=v`yod(q2W*^mYF+#iQo{G|UF?c!CX@`C6i0#8m+Am48tzAkTA`|<_m_e1PMuZ*q5VG^Yk~fkP3rfb zr$dMKAMXE&)~^36=KPWy&c|*4@5F2gqv#)$@x{C{7BYsLZQFc&l&fs(IOt7e>@XRM zOGf&8;!i=le|Z9^lUMRxEThyo!NN0BfGzT87r8bL-Hu58rQ+V>ihO z=cc}&B-5&%;r!V5i)32qBAmziK9Ef7*S>S}Sl{lsF-qM^ z8<#Zy&L5X_KZsH}Fq|=H0#FOg1r`Czfi=KpKn+?73(73vW8zs`OPqtxCA6o1NdVk+}I6e%B zec+W`vvf6ecr>pLg^Ul z?P;kJz5&M9jxogAOR@SY!1vFT>#LHnAFx6{NUV9dG2~1zzRm4L_5;h$GmK^ZJnJBt zQ#jT->bYRn4Kn9}nKx%H2W#E)DzMftuK|-srW&mE#2dhb4jGL@L!yfqhekwx&+>F| zZ`M~Y1NQ_^it+yLyw2I&VJUg|KAeiIZ+GY1gMdEvJ z=WcJ6ILg(BuIu(#@#&dMxPCHtGMG9C6=4muav{3 zA>_L+zlMTOj>cu{sq4OvCy!OCXE+A>KAlXfHa(G%U;RM&`aYaYI~>}B*%dZg-*1!0 zK+*P%j&QW9r|+xDV_-S7>Te^!`D38&<5wyN)?lm~fo(uHjHnbC0*nLdfqB3ZU?s2) z*bJz%_6Ev;_NEdT&yMd$SRZH7Gsx@=jQp6XvCkPkvazA1vaaFW`o^jo^wO`hr%jz& zMoi%E2UK4auhIWsjtAC`zAPzME>%lzwYPqdWYb4*r|C9+OP#t;R!P6dpwpSVpjVes z2lyAZe@k56cnQxPy^Hog{TR5{UzojbXuD|4j3rE_q{>NC@Dt1~EXB@^R$W6ai1R2@*#}&5q{JjPl zTTOHT^vr^Mw~-gd+?ra#$> z#v0!ixp7J1Q~$W6Ea_=l6akEpW!W)Rd|tn~u`lGqj4~RE6!UZ;g0V4N`Ffq@_*6yn zpN!v`Ly2(Amc5R0Wy_~MoM^=A;dPQcW-7+gnAsDYKW6GV7^MNg8VbG<*amcCBc>D> z4om`O0`q|-!0xnj4U}-n`mZwvj>EoRLM&cJ0O`7RJM4c4{a^NFGSY1=!Xg28EHD|A(Pmm8$J>(nua8IH6gbL32wrbnD zndU{zft+v2UpH%g?|f+#&UfT{e0wGP9(-)8d4O-9WLo)=aL(Y{Bbl}rwBbC!w?R%v z(yRGD(b_yf<@I_`&R2TSdYr|Ywl6abzLof>wZN;ucAy82xC|HrR0DH?MZhv(HLwxb z0Td&J_Fo%kXnVmr{1f(js;zs+_Fw3I-O5Kkz~&jtbb=Jx34Jm>#^k8qj%u96tG7qh z)Yr}6ooLQAg?ViCS+ug5KapKL3l4cDW+j+66MToK+^<@K7JuV};dXs^q{ zipZ<;V&K^|uU9Iyx1}vp=_uv2f9(Dey)!BX7z?X9oWt;%LXzjY{yqfcR zrd@UZZC;&;-xBMrd)CIlqdNZ~ug)RQzoO2Y<2v_1wxzYy`OtoGOy7-~T78m;1nBiP+ATJM9C^JOS* z6=Qgxn@p><-|+rQ?_-l=4AF*hj`yj_`O=|U%{9CaP0m-eConU%x_O_OoG-T4s&3vt zCevz9s+3l+e7#RhE`w-oZZw8=^L{Snd>)4prjWfKRC`+*BQS}K4CfDje3SW)-{aaR zdKddwP>^h{IFH}n|D>{hi?+``4|pW`(7xQo@AEqrthv)8;FG|TcY2IR zfZ4~<d>Xw=eU{GW_N+yiO@_JXd`R%i{e)D(g?evYbL*s@o8-)}D})(LCr3FlIsR z)CZg{+&-Gh0%hnJtxPh_-$8)Q7%t^|G(N&?c;4Um9^cl zePmbCr|dv`nd)CEv--|Zo){P$jpk{|^TFq4=b?JXn$m1w42-p61|9@f0PBFwKnY6e z2Mhxy0QJB;UVJU0C`O>q(QZZvXlpYg?`2m^E?6r6vIU1T>XJkYVv`()u6I*rjhb842?k z<1J75f`#$um*Jfs@)FOwkNiNY7{_?$#=P<)mc9b-y~eAUG>_Nf*`#LxzY6dD#;YfW|6e(-IaJjRMPj30cPCg;mo(`rw}w_|d?q7C;{eA^|D zDW%Y&^N8^vBb|ir#?Z6dO65Qq4KfOt0?Y*F151Hbz(!yj&;!K}0Lp>Mz)WC1umsqh zI+g}XD6aXSO>xmHVl0F|Om{y%_WzR_d5TM4wD5B-@h$@@0He{|kVEa~XL|!*;vCV` zR5?fIkBaAx;q|7*8I=v$oRxR!0qT+=O&!OD&L_{I?4HNZp>4n978N8;BcQ3z)sL@@ z`ntW!b*;yU)~?%J89$M&TZ4Zbj{Cd(oH)GJQd`%2d1d{q8uHL})hWE*z^gs%y5_2S zo*myE&4R8eE|YY@6ucFm>0(#)F)6nDSCMJyT=emp>0?lpd*N3h_jj1iH3lpMe7{J! zJ|Y=xZ@Bk_=r=yyjR6;e(F=FR`FqqZ2A{<71n{ZgOTZRubHAA0)8y{CyA*sa$5(*; zyFhgR+%Q1*VD|@bR-~@crTo^j$i3a1NNwxeH09b?G-}Wd`azl!MH#8)8nF5}GBTPn zSAaFnD)v`Brg2PY994sl0$&GKxvvKg1K$9C7kCDkvPO+y@{F3nm{3Gl%QS#1z)dlJ z5BO$|eR&U#O0b5#+$yQ+(SvAXG;3w${2mA##PQhp_!^G;vU-0!W1{Nb)77<%{Cs<+ zB5P;Wtv{eNkk`JBrv1_H!Y*v5I)Q}5wZQroOVLF<6czz(2SPk4ddsbgzE{oCUI z+PEr;6D*y}x=tSgFy|t6asSW8nI&=NVT?TzIRi|Ni*^6`y+>xBakq52jDl~l@wr$x z$7l5#9{V@%4ZQHt@SSda?TB@y7x~}U$!<8{b(Fi;wF~EDdrF9L{)75De?j>(U9i*q z=R|z{ljB1C4L&mWjE1jsa$G3da8JzFGdV7#tzBHmbUc$E7wY}LN~ORkY<)5?6POPy z0agO*fX%?})G;*>+W+#n3Zea9PCW2?28q!A6|0DEHXvHNUda8vvYkTjBha`N#&e37 zlvv-&rYk7#|KydokoZOQ^=0!hqs{3x23nd7&3+8@PP}}T3*wsbqix^c$(Lheb7)Fe zBIj6>Bj2_Qa$cwK@<+a{a(*g|1>~3Zg+~74T|_}PZx)}|={vv2axBrS@%4w#>nY`8 z2o9ajOqbM^IBH@xPVsfk?E{2m(;6mWhg-|so0Z`ciCipB(KBI6rTPb9FJK^04on7G zfCa!(V0UV*fzbX}$CrqIvq|y%@&Q@Kq)~**~|HaHXO zm>Y-t(uYpvxF7g@Ft^<>4qpe&WCzxtEbdjDv5G#k;Xk;1-AeU7PYj#X38 z_#r)ovIdZ+QYedIF#Xp&S@9C`F3C!I2OPsxTE>>G*Vty=4RCQo{hU^PCF%WdgW%mW zvF^is}MLoZspuJao>U%~lO&g(lM zYBO8gLd_axU8-xSu2GC9o~_X7o)YE>(Va1mt$Bq!*{?l9r~YZs9^G12zfLBP+u{CfLl?U1^hTv7FF$8Kcs@=nt;lM>fu!GpVs%GR#L; z#Dm?)Y)#yrfBHC+aehsUKH15txBK=%d+K98LeF?Ah4tYX)%5iyYpe|J;_F1y9yw+& z17jx{%3&QceM?SGb4^oW@6R`XXEGMXGQvJU{FT;yYOZZAt(nnyQ%$?-Vfxx0%g}gl z=`3VC)>_60#Rcur*X8kZuk-fuxrcEN_jIJcW^xj~X)!kL6x^du9MP(aw5u$yQ-uD2 zkF}E5fVvZ}_92=vS|48}uK|hn2xdt}>*J-|+)8a^^DwOe9YU#%*2gEQY%CGd_JFn@ z^Dm?I@kKIiPiXscH;>W!_#nA%yKKC=WlbCg*WsoX7Y$ zkBeO%de?g{k9zX(<7P_lC~!&kTj77Qst{#l*1{^sBydmgN9}ec;6pBwGu5ir?Zh+HhXpp85At!JJ)> zQVqJaX8Nr9%BIn?XEsp+J{sh|S5)X4vg)fj$p!J)-=dCBk}tP(4g`~Pb*^k`u8E(1 z$i28tDmb~!>!6U>L;93_i#;feOQHO72rAw|{uOmCwG$ef-3QTKSx#<$SrN9v*U%ghvXQmDivkM zGLl-pzV9Z}{tepkjK)Um`&KGj|8N{y-$k?+Wodn1NT&UJ9<6V?WZJ_@qRbfXo3Ju? zT_@9)Lwf;wkZ+WY>igA7!+?7H@dDscU_Gz}7;tD5l>;+@`GCHMvkqW^CF%`~0sftm z{GrY1YU6@2jAaw|tE3;M;?7O(;{N~JJ^yT{gb(8HkH%ARzc)0<-h(5sxbZ&pV97m{8y@wKSH#_`aN=D|KVp3n>v-Z zk5$$;moa9fd6MNF_S_j*RY%#J##jxvC3{AD=r~2XiId95Vqmk;PzNK>!SCNe2YUWF z1BlOPb+0Rj%pu>t4rjNe4&=?6PE<}=to(Zf<=0py`}g`!xpHvm>aO{=lI~mF7c5(3 zsEYW_dXj$+8VK4UlvVf4pON(^zAkT{pJD~&$CSq9$L~z*{HABePkYCj^uGw(SplpC zwsdeiQhhsOl5N=d|7ctRg)5eZvj6|XBU_LEX7gHu5v^T+r+J?2tkC%y-QL-!l`-i( z1E*8Q|IRC8A#*a-QDw6|fl(4l3fF^&LGurjp|~J76?EmZ*ud@=3VF|fx8$f;hdYTW z?D-!;fowVxzI}{uCox5D{FjpK$R{Bt;cqwqdQ`6Ay|xwRhotf0`%gQI);zb~=r?%qj5!-WUTikn+o@;!vt$@$`z_^T+nA4?PAz0Y_@)iuv-Y*sb#-R}_pP!7d)-Jw-mhWeZw`;Gx7 z1Uw0vPnaCt!4d0aSLCdU<@68aT!x(IOwKOWM}BG&;QL|9^+}1+RDFzokQDQ1J6SQ0 z%#ZsR+`Ert(+WLU4$k=RcOL@ZX_58lF=^t_1nf~?NU!}o)f_NH74 z^EeV7`Dcb1=79DcSv_~7eI>tFq&D$woc#R;@^yP?CxA7E&>h%Ybnm6e91T91V?76> zeV;UuMpw-?qLOSZxhi%9<hSEC!YX>wwKbx5J~T6c`3f0BV5@uo&p9 zDfIuVV0G@2WAWbtPKnm8hyMSaV!>kFbEiHjpJwr)t?8W3c}pi# zhnabGD8!#h2cZmm|G(x^mQI1@u_DN@@nelscuDw|G&_i5v8M?7izlb@ak`2Lb|eMds%k7w%#=@?8>zTh}8F_eoZqa__I#9CR$l@~?^){d@N9+u-4Q_H)mJ*F*37MN0eQF3F`-_@Dn& z7Wr6}g*lHai~Oj{A~!M=O!)%Y`nIax?XP|HK3Tu2n9ui>T_s~EI#W35ij*Aq|{~yBk2VK?L{}^(ezcL}@|A#cK-K+-<)C*YfId^?%H zZ;0iE{`QmbH5y+#{H^I+{#Nm?Z@=Qr-+f!{+Wg(OMY4ZF7p;7m*L^ZA{is#!?e(1; zBa1eizk3}g`@OfDzb}x{kmUE);mckHb^tv}+5ZE^02RP&U?H#+SOshV{@qe&|Fv=9 zG{#wanDyoha0srO?&AKR`I)tG=HWi$$B}bgo}5DbjLI3#Z8hgr3Vpy5Xx?Ko(RTL%c4g&uip!-c|9RYrVHN}@_U<_m9OtF$@$6$hVL!% z{USME(c1p5{GxCFWZ&8cTE&!#pYvnNdkE;2)HYj7S-U!tI1(rW#sC$-Y+xa<6j%jp z0JZ|%jv`J4Mgg^eUdpi;*qwH+fzba~$7I+}Htir5xn@dh|6hn-{x1AU@n7ig{sGN( zMU*ix<%^G<0do=tVw&BKFQ+kc^ZxXMgE!0xeF8s{FyO4lQ2g~@TTSzW{Q`kG5-HTsV~g#4Rh ze%Y9%8{mJ^_+5&E#@9G=>gXG1Ro2(F%u#&`@vmwhmCOLwMUl4ev9_- z5<)*a6IuVyWVOT3T7680-4}e4RR(+`GX7#RoZb{J^)>b=iS}q#c2!R0>+LN$ zU#;_ov9hI zcyjM-uIHTZtGRoqr2h&)=}73+C5{HuHg3&X@z-%2%Z85!vz*G)SlZw7&xQH-OlvNq z_f2cRZ2(xuIopPz%fh9t2hZYk^mR9YF76h^v4x!0zGoZlq8$9R1M9ICPT46-o0KH$1v8p6!O-Wd88t$k0Hch6LOk4ZFl|{b&l4*NE8;)zf&639|(b~9HM!vqClE)wF>c$^zC6hk~ zoEQ7-VdPPPe{BI4084zzEmBuH(7x0A`{s=c*_l6PWoup3Z4Bk54I0-Hl5elBqF;PYz@E928=e01>fmju(mwwt#?gH9&=TP z^}9O$IH(HJo_MoM%xC*ywil;*SUQXPS0>e;=h16sdnGs>prF}+c#YoPsl_}pTjnOQ zLF41xHpIu|Nh}ko9XyY}7rI9r%N>xmk|GKaXtbnmR?;dPOm#|Pk19t*(A;~sDcdv!jK16&@u56;(#cW%UW zm9Kn?^Gd{yw`*+(9o;?wj32wb0o;?kZUHNXB7d!g%=-;k^Yg!enNw%>Bac$>abVPT z$7nFFEkjJ~-p6t?_yqF%2pAc+KLMuxnID5s0skF51l*0b7|Qiy!Dnzh7W^)br-A7Y znGCob{0R75&OZen&G9e5=SR_d_dv1ZI6ek^5qJ!ky4-#pSnn@+Kln26GVm4PAAqj} zzYe|{ybnfv4R{cEY7~9&2nHN<@WC$8hiS9LKnAD=CIWhYMhj2{+zfmGxDB`fxDn8` zcLTG5dSGFE+z5Vu{QC~@96);;qQ42yIpecDX2jQ8zgNCO3mhc1eG6m9B48P?4%iH2 zZ#Wjw?({F!09__K-(DC?QWIDrL`wgbe$F3+?)9%(pFf#XqP6Rx&u@=EmJHA5eVoP= zr9C}z|5;~C?}y#E@+eNcsB%UPS3*92(XUq-D|Vkg$oLc|27I;-%pQPC_>yd5oi=@# z@r~8zJnE`rR`k|(|1CYLj3&$O`wC-Od{X*&leG(b0{OCR-mmpUOU$>^CkL|HyC-0> zEY@C1o=QDDa{o(_HQZ#iBi7EB(H+01B)@OzNMwvN8SPj@HyPGGvtt>IBiVEmGUk{J zVxji#379O?*~SD}M%GUd)pU&JHik^3g7?_0^V<&O5m z?3#Zq!IKg(Nz{7)V zRDu!p26m@i(?C-DYYedT2y@EYt}0IZzuo%ZqsaN7$ths{?^EzCGQI-V|2_@hgT~j6 zm_&L}Jf}XbxvSUFuC4$1`X`U0vWIZ}&(}G5yc4aBqp~+&&*U*oW4zisY5lLiItQr~ zD8tr90aJh$U;*$b@D#8f*qu7229oTb*eaVw($8Pu=7VDR|F^UMQONm~$tl48S+hyM zW_)?}Z|i#fT;W^KBhQ2HPsS&CJGsx@@~DXO(AZpnSO%9aW5JNG(H&R4Xy_bOlKb(!qzG{2Cq>j^F)G7i6i`{B4@mB$wO zGupK`PzHATPjC1G&HtUwz${4A}{y-mP>1{ ztFNij1^-P|6_T=L*Vk((;G{V-Yjpl#_6$_+@cIokb6ETJ-(n5VS5;Qk)>QkOEwrA` zx^A=sg1O*B!Tj+QZ|MP=uZ4UKe)-Aiq!$;q12;i)1eib8lS|#QHNRVxaeR$l8IrxR z#PQ<`+`9HL@SPCzOQzPpLjIfLZ_3KA71bi09djHwEU>(a>>Rt)f*WGg{RbZw$nOR`+$jk>X)+;p*)C{cH-Pq;aPd#S8-`0JVVH(%P|BM5K6{ z<$m|49Uh{6X@czfZ=wA~tZK`*8~@R1dYQ@5c${$G(*|Wkie0t)O&g@2Fg}gJ0iV^2 zeJz(%e@nDk`bpz!$G9uKSpQV~?{$>Q>Q3uBzNP&*D;rk3X#AnCW`;)P=stIU6Zu8H z{yQHN!~2GOop(MahW8EmdKNw={xuE+ODUTSY7wvuSPg6hwgKHw!tVgPQ^(XmX#eZt zD%=)Sg?+~K-WXhH|8Bn^#8*MQkm%iIdqxOXbM0wwH*mvC0! zz9`}UUQwz0-4zZU>wH&s#=8d3wy7LmugU&P>*`_r@Aa5WdnB~|kg2g>`Fg!2(`rnX zuiFM4>WzjS$UjmkFdU^!0BV7Gz=Oa_U>&d(*qvIB|JAWV!twua^xK=*j7aHPy#8Cr zzUQCdSO2!Lcug#0uNVt$hvt1nkYVwKFKlbu{W~)5F&W-=r`6QAj!TBQO16$K-hl5T z#;5pVTxFKe>hxgDCqHEAf8cw__}UR)nBHUqiZ6T{B*z!bNiyo(wDn`N|IjwS$@fg!-ZdkWisVO-dAf&7><0I$*k+0t590~I)v!ZIHWU(eE@%n5weF<&U}5cv8SpUOI>rfzy| zORF}uwW3g7Z}^ThKItfd&%XZ~%41zFeZ28W9`CBXA!=PeyH_Zb*9X2b<8x#BKl6>! z1fCSi>kHqo(mPJMnZ@VjBmMmeFvTJl6xb^dL-tQ*Iftq86 zaiI6L$#I})Ee`BY8N7c@&X=XjR(nC-mnP>cTH6a!z9pq<>*Rc;ukiUk?ZpV-Y+HR ziydVSVGTrfsea~tQF6Yb?Z-^TVpH#bl4DHm7Z7J^3o~PL9`R}Z=Y2}<*;l!J#jHvv zLoa`E3RwN+RL8IP0rYb5t*wpRAqPQP4vZrMz-(Z5`qyZngluihtd2#P|Iy*ESjSj^^N}xV&-%|R@N3L88EcdesfS1I|F5B0 zWHQ<@E}M+k$&D@<`SRxMQK72rRH-Z7jxo}WlSi;G7ta5D8Io-i({Z+mon_26&8~jO z;HsoLEu^nL3Oog@?*RQ)?QioB`57hY$I|DCXZF83ZhysS*)3~7|1e&~CrTmj7vMcO z0SjN zkG3IhBX9Kq^*0qM?DwnUGFm_6a`Z*YIK;}>jDJ>5UBgz^C8z+_-Hun<@ZtOC{poju9^&5o*LWrY5peWUdGI8E1m z+tEkQZG-&Hp}B(%x}+E`F_p^QncdE7G-E`QmZ0 zFYXuAvyOU>$*X4}b9Lz{^!NB?mnH`?u7{@DWL#dy$Gc^FZ5UU`OYwcaj9#(7n;XlL zs2h;+R1syA$Ptr}olW(~7=}SOv2i`rCwfz!b%1E?y3UW`+**L4E*cf{>E1kLNKqZu z?>a#A70|8$F5q}fOs{+PBrl||XZwA`td?56i9otH*cF}D#`O(Dw;9xTNnU+-MMkNN zjx@(3_n#%~^hFmWqcuL!+I5|OkaL>>ji-mxIiwriQz5)}pwp_#`ufIMeht?5 z&-VAXd2zXWBEwQ6pI_$bG3kCmsNrOl^M;L>(dR@+4nu{s{TvT$~}t4d*uGp_0vZ&{|IeySNdjc zEF)~=W@I!LQO4R>#tA_^aE0mHizuTko`{4pW+CHqMU=59mT_WG5AOX<|EP#E%DVZ? z=LRxvMurSOY;*O=#gu0U;ArFPcAphpG}kAa&*c-!H^gIN`~AV9xNP`b~e46`d%KFp%^}P90P>XQ69Pf??J|l zBFM0Na8|@J&{a0kFVpv$jCOwWv6ei%j{Ux8Z=9`CSeIL%dC24xVN9AE%NXlLx&OB! z<6A|Pu_=}jw)<_!=*FZXwDVoDrBOHmrC5~vok7MCMU*iF-=}nwE42T8J2FnllOY=$ zqw+v6TDz|EvpK&5kiA}tbt)_QF+xJ^UnSb>Lg=>xve(N49zvv6JjJ%x#c_Q@o!&ux zm&9c#hQ02HWyG$58u8K~WPGlOGM2}NTIzE5|K=fMMV<_`j~t+UylCyZ&X;j+HlY2+ z-1$;+$cu?MmJRQ!udJmrD3!YZ{@?p3^ZJA`ub^B*pck!OSD9bsd>Q9eW;<_VCT;4< zuAJ+N7{{%R%N;kXvXAbh+}rZXy(_j}hP^3;GVVe~ioj0xRE&PPC_%=2Wb9W&8AIY0 zctK^3)BBOpH&2Gza6k^6r)<*tn77o&fyh-F+8$XI}k zl|_`%o4l05ar1-7IEXd5V)gU6v5av1zXuruizs7Lf{c5SF{_9&Mv<4&D39F#g~<43 z5oIimWrXA5hmf(yLB(s2?&PHu_NxygW8Wgmm>J6$;YGRs_aWo@BFb2wAY&0SK37B; z!?a;Sy3!-}|0BrQQbZXK#xg=(eH0m^IbSRrGy@+W)Z>0++*w2!55`U;6UbPMjF<9c z$Y+;8TMLNRu3Owd7@GCjbw!$M+l@e@gR(t9*(OqkV(GZLx6eFQgFE;bG8Pw6#+n2f z|Amaliy*`1o@Iyndh`!;^&m2yF&Vo!_cS@{V>uPB0lct>kn=l}%ksDxUws?ZM-!*fPUak%V^<`#7GjNCU(#63&?`LKcD z!#ExWJ{;VIr=I`$KEY!myN_ZLbbcQt`Fo9}ja-S3~I-1kQ~bo(N-txG35Ui(IhyB8#*kWkNMD-9ODelJ zqiMw|Ka>c=;E*dGU<0KN*W8cqR^08a%gUZ@0< zXEY5Ajmz)a7*7Y+aK6Mn6WEyGJS?(RTt}cxnt1dIa^dH`0>uxR6^QIZKOILbHNmL3P4(K`h z+&AFWr~JN3D!U&eeLV;$-4uEK-3*qD+2E7FbHHbTS(|g;otIu|FL!(?crNF!jE}3p zx;_KUx{-Ugz-?gl6@9Zu@Aeb!r#A+W_N9E%)1mY(rLes8*~ss=OihHo;;5k0#Z5h$L-|^LD`F3#5?|Y=O`y~ohw*pGU+OAFRb$k(T z9QOKJ1jf}x_k)iFKLA$0Vm!&HZKV(FO?u9hgYld0+0=)@7je7)}(m zf8_YD%<`?`oF>Kc2iTKK@?k6D-#>+3w)!)$EM+73aPZH;gTR}>XM)w&qzfIN3;q>& zY-g>H&z!FUZv!`g z{{r?tat23Vxmb0}VR2luANh-V75|;7rB`(lHc*i zb6%M}q2YNg=L>lDiac}=cFs;E&+kj*%CQIM`U6Tl&*bFyal9k4^{(KW-)l%=r9P!W zlj7ez@8kLp&+laVajq1668K24`VG&^xVGT=7s{kDZ~)Lh#;yI2-)~6P?{V-;zXM!8 zCuGZ~^7}o6hk~brPY2h7&j8EM zp9yAc(RUFt-vaZUhRnCY=YX-}s2q$PN4y^{Lw|^P-&#`iIdPNuF)rm$qTfOC31-pL%wGrqlfld}0@+2FQVrp9cg&<1CdhkWrIa0%rO z`TW{>@_TDdDfn}ozcN0qim%TAbI-YpuOA2J`?`LVRq5^G>v>$S!~w|;u5i@uo-_CSoerNM zUzK+SSbF{nSmWYKu*&^)@EKs<&y{%>_#0rA`F*1JRE<22fyU}H&}AEfCqqo4;}{o16VfrM{urBs?9YH=j6!G`*reUKmTXPf2Q;E z>Zg9aJJ&bV7u08zwnHob@P^|dJ_GmQ_)W0-D^Ab#(-c_!v;=$!cu%nU2;a1!tOwH{ z6w9lugZMoHtUjW?n=7~C5Wg;-g2Jb+An8`AJ9+I3<~so{zTF?Je%cdU4(2}AjPH-< z#QEo*%TeBbJv=#Y?m2aN_W>UdZC|kRJ{(*QE(Px_Z|TafgQv3Vm*0648!mIwl_YKH{xCyNOQ4THzj{u(xJ{PPu9SI%>9tHO6 zf9e-Ix0wyl`gL(S9KV&6|62EpzCk{ce}T)7dp*Fqei2w>`2_G$;7h@$fG2@9ztA{P z9v{o6UC#OO@v;21u2+I5bG{mU6}Sa_HTX90HQ?6$x_xsx^%1}Jp3=9RTngi*O5~`1 zRZbpp5ty(ess+mj)qyo{st2nNHGp$#RfDmybJ4GCZD3^mr3^a17N6{oo5(}{xY^}( zVkuT74U0+ z?3_@m*SV&c+pmGA+7_2t>7&d-*a7q+Fd6`q1CxMy zK!ea?U>UF)*Z^z=N(f;30cF4#U<%Lz%mfqB4UU^%cF*a&O|y5a2m0YiW>Kn2hOEC7}OD}lAZtH5@k z2ac*gFdUc!)C2Q@f5#--vgf~Q;{vLmSvsC)3^$kh`KCSpTj=vQ$}7BQ)5d^M4s-GJ z);u|d-2bF9m*g8Q4Tkq%<88^7E#|Lz(cM8NOX| zGNj7hfRbp#cSZQNNX~bEXpdrTLUmRdyzZ0p7432OZqtv~b@FqAOeNjETQ9I;=J1{K zi}zM3@matU{KE=hEwBmL4)i()9|ep7DuB7bB49bN2G|7bYI-O8|1N!L^pt;%{fB*) zIc$2o$!SNQRXJr-)+WBpx%QKps9lwaVO-y%{}F5E<{Ij=z6{B2slK`&G~L1ZZMli_ zN~+U#+NFCr@_^yMzjIRipBMRi>F34;#cs0cJd`?fYTW+ACp0xy)igJcZK$tnsIjN{ z&z?4Qs#M1~Qd08VIlp`6i7S6R_Nim`+T+R3t*FrX@zE$egIn|0y1(=nolU-KFO$7p zgrrdR`4HUl&a##DF3E0@(;$VinV+OT@XoS_h;LWwy){AhSY+S-&axG;wM({aM7H4D zHMcGq`p)%yH1-7MAV%xkA({5?d9+?{$+U-+DBrWP`TBY$)0R8hbF$C(FW2OQR0>Qg z#|VMNz-nM4&}{_QfN{X?)HV&s{w?;=IHVNDOk>zCpNig7x}cb8^o+{7dLO?S-%MR2 zh4IT+_^vZP#V-M$#XZYBTPt}Nz}H}WlDCuhb8n7$Lz%3zre_(iWbTAl^ERa?JaYfX z!F!AGI=Qpz>*Ei-7GmG$l8^kF)p1oU>)U~>@z9j9fSA?k*oL~6y2|=yXm&-`j#yUM zeymHS{}jsF$vex3#c^b)&x_&RZoJaxPIy~l-carYc-64kI_ACa-1M_NLGC5+?rFS| zyA$4iS|A{WWxf>N{f&1QzM-4nj`L$#TIaAd5m|=>vfBF%U6W-oy}i@%BohRlgsh`X zRy)22YcfpllV$j%Ydv!RFGI$~Cgc3}f8W+*S$&?0WhpkYbUCsvyK;wJn!VMoe7!!+Ju&(wK$=x=?JK3B>`JcE9ep?Q{w@`Lo8L-mt}*VH|BjBz zGJrg5z$b!l1JnQAS{=b<#>+YjzVYO(y~o_QY`uR=)*k^HYm&Kd33z{&tUu9)-yQS* zD>+|+uU2j7{Z(?lqCFb@SU>XqDVdg~tc>=Zjn?~@Ys_ipcy@z$-~GX7B?*5ARUVElJR_Yie;_pk^b5NW^4j;&q2zer{MNZ78}pWCOO z45m%B$Kv|hRp4tlz8c(>=%Xw11Fd&=<;|vD>3PbVHjli2NS=#T!mGL1G_cLZOlRKa zbNe1C=*;$}vpiiw|JlYljT_&j!z*Qg>JiMbfknVFU^TD_*bel<;S2=E02RPoU=gq! zSOdHY>;U?WWStP01k?lbfhE9Gzgj_KrP@Dqk{Y|rxN5@9G4XTv7ep( z3JsM~xfB=0FXB;*V|+8?GKb?Z``_tr7@x-QfX~K-4KbhE(b7}!eb@MQ@q5E2$JX?E zm=G}g^68gMPCLdQl~X#fKIe6m>?^Q|Ot@y{^^$D=qO~pG8_3z@tF@ok1qB1$o*eU8IQCw zw&UG;s$=Mbd^;ukAo+^$eb>HSl4<2nLR#Mr$+XOeGU59ly-t&TjeLxJJvz#muaW;8 z4tPD}_L;kIt_)C8*){J{xef+PX43l~%VQlAM@EzINiDzvU@5Q)*aU0`dJqH+0EPpd zJ-w6tkEM_G7#NKI1=#-u@E#KK7GVDu!h3kgTcG`qgZ~)g---R(_5UmTA5R%ivof~B z{#D1&{(U~e;cD7jg=9OQMlB!PCM5c_fhx!Gw137qt*3)r5#y}vI#j#^yh41 zyiKbdu8eOJqx5qGt$7(|(kF(zc|OYKIJRaS$}NHSl#q8~%N%{6#m5VNPi;XgGn^ZB zh3^dG)7&WFvzTaYLRo2u^a$fqJ>SMBa?hYkibpI__VgGIT-NQF^T3z&Hc zTHjvDw2Dh?{Y>(G8zs-vL~Hi|h}O4Da=tyG4PzwV2FX4WUAY)Z>uwe!*?jD#co9SM z^hxKlZUE?^$tA!_U_Gz}C_z9!U3t5{bs6R(N?ZqTZRbBlMt_r$;3Le=ZLMI>Z0X$dh3OMR z-e4`m_-qfkTfp}+GEXtSovneyWex3gBYbBXUpws7bpASJQEctoFZWDo7+b3!Glo0+ zWDVHG*#3J!IeS#M@$HlQ{)qaG@>a4u6bmR1tu3po%JzI-dd|7^w}gCKB-@Mf3vJfx zKABdw6|Sv#eJ9(jXl-q!jPiLM7jB1N(IkeXJXWBbHNYld8_<0$>x954U<%LzEC3z_ zo&x^eQfU7};=+Y}zZ-pVGUr`4mEDZ3ZZ)s1jd`HUroG_d_65(QexJv)E~bPon-~w$ z(>Zc-inQ)GB(^Q~GO~$2nx2^_rx1Upa%y}xUo$h75$cTbDg8c^A)QUWwC1|tyRpW* zEanY$hwY>n7_W4f$7_DHN5c3{w@fcG-gfv6tDF2rf55kUvfVM(Gp_f^u7CRWPPRMI z_Ko*6WHY{?h_ox341112~z+7N4upC$mybA09cBh;MWd9b!PLBJoy@Ov=#I@S@o4oqi4@-;?C2$ z#)f9r8A=sq>YfCL^}D*UYLG0zO$J`$aTzR2#a(imcicL$`;A7Xl~Y-+9<(NN{SWZ`u?g*-~g zTs%gndWpYJQ12O)EmiW{s+XECyw;R+Z%!vFYk0jfmZ-88;%n6>#B+9h->`jmiEffj zywf@TQtSHJTUSRnv^32Tq52TdA4V$y@f!V6aXtG6^~|o2}9Eu?-E;1iG0SsfXEv%Vs~ zj^VY+I7ji(%u#r4MqPEa*7tNx-6y=JZ_%ij?d_LV?@?~Gm3LYwvpBt*diOoORljtl zZ05RbXg+oB0iSq`PUlx~zB}iS=KS!O-|EG^K3RQOomKW-EkAzHrAm+7|MyV-5Bz`j z-UrU>s>=U=56p}Mf({A_3Oc}mpnx+lgN%aC@J~iTKtQ1&XJ9_a)W9G!7!=e87h5RV zu%NJTgBA-53ko;bbc52u!VPz&u+@^nO$>LT@Vii0zvsE<+|TEJKA$&Q%09lo-*0=v znb+ri?>YC+x#yny=lw6E{G;rvG+O>~l<@#0GM-P$DZ*C<G>Rj> zA{F1#TE9p-mFV#RY1WbE&q%XfmD-v2C83OePrk^Mwr39vneQP}Y%)@gwpsbiS-gl< zSnH^H^^08JmgQHWOEP zz3Nr$6Ln{#;o73M!57!%FW)7Zj_gKw&o@~qFV)D9_2u0Ke|PvPThz<=r40$r;J?@P z04=MOQRJo~cMW`vfgC|+mCLSUKNgoifM1^57CV!CWxW~d$+wx*UzT-Y+@j{DMA%?b zt~v@(N+REecTZ4%=|-V!s{Zho!2bo}pD}*1N13;W{BPG@11KEtqKa1Ckgkh#nlKGN zSCVoLAkTit%tq$3CL`^{x;8_`m$MH3Qut+U^%LV4oye`KVID0!4cwHNytuhF(Lj{b zY3D2+-CCHdndc2w^0_oCzM(nQ{hYt;nian=v1kr{!6)JJmT!!7C+{YB#|C+K%aWbn=tn5+ ztJ{$4iriK3eZu6#1~1E!^X(Q_=jq5_4!=C_FS-+XIS=a`CogHe({Z9hUbOZ!nMoR{ zIih*!?@A%;NHR{mV&&5Dzjnc#ro|01j!T34#UqYg8X5q{6(+oey?F4=3AFm7Re>paOy_MoqBAhEk9eGwgYL8Fuhcs&JJ3f>}VX}RAfJc z>=#W|@{{%oWu?8A5GMJ_g9Ve2Vcr{k#bm_p+GWXP=BNHn#>X(-hDIjyvbAJs%Xdr0 zlQ!=`i2fL)E#qV;mrC30(%Vmn@5Gk;Jb#@ya}KGqKkmbpnn#AVG$k=draCs+7Tv6) z>~+YBoaYsNN*aCN!luGFzXlLFv8gbwDRFN?{IBR+Y$}Xv$taEXt#_gW-=8XEaN?M% z;Qsy%I{0;l4z%)8_YI;mWQ5=I_`2i!oem@sUq5N9cT>KNRz8_S_+usIyJ3`XBYk9E z;@(X@Gi7k)I3WtR<9_nFH6|a?!zRkr4;kV2JYEm|0zHKLqL{lpgO$=z%D!9PeLI%O z;Lq`zg8Tb1$}jieNxo6m-f|sfKL!cE=Mj4oR^~6MGBzZd8s|5*CKj zTuJH>#?=RDzEhj^^M~zSweWvqbr4uZJzmMGhkhkg>u`+nFGEgbJfCk5)&+0d9wE=W zZ4bXMu(L!;&bzq8>D#fIdd#cMY>&*>RcL*7QkR(}D(m@ueFg;e88xMJ_>IHvx{D8{ z@_=?(YM(vivHH+U(qnKK@B5gvIo(m-LYmUo?B-_o+_&T{V{aJuK^FFn3)0sG2EkJh z&*S&0gR7EaKf3nKO|y0ZJ!V0DQ#x(QU&iWOURht%J7X4}qAZ?<=Ebv{61A=MO^tJi za{7_x2-8uXkNLC zQURdYR`}i<$cfty^J_F~6+i0rS+0Qu~J7z3iqO-6hPK{+y3Qs+yBhpaMq^qOUE zeIyTmL10{vN6DWdAL?W{8H!Gh1a<3~l}4OSx{{ID-K5*oI_Z@q7wV*%e4d9yC-Y23 z>f1X;CR-=0VgD?hNFJR_bg)?;-M=T0XrvC%&Ub!6_JkyfZ1k-z;f z-yfGXdUQ!%Uf%sbY;*tXd8^mAS-mT7O`kSvM&+&D)n@IXJW1EjWu{Bxa9pq8{(hV} zz-3dk9sInK`wJ2hDRtRZ!ae|UBIEhQ_9cE`Fg7RN<-F0Cv04m)qfefq{QU%FoSIX{ zmR5PepOkSX*tOkPh-nyKTA&S5rpyYww``IwoQzeFNjPK<}oqYE=5-4Jg?|U(kKh`oEk&$ z#P7DOCE{>6Y8BkyzoV=Vy-itXQqE(L$a!9=!v?}$g>EGLA1n=Dhw`8f3xm2#9o}s{ z)>=I-a>lHc`6TuDWmY|IPw4Ah%E7WMb*v@7lXqse@s!5-3*~~X z=w_Xi5jm0ZeBQSW4s`Qw`@ApXCM)B`sS>(xP81HGo>|7J^(+(Mc_%hM(qA8C14oYM z72MxXp^u4Kc}-i8?Ilz&#jP!k4SJ=hMRl=F zbV)jrhL`iYs0eh?ytsAY;#RGXn0*-MuMdl#7C#%tH7*$KR)+5C6nP4d=p&P7O8N?x zmFpzsI@2$TJ`C@TRv#%>evWKY*kmE+7l7h#F9bV-tnreUfby<-nY$CVVm8P+CD{yi1MdZyYb95J zOyk@)T1voAbKVnt1f;7cw}Y5<@}EIem;4@xDv}35)&$9y!GYj^f{gje-+_!*$pRX4 z2q@PWX_Mp?U?tca912!~!@wKCDv;-~WxkZ01l|D721kG`AbvQ>eQ3PBCrUE+ifX{m zgCoIB;3)7L;27|G;8<`Ucr*Aj5dWV14agEYc^qU(n{0zYO#m+dZv$msFcItnP6o?C zrlHB9;8c+Jb-Hg_P62TT$prWw@E-8J;Jx51a20qL_-U{n+yo{--t#WcB_y8&8^LG5 z_k;feegOP;a6b5JZ~-XyJknOl)8IW|0mi)uY!70}$^PJCuo9##lh=bE1ZRLt!36jr z@ckgRo?Hzs2iJoi0Y3+R6#O!{0{kX;AGix#3H}uP82BsjZ^2i=)!=#9p6e}G>B^YIAzj9B?tv3!e6jsh&JkXc9}Z)+-KC#jGf ztOEYF#}W&%HkmQ$d6k{ZcM>Fil$~F1=QW(m_Z{VXjuL+pe{Z$l*YkU<{g!m)-BZGI zV^(;Lg-e;_onsfmQw>&wBf(oOOn#5FxZ$9b&8Inp-{UNu!H!S!dSCFnf#0_nPx!ln zaG!^S%RAPj4Dx%7@izv)!@PzQegnLsGhbIJr@TL{kbhTzm!kJ8A^8qLXZIWr?P~WL z=ehfirA^LuMe138dcnXwnF6y_H1?4+l@{Lseu1~wDgx{>#`77^v zJCEP`J-gco(`UVQl8)Y6o0qybwV}LrR;itZ2CK#Vc9PyZL#+rV0Vx)(Uo1s>7I7p2P`3cFxU$m4NCkt zi)XBoHM{#(a$j&J=iJ}mzRP(vm>f`0RTC7m`D{Ucm ztM{O$zc(srNj>Elg{;(vXR%y;#)49xT5t$>3s?;@FS$?p!bHv)uibYX^O>oreMp_; zdn;3+5-9ymU-4;rKWJX+zS8!Dt%T&5N_vw2G*I+;Cn)*92bBEZ3yP26ISr@R_kp)_ zUI)$q=YaQt4WRZj@o`cv>37x8t&sRQ@p&^-dZ|Fcde3HF>ORo~BZ98Q1tg5HK}31=SXzIpy3Q1r^Z z&&dyh+-Ko@_ea2wa?X9J$uEN|&_6ykx}Wo3f?U&0z5;SxH2EsXb;TrpNxt>z`nzD1 z=k~wc9F+Z`WJk`~4@kG4kDX;4crd?5!?ahx8XV?SO}74auE19dbDv~^Gzc6O~9AHXE>KRD`mb< z=BAW6IS2eVumwB_{w??ua3lCr@b5w9=gG&w7s0QC)G_(b;4i>E;4i@+gTDfw1787u z2_6Ms0nvq;2Q80 zD09-^gI@&y0Dc`j1MURh1b2gM`Xs*%=7BOdZ3{jN(k4l{m$?bPpBugg77?yKOTLGA z5o5?DBqDyV6q5O9cl`BLP`~JW!sIv)A9Egkxrh}?5%b#f_}hW8vxt>c5v!ac(owpA znd}Yp_@SgDbIzXp?M*t;Q++y};T;T#Y+CNTsD|?@3%>*ux`5f+P*U;pTuD#L)`v8E z25Cy!YN0EGvJK(tbe!*Ln;l#$03skywoGx!c@8Z-mCi89WFx*{_Q8UXchq~(%tiOHP&YEr0#OZ@vK zZcIti-(DFZQx4`^{FXy}Honds9cfz`V=e^6r}GTG8?P<`ui?B4I2ODFd@snib&_+z z%fMz(zAd;2ls+#$QO=ivJ;0BHSAd@ZOTa&ZrCAi)rMt$E8~uQ zOU{oyvSzvk%au_~<{u^KathQFosY%d$J1t4ffqtI8jdiOxL)>KW;U`H(VMh0$97p` z>%EM5srw*h?BRQH?ifw^q#ee9ox!o7SlKvG#;RMvk>G8h=yfvqAb30YX>cm|IdB@d z5xf)p2XH$02q@qD+YZhGzXQGxWWFBV1-=BXc1Tiwt%%Demi+P$lgQpPH-uh06z@g11<;g ztM0pb__JsQ=lCu6{k(4IY9;5iar80pIuO5~tODiRc+@@mI7r>22SD%E3~srwWq@8g8a@k97!&GI8q z>L&e6=CD8Jya)Ik*bn?yus?VZl)36pL7AH#0%d*m0$2zBJGcOR5fuG1&q>}7{sR0o z_%gTwJPdvX{1x~u@Cf(>_zL(h;IF}7fUkl_z@y;*0e=IYM}K7Alv}%$uXr;Dg{FK<1~>8SsnXAHkg<3QaQ4 zi`szCf%)J|U;+3`@I3G&*be*?cs|&H{(Av+&{ZhWKkz5a60d5Ab1iu89fY?CP3#84W-r!HbQjj`FeZf51{3@^z z><3bY=xUHOqH92Sqk-Tk@LF&pSO!i72ZJ&vtpGm?vWJ>n0S*N>fy2OUU={c^kiFI9 zx544y55N)NGhj7%5G0S}i{P{9_t)T9&c!Bg2Gw`zJWkfzI=ARZzmWa3aKAC!YYg`p zeYor~)*>hKI@x0!ZNFuYQQmFu_ZY))dEdQ+i+}ZdeX_?Wdv~&5R}0CWpYGkYk0j3T zG5R#6oPLi_{A{(QDSM3mcLTruK4kb?_85I05`GKh_ZUZ6IRw-&L3buxjtS^o)~~mLvR<78iqE|r><&%=dxPQ|`ha(EJ{Y_clzj~B!|koG zkM6!#JrjH%;j_R5D01SH>o{)(>%k9$?*rF^3Gg4mx!`{AZcyd~^T5MkBX|^KUmn}2 z#Yf7#sWZBevBi&PG8T5_d>nDIS0;OC*>Tf}n*v=0>HJ90`&h|a?*-0t_XTr`=A&qj z{NPwX{++;uU^j3PC|0@{tOoA|Zw95l;v1K8eh2s=a2EJMP{yL=;Ag>)fL{XXPsy)= zN${UQ`jy*{yAMq7Q^@!r?_`vgleLf5FQ0jSK37w8P9X18${fSC!mIZNr}tDk5GLcV z9DGB^wf$;P!aol70zU!Dn6n0yvFz`_vEV1cap0%GY2c?p*$ep$_!024;CB)5aFf-?Vn4P-76{RU)i5V22?WGs*V3uMfWehV^YM!y5| z@Y^TBV(<;H2l#)$67au4#-ivH*bh7n(qE!Kfb@gt42Ydae*&?&C@-IKfo;G?z_uW5 z6cvK#HYx(qY1AI1?omfj#*Yg@${ZDglrg#pB(113DA(UE1uqA=_Ll4ob^`~4mw`8d z#3e_9-NBnd`6k{vkbRHjMz93j3?iHS3fKpfYs!7Wr@*Vge*>=uUj_$&uYiNV-+^Ud zVFBYP*bW>5UI12teL=1TCI^7mgViAWE6H)-aPUrW1lR!H2;L1+=42CC4ekahdvY&0 z3j97e7W^^DHO1s%uogTD-U6Ni*|$j+(2*vB?ZMl@?%-6g4|oT79e5{r6Uci?lDC2H z1@8oBg0sL`;B2rCd_OoFYz7nHQt)o@KCls72fiQN2z~(kD!2gL2{wbf!A0O+uoe71 zcrPgLp;!X`5?l(t27U-U4SpDG!vuC2DBt_}C@A0ZSpjwiSAu=PkAc^MtH2s?HCPLN z9Gniaf0e8U{|>wx{3O@}ehQTLNMH-erQl~knJ{kvKM#Hml=o9?1iuM#EjIZB@C)Ei zz)j%KL2M`aGPngi3O)j!0JnlHuA)c5Lhvi#h2S=@2e=&^0`34ug5Lmd1|J6}g5LtC zg8u~01fKxw!S8@A;9hVU_&xCNz^A~^fKP*ufcwC&fzN)w`9WC8!2`hnQA8;U84BiRJo}uhRN`8{Q ztluTiKPO$;uak5y&q`P7;M0}5TyAOJ%I^~QJGZQ|FC}HY($bW=NLgi1O3Hd0B>72M zOWkiRr|eapEzRDR<{-zPt(zidVyZWhm%MckGL!GxES_sfYZg=nNm4&KlcBzxx94A_{T|}#-wu0{dbVSZu5H^66rD-Czg79AyxDn6J4pG( zP6j}?Lz2FvIn;hj-7bVmv+|I=Wo@ScwEbn+uGqU=^U^&Ay~jZIHuRqBJYw``djjWyGXF0Ewg1RGPx465spsV}rm*24^SM6!mP6JQvKE)4BeJ;h zh_O)je?ghyUIfZs%Ee$GQ07}#ftPSz0bUBqK1645GT052eU0v59oPfB8x*-lu!Qq_ z!Jgo9@Cs1o;C;ZIAY*WHAILSmq+C1e5B@7C^3Q_zs*B&$1o}^(}Kky;nOgbA4_tHF`rt>7r|J>VE{AvhNN7svCemO`S_Ua9=I&=$XBVJH4Wu0_ky6WUR;P4e=cW^fNA}D(Y zKL?kBzW|e<_>%j;|KMEq2!0Jd2p*=s(&oS6{CnUrP{x+mL23K{1hvn~bsDjIxi%=i zMEbd03+M+)e;2LE{PPm%3eKgk%U+P)uj%zA{<8NB?JEyE3D&#d0K(%`KJfTTrQ05J7!BHUVO4rAW zz^RAsl)lx4@O)ZbNcO$t9ss?b zBy*xm;1JzN+_l)H+;1lPw_>~UyA0~g@BS7p_l?T_Z&$3vU#sq(`u3>*o;~g+>O3CZ zL8GBMXbH3t+6f(kjzgU%zypng>Y!!NI%qqz4>|&!fl6*;j~uFlmO$H}r=XXiQ&8uL zqyvqI8X(zF-2iQe_CYU0r=a3V%u%3mP#v@kS_kcd4nW7Cd?rMt&~T^$S_W-|c0$iX z$Dj_k!vj@A)1g-A0ca<*A36p7_4vP|fqb&{?=Ek!B3uv@<#Rk&(vC@)>(=k!8)b~0 zg>C2oJ`Wj>X9mwGtfbg(pN3uM#ZVi7s5NBp(fi{O{`V+>2m zenLLKPI4||*K5+)9O9>or_d*%;m{;#9^@7^j^nR?{y1NWP?ZsFgZ!#w1kQ8~gq3drM==P(cMA9DxOwA3LLU3(7m*kE~t^*E0_j-JCj zxIe-j;=}w=L>{l5!#wK5fpdiQXh$BuJ%@R4oz5LH@ApT0^7!33%%h+A_^=-5lgAaa zGW+nm=^qbR9-*J${*%Hh&tV?y#k+%HDRp!tk3r`!5B7oF5$cNlm%%KhD}a=$D4w>(0- zVZW~MhvzVl<1u+$OddZvhk3}gJUPOC+?hP~pTj(M#pKb2JpTP0=Fy#rwj5!5a1VFk zYv(YJq~#InihJz}e{&A=I1*EjuH^CibC}0C*+At8`$sqO_`^BOL*Anp9G0T}&ROrVIHeu^59%tSW7#>(W0IRaXSVq@-$m1W*VID7A9-*$TC66uVFptp}tFA)3 zDkG0==P-}0mPgng<>c}0bC^em&RUN!kHO^e#5u^rzw3IL?c^s%Dsg`E>`h_YyTUo|sOAN&yc#aC zXpFsD@*U;r-vc&4FGptNIg~s*$LE>x8f+=+JE`w)ksA)_o^M`i%nYx8$aN1{zRGnE zX#=LXNxgpDH}cnyO9|IKTe;gp4?(#$AqRbw>mK^92;tSe*LYsKTn4Z1p~mxa?K#D} zlXP`2G>^L|^^mFAR{PC$X?VH63zY4s5>TeOy+FBk-3ROmUIh*UuLi{yMdq2)eMxvnhtgv$FtuHbsS938onPM$fxTuQ+a>O}Wgke9 zlkqltE4)(P@u1l31Tdc#m-_&G8e$i^|Cq;5d$@=E*Z zUS_<0W|OY3o3!73WGI{^{FWnZzq#;=%}8COZu2;orE4Q7b(45$M?tCE2f+0G61}nE z%eX#z9c`F?&Q$XJ;#=g|Od4UH_i!$GE&?S_iI+SDCC^qcou}OUR)TGhAkXwWZKN-J z*YYglw;Ym(=t_V8|iUEU9`l;>lh z*yZ1X*>)*u=zdy!8lSK<9C02LEoIjIviLGTh>WkFy@%gQXSIYbu zP|EySFuTl>pYChL=l6MJe16hqx<3`~zrFyklrn!8l)e()8!T<6dnWO1_I+d|jUPDKv`>({ zbsr=??;n}meo*p$*2&9#YMI}u*L{xox;}@DudC=q_bcLg4+gwaC*605uhR?gN}YZN zhQ34UqG5^_oyna9rLJ!{`OLaX8oCaTPvf+u@q0_-4=#;d z`_pxHeEI)mX)xR+!?qH8(6w{CJ>sKNveW0qPCio?Qchie#+UO_WWqY>Ix?P@_nxG9$C0kC2lG;EkbJ_V z{p7gP@p2EfD--vNg2jZFx^tQD%Dgvi<12~NbzEL*9Vl}}#$FK&GKD`l^-c6QXjioozoy!_Pbfx{1zT>XnlqXLyd5(hiFrS0I5ZWS2gwVf)Ci%G9kdNP1pUA5 zkpAlLt=evd6Tj>ao}(&!xWx7_?EX*LV-dL}knsBW_EBl4X;YTA$TuDSC+-E4dAjb? zT-}MEsdq|TEGKsKrMzD)$t>?*vd*_NAuY%{FeI9owTJN%NS-zWm zj#xgjuJH%{uJ9)%Ru{fv`fl?1Es4q)q-~YHZ#7)|upUa?uXtR7NL{~MWPdsfT7Y+6^Iy)oXfY_xGw8eOnGJ1y7XzfW>b znWGM}DC8)Cj?>5TS>JVs%Aj#j1GEg<0R8pI)Iiw(=UG(P{~yH$e~Axt=4t((Cqmx- z-b&Jv@le`Oj<8Q{av_=bfPaO2j{AJ1PfblMY0Z*5WOCBx{`e|#|Lx_Zj|6hwuMM}p zCFSwQHst=~<=(;l;G!3)li2QXNOhF%S28z{ej`T#Hd_d?HgNq*`dM4|JWcw3aOo>r z|MdOfVP9#FOjl+tlArKuozrv4Y~CJG&s4wCddA-`E`3(o`$91Le(~{A362tIJALOV z=tbxx)PYSYSx?GZZ7THF#24hu_HLO3@W9NIAGr2A#{nB6ZNwl~=?PZsk zKq$+zu!TPeW$mg*3%t^I{I#ZCF|xe(vhZI**(r->^L4D&#rj!QC-3|BOjkJdHNqq$;bas%vGdFQb%9LJyu5PyZ(5HGQQ%=_%5EU@jgM@Dc*mG z@9D#HX`WZxC7zcxR|c=PLp(1-Z?Z4rv7{^hPIVgZYsANhufY!|y{{2D@t>-PJm=du zWe$<{pHg-i;-y@dfRg7Rt{e=CM)DNi$kaSwJdRe5evs^WJOIg>dk=I7It3NqMLbju zO@;oqAJYH*HO!r+jG=*2zKo4-^W&uS|0xR-a~kWLQr{M$GyC1V0qQns(Zk5Zlc zdYAJ*pAUPt?vQry2W?jP{-x_g>9Q)P z`#bxr9MT{B!S#*8L%uvR9@Q>rNG#BMc>JD?IxF29@N)lw+%LSGtP=w{KM$=opAqKw zYvg|I*bRsANsXdk^fIGFZssE`*QD!$^R(w|HsR_{JDLI zF*nqcyt7e`FyGgZd(+Fgd~@ZvH`Eo!4<)Le^PzxJh;OA>P#-o?-+6&yqx40 zBj=wL4D)*(xz1ir>NmCiZofY8dN~l2-+v-^xtEjt0y#gbQjsaY+D(vm$-oY3k z{XujgV?Yz6wx8$vfhbezRwq9=_??t>zxZ?+Q^luu20Mb?L75K^051ZEfER;p**TT> zaL9XV^q!BgVCFu7+JF3fybEcB`vhw9>9Iyk#m|p~*Y6XQ60UY0pDtrx2Cv$5e7eHh zi}#iJIhxvUe7cOuT(jws;#HfCPgi)aVBf^2t9BZn?&a`?dQjVpPgi(DJ*Yj#r%RX0 zNLOtzK3(DU>B_jTb{9W>_k>s0M!i74Haf|<^s$d&FmlvEW&9Zp&4iXfYoTq>Q_vCU z4Ai|IzYL9s8lYv+I%pg86!ao=66!FUwJgF@o6s$4qVt5p1;`^E6(btc%oc!g{4=8vlYG_cK&34 zJ+B#}c#z4A#6NI{Z)!j&r+O$GneqZYZUwAwB)?Y zNX1U3-`YWXzIv2mm5oUSGxdD;K*dVhMC1!h&&zREa=y8b;^9ig*Ly1-tW|ttoMM;j z6l;yYCj*X?AEx-q1jQcpiU+NHE3Ex1Ej(d%kT5%Vp-TBzSUWswWM)7L82SbMKFz4o#8USaM1khSw^Yv(oA&U>w$pS@GlNmx6-ZtdI2 z+Ba{8#;>q)t+2V#3)bFUti9LRUdJ3&JZI(ZX#A_q4h9{-m}4!-fOR4mz2= zCoH_i?4g^ErYW<)7AGalW;4&Fy;rptbL5Yu}#6H^bWZu(iuTYv03WH@mGJSDU_S z4Nq8mZ?=AY!u0*Rwc|_OHQyb^|M=y4{-)XQZYy_rorWL0OYu>|8p9p4G`xr53Df5Y z(_bgU$+s$BAH#adsHH2jtJ zin|TpFuQohu&4FUH>`g=W7x>VU;4oaL*CEl&Uv?@L*7a0u(GXUJ41Qzy~yq0kKp|t z`7P&|xkH-4p@a!NYIe|Ll%79l`gqC8^TPWye1h50UgO_8M#E>A9h~T+=esXZe98KA zo~6S(^<92E!|$+%m9K~OlXBC`{k<(6^NUZKpL&IbhLm@?`J2X@^}MGqr}c~1Cu#VK zD#b1n6>D!%OqhSEF+DzLcB}6X<^EMmr)IeFFE)QN(Co60jrXhjYy1xLBQwm8++%*? z74stx)+ygC!{^L@Jnikz`u9Cn-)F3TPg**!n|_`%Kayv5dALT?oo4O!khRC{Y}r4P48>09bc+8K0EK}^l8P+}{Zq)GIrk54gemxEIOs_9oqkOg2POpsA z^U3CCYs`r3%zmG? z`mDBgs^6O_Htb_|SZ;dX zVS3+Ntmz%TNpXbf{|yU&$;#W!^uONp|EBee7fgR^OfTi8_lHgIjXgBo6{hbl#$Rvp z&lPF>X47|#>HB`O|7We=tT!BJ{^Nw{|6$YrV`kR{rvKBH-YnDq(Hk_Mhpl~Qnf`ZJ zdM}yX%6BZpuN}2^SbUY9SDD>DWbM)8P7SZIep6uW@`{aXJ*<89_EWye);^C~`<$?H zKW@0xaJ}VIVD0phwNoc+#~s#Ajn+=<&7L2&_I<|Ar&+u0w(`7S?UrZllxO8SXy>~x z(sI^YyRESPy4=#MvUYsk`#0-ni>=>mwsu@UNz-X(`tM}z`MTv(HPrNB?fal~ku1k%t(%Sb~OMkVs@6*QjbiK;GP_Fo-wfjM9_s6Y%V|r=)GgkiP9rV21 z?BcN5MaNq;ocG>3yJ%|#Tv7lv<1r@1@qi_y&?|hyLbods@5CH$8Q%)%X=wu4!ZSeA*br*G)gQrvKemp8lryO4G+I z^LML@Rj$^`*XevcpJ4TR#{5OSl}oUgK+5qx=sJGC9LBruP|_YIvW{ ziYLr(k1#)ixU1iKOJ}mR`?Ji4Yqfk&-=hpqmbt$vI9X?o9DJr`R&$5{A- zX6N-*@5jvE`&+sPd#n6Q7Cytm3(UUmv3b{Ii$8jm^6#~JbuoK?u&0JEHT`jKkE`bd zt54-9J@4N^@ln&;o7Nwm8>r!HZdV*=;k!HO`FzvcEVI)$O<&9FHU4!Af7oM)BB@V{`-w@md#ftnEgCtd~2*7)=$v^)I(}+idMN&DyQX%6r)A z{kpZ=LpC1FFh4)T?5wB7*I2tgWbM~z{QZr;zww{2^lPkLms`7@uy%c+M9cZ6wX1(u z(__}I?W|vIw)UJ{sQiKolC{sHrjPz6H_O`NC2Nnz?3{0fx&Bmet>S#sOUG(Guebi(&E$@D z((u=>gC>8EVR;{wd)CrhYV{v6Tf>)If0OTz zkwqlm5frSkc6rR=k6L`A)#C-5KR;%;!f={lf5SIzym`*>5yPd16AXJAzG3tAXAB=U zyvJ~iVK>9qr)zol8m>2NG#p{r$?z2$FLxWRF|0SNG;C-1(jA)q4#WEmXBZAN%riVV zP5B=+Ty8kou#e&Csmk}P;bz0dhP8%03{Ol^{-+HeGVEmI%`4{bb{noStT(JQY-jk= zaI2T${f09P2O8!X9=yToWw_jMvSA;?)7M+Q3^yAtHmo)5VR)j->Sg$l;e5jy!!CwL zhbjLW!+OI?!*+%*U8j6I4DUCbVK~q*&+y<-<$u(0x#48PK8B|&mG4=@&4w?SUzle7 zD$n{^CmVl8*f`v1?e>cG-#2XBd&KaqVbz;{_sY3 zJx^S&_}oQ`tIeMrv~i@H`H|J_HNIOr#fQ#QNBH2&NA$mjWxtW^0c(OO@}a>E)$adOpU={gCl@ zvvSX}a=&8j_o$V--pak+%3WaPzQ@YF+sa*Kxhv|2Q zjZ?KYo^-PIuQWSsXLc~6TIH6OE3P+tuC?=eJ3naknbFz!&CYw6J)f@8@TUzM&Ay+p z{xsjl#}~{_DovlKC#u{th7TEb8L#25SiK4oMN#|9^YiklcTpSeU8zn+bxH0;Dee^| zONyg{f^Jd!_W98Rc}2xV=t$yAh#$GOq$pX!_i)hTW$p9iUHkdG>pUtR8A*JbYUUj) zO1Q2~e0%yrey1p}XspP)_^A3K*j#)vYJUx%hUK+1MNx4oejJP%@8pxC^YSU5$*+nc z(l2)LVgvv&Bg!5X z@2RGWKE8caqVbfxI6tZ;zIsozHCdAEKwi8BSdNjBO?5E=9L3dbkS8nd(3hIY(S~AD z^EUD*#@cG`7D`r2eAHg7F|SQ=FFxQYPgBdG<Hb756&qFUmk{j>Rjru{=(0Hf;S_rLz zHbL85T(Kx?6m&>rXrbOtKP=Xr2w5;PN<2k{+U`6jM>=QesC zItCSEfBm2eNS+^&?;bCNXdiS8 zItBH^7l=O?4=se&LGlj47on37w_`@7&^V|GS_y50c0zlgL(mcE3{-Rp`9i~>(NHV& z0JH^q9y$i)Gxilj)zEaP0a^uZf_6a%pjV*|bh=Wg3>pX3K`WuP&{k*+7BIp&Ok-IunlMc zGz^*v&4XH@B=i8Z0onp>hxS3wL&u=}-joaK4)ud7pz%-xv=CYbt%Ei}+n`<0Q_unE zMd&2dp_F!pN}=J`pubR0SZjqXERLNlROXbZF*8pr%(DztC_ zWq?*e>!3~0Hs~qn0Q4fXaUkhKJE1+$5$HIyeGu&c?Sr0&UWSfA`PWiss2@}TRYT*U z=}-f-5LyPUg4RLXpk2_5P=~VUug9OEfs3L(cvo}{T^i{FUYA6&yXV8ohL&;6nJf3H zEAQ4AUJX;;26XRvW%iPtu7(+Jd75`&46lY6?_j=tW@V6h#HEouFc3VDOu2m7HQwZg zFb6d`CUhp3ei+%yXq?GZr1O%wiRP905VDukc$2G?GN_&&aB}vLK~OdgH~yjN`b!&J z6w?M5Mao-WpXOZ`!>eJ&J3C$eQ;s)YR}90k$1Fnqy}_{ze+~TqjRw>{%x>nS?WTf0 zc9H92@piBACfAU*`_`14zKp~76Ad^1M4Eq_<9847xR-u-ehoK%{EzQfM;w1{ztV8! zpB?xh=~ta&`c-G^SF`D}-e2vE;ngrpH|VcjDMxm?8fLuLrFFT?@y7Q-F(i#Qxnb$L z?n=o`XsaHvi zU6-g`mzSY`&pR)MSHoPoVi}!UJZ*>ps;i;5d zX8UTm@dx&B#_{L&0}VHR?7`a)@4%;wxox50#-C*q17q4^pxJ~x&*9r`A8nD%t6`dM zxpOm(GnruQC_+C2osGB$Yg2t*!;L=} zJE|SO=s%NR!)ll&|*kK|4wQ7sj;zh1M5`2DUOUhF8N}y~>7Gr2C@u{R_1( z&P&YsK!RpV)kWh>hOyN5U)c}5FcMvl%8}7HlVMEt_CDIlISsneCNzVUuU<4un8hjmuDTpN};r^-bg!aA!=rcFwn zQ~bf4K;{ZpI=yD{Yq*sOoAPzp>G-8T#``vnH@W(>zC^d(V|3fyY-uib-^=X2$?-}a zqnj7cZc2eboD!R~`TO=K6-Tel^T^>7Sl=Q(GxZCa;DWZ+)6~9R}1TnpD52 zCA}8VFyoz_wspCN(IsZ?py9?J%*~ED{>-_jh8Zt)@nse}9v0&phMC`;js19D@v+&w z8s^e1pN-x4{v&>M*jw};jW@Z#cEq=;9CpBa;%L&8U2B}l1mn|aCnIf|E2D8H6WC2M zl~1M}Xt?nQb|dSwVd`%(>`cRrKk)6cP8$}}W*Tn%!Fo^HpeJclSx2Uo?kmDKAhtHY3B zypixC?Pm+-WQ{i(r#c!OluOpcMXp>mIWih&GC{doQ~8W)UL4q*h8urNjC8gFt9X}g`5 zlFRJ>8gBf~_vjw5>~E;fGWj*!_=EMyp;Y>{@*3?_c{E)4htQvWKdNTz(DXC;HQe~= z)82NsI{umls+3Aw!;ClR&l@p>q9~JB!;F{y>C=rEJF^)|0RdtEeU#K50?&oJ32DTN=B?u`i3pJGsF_kQ-!WIc0J(`LP*d zdT}Pnl$T|sqx_Z*%J+3zg1?abW7D~_v31_0=9WgOrAxCsBTbdnG-X`%Wt00^(sj!C z)Sj#1;PSiZg=u{&zokQrPbc~I>Co%a=_tRYL*Mo3oO%0n=w<12l;6@J2cM4IU-LHg zqDQ6EQGQD&==0L17sQOO7uejO5}WhuL74+w;Kru2uLqUKJ!r*8gBgc>GXFw{@nJ^aO20<`Y}%Q zb4`qXt}*>oV28f!TO6@mJSGx#?@T@dxt)X^YaBwkY+simrUS?Tg{nFim$z&<6%k?(B3m%y@(Txz_PY z8>fdMvZ7A9$E)!shi?3Qb$?1Ocb`M!OeWAz5&9{OSr=-!@n`90NQ{1ln0~4n()yW4 znX`E{Ow+BR!M*+Lcf4n>v&NfTVBg|%hB$l8?8_Ri{Pnb%w})!SpS#}EaN`ertBlJ- zV)Uco#!uUMn-Kfy6r-O`s-H5cv*(quCYx8oT)JgdK|K#RUeQnH^;Zp7{;-}>|4y#o zXYy;f@dx#k`ge-aqlO!Q&~K&wntrC#yve>AXmAG{n$*$-@NdyG50L4Z)$9n1+>pY z<4gv9d6|7)rglNXOL-ZMGnt@I$+gaFW7sN`#!tWUK1A$fP>h`n@^%vVrgbsA8m8&W zH9T)qvc?(YY$|>X(s+}juX?!(+Ck;w_suolpjz4!!rs2lV95K}E#W8xl*!=kHz;`yGtBYfNr-r+<%Vgi$_n$3}KX(k$aO0;f zJipAYMrQfCa=@-5qZE^hZ{Vv5H_$29H6*0Qka97Xr`mDJ_ z|CqA(x3Y)V9i;62&r#%xg5<_=7P^^nKo0>?u_qbQzYtV@%mQ zTG=a^1A2e-JZX1yWgpwPsHN3;G4CfePRk?rX?dAq+Dc`{*PBR6{~Bj9_*Or@k59== zXl!U`N|?J$$!WaF;bX(P^oXfT539@Epx!cv&gRuHO?Pf!Kl>f8tc%9i&rYPTQ);;J z2YWf<&wIEw%jDN^<3~r{XAF1zx%RB##*co&dR`w>&+E+x%y#3KUc-?(T_0l)8t&3A zmwP$Fw0p*+-P6*Rdr*D3*O7KlXAd<^jdw3dwU35t+Ts1DqOYD#FPZ!rZv2cJ-VQ`x zKK<6jq6PJ>3AYgRHmC6>$JpWJMmst2!8J{BavE=P!F+UOI=|SxK8-iIinJc~q~yjn zHP@%FO>4OE2Yvcfs(hLJ8gBgbY2Sy+@JFhLaf!ye=e457l&&?-WUy~9GtbG04svBQ z&SU~Rm+N|(5BpvpNavy9#vj=Ep;R83{2Ffj^=UoHSg+~p2R3{=YPj*wPV1Xn5xbX*l>3Ayr%4y#{@}VSeQB8S(&nLV z&(GqOI-hU4l{uF052D-i&!XEDe=sIWI>j+*7hBpxgSG3i7+wu?WiFGwBVXo8)UP9 z@nR#Mw-lvi^JAL6pvvj6m#v9ng7W!#+88pmz>2E&WqQYEW z4KrT)n&)kb;ngtX4f_0n7+wuC-eA65!F>YR<<&6b#fE(uVyc%Y_f&Eq#*NrsX_yZf><@huEk%k#> zV8h*cA49g@G|YGd8&1aXYMAi`Hhd(8SHqNdSYX5BI^>o?!;CkuVR;`!c6l|-cmo^W z7{jY!#v9l$7rArN)iC1?Ypcmw;DcX?#nq=p%9V86pJ$>r5B;|=V0Qw*<$8E;^}?)@NHeJ&8~EV;jyLz(y@ne0YtM znM`2I4Es^4X>e&>-t6?tP^1!8S3k0Rjz)()n-!FjZ%bGa2ga^I4XaPbi~tCPP2=^VMBWCU@Sf;l>~IWzp;K7`+ZR zz0SejecGbK;W2Yz4cD~iVDnc8&%%vN-RGBkPaJL{r2{F)NX>Jw%)fmaNf++#70gWo zmyk+Bd0jaMSJ0n)8fV@n4Z43S4dt~o=x08SCFu37>OzrIX(+Fyfn9q2NgX@5b=R2r z^^NI0Fb#M7WfkP<`G-4xS-WTQYq;@~zPFdwRQkDliyCJ#^=X;ysXTIJG|prK`#+Y> zXK_ z%rz;EGa1G`Z$A$>ncV9?8gBd;zt2PVU^<-T8k5GEOyCpb-D(|Te1e7>Kb^yuX^-R2 zEt7^DKYiEpOW&w+eJ1n%6%BX%<+HJ8&o6zW%C&zczlIzC>|k!-_%p9>N?)lm|2G>O z_G!Q9!gGDAhFjVVX}gj#-tad2EH`*Ri!=1?P@R&C-)Bk5U{l_Pm!)LRzR!}9!>)Xt zo^W!xb<%LH)0|)~C3`A2WQ`XZX1v&wFO$^&>bI%?)mHzCz>ig@+JPU$Ytazt6@%8Wo1G8ZFRgdKZw7N zL*q>@@C!#$a=E(FIFkwdLJ4)qbM2CO&zXiBKkevsB>p+i^{GsL4L5##f^Unp>GT)R zZfR|7T`V`#OM2=1BJ;G}%gO@ZaKOps+Mx_6DyZ&ypZA>f@C!>eJMZUf`4 zFaLhWd-k@_c#{jpcbWTjjqz0)Zv6FWy;eJZ8LKjVm4+LCV5>_Uf3AKs-1q~3CAQYa zm8Z6WpDF!oxbl|;^9_E&FXhSP*Kp&fzTUo@9Dkgr|W{v$1Wu8hW+44UwEz1_*=>QlpwKUgD+-nzxuTQ_fSr0we~ zddTM0Filr(GV^6W;CRK}sBU6WVgWZ=_`afXCc~V?%XFaZ-CSGc%4nR*Bp6qGeaAVO z-1=&`@#B*`ztp!Zvd47z?aQR$j=%gm{Dd#lOwxy69;-<`An0W@&SdZv{vHOITX`9O zF=EVu)Pv;}=mNglB0ZzING|ps#zEi|rua{|_KR>}Em#KEsIFq68cwKBu z%kWYF9&KCDsu$aWHc%du#m@cvN;Vdy^0NUbe*98ClgIW4+Zu5td%afP9Qp83EQ*q< zhss!5L7&*h9-*aGyI@Y!V(DYPT{KQ*WPjDS<+x5MnVh`{jWd~GtX_97@aGO~d?VSg-x13=NfNv^f})LM)wNjCN65gh4a))ORGMS zo35wwnLPc^=exakAdma3zk5;rLMA6(ry6f^^gS;(v-GXyG~VRs3tq0YPawymqxFpo zTups`8gFtz|5_KyO=+CJFnDi<#;J_#|N3?x);Gv&YCTVjrt76~CPV-7`rH!AOk2>L ztx;c2*<2NoI zAC)<`(Jp zc<~#aH)@-ku7(*ee!}xM#PDjE@doX@FNRmcjF)!y>B_t3v-PWC#v8P;%o(zIHOzP$ z(&?Uz;ngtXrGNP{OfSeySHp~#zU_I73v+ojOnK!VG|#&)hF8Okm%i+I2QatDuA7D# zZ(zS`V|X>pcmw-A8N;h##v9o0^rGA{XqfQ^_WMK(uZ9_KV812IU9#(@Va6NSugqDp zc{R*<1N(h7hF8OkH?ZIFT+hxl zlFe8iFc0$iE3c&y*gnH3Wyzi2^|JkFd49m_duI%1UpQ zi{sDTm(+0Mr>}Yb7af1@oL0k)pZ@0UOv+yFbmYw}^L-E+uX0tigV$4aN-lS=TjNZI z_V9Vhbpg%m?AHa#O=nfKiLaCF|CgWTx;D;r=AS)jYbG&8c0k5=gHm`;mFXi|3J>YnA+fc)eKk(a<=jAcw zxZL(a6ZCc8ZtEPc*q^)yNp_?p-}JMADVdyk4^7eofp}mQX>4UU>Hu{mbht zJFW|HKELd^9>jI9G#lCRAEc8fyJj=2YUt3>m80-ma{S4xLcRqPp1a5>5xv}2e~l+i zsb_f9w9ILA>8FPIXw=wIqbf(2GwI}b>$Kk=Ra=767H^-nUNx$ztSTE_K6aGL;BE7` zGm?AImhib2PNPY;f7o zVOoQ?*44dHDQzIf5p3!$(v{a^*Djdb99=i2s*>hrwWG&dr~iRyl_fd}{4>%|S*==D z`RHL4!z!z4{+zsKq}pAst)4Znkr=f3Y*?z!h~XU?6a;`z}i+c}bn-!s+Sp0lHEex2#| z{U;E4`H7;kM1Cgw+(PwgS2rJj>SD>a-m#sZQ7~l%yFVqouX`DvVQVvGGAv`3DvU?U@)P+P_La-j7SH$b zHs7OX`IV!R@v>w=p$untg1!E0GwX{-&#SngN);Cs6&B`|X3`g5rDC)d2@SUT)=$~X ziVJcRC9$|`(nNiqm090dIDk><7CW;aX*SWnuYShL|>f0Gol=6(WD7T~} z9xZkE)TY|}>FO4*E$*>xQ|W%?scJkHVRy~tve60l{Et&|Z6{%MQ@)*t%LRGy(rB_I zqkVO>ig>=a;@|t|q$Pj+zVX24t%XI=lCqMRy8-O^pReRMlM>EqWl6&wX;EApDJ+Y} zxqv6w{jN|_*Am`Dfq5TS=gdvqxHFX$6eeEZJ(Jj?VY)FV8aP zL14Xb%R%Oe7+cX$IfvJ;#S`&@gfqf5lQbr&9qwvs0&!Dm)T=z&O;NnmJ8;|E&UiK1 z%l~t>dO4?dUd4QV&m$)W^(vA~M#>^FHvzl3Q%OEd60MLp@&34sy}_$TY5O(`d3Vkx1n0(~c(cJ~6X> zR;G<;++hpLN^=XMWr+;RaE5x_E5qHkGNg^r%8e#D6V@ku_PU?xpG$7CwHxP_dR|E) zuedmuXCe~pek;^--mz8sg21*eKdVVOEhsB=F45eIX)=vVRcw%x6*Xq4B@Jh&=0cT- z7AK;SB7GX%MEqYJ#`#Z?)~4y8m)VTSnrgWn~3Lne>krXI3w+-)KQmVNqUTCdcS` znVqjsoX^7uzf*K?Ka>_k3bojri zXA=8_ISoc+bv!>tc8#?^7%IVYPH`Fy1OOiDe_4V>D z3z}7KaanGVu?0Zi`eUwlMv3#rem zmAc^?b@lnz@_FlVO6A1lJyc4qWK59`vI})}zWjZgUS@9>-&9eruU>9z7b#=OlX={f zD=NvbT`cvlPwf8PS5_59izCIwrEX_U0ql7%SLI$qvz~wJUuPsZfEDMK$##@r_g$?v zdi65KRxdK)X38UhSe(;`xV}5rR2o;RsF(k(Plf4ULNTw4^_Ad*QvCMjX9g7pm%i$K*9;VA~+I5B<AbX6w+|E>3DT}-r}#A4e2d*8 zi`_Dqj31C-`i#&4JmI1P*axtne7f&}a}7_pI>VXtHlRX6EzY|Qh-D0=XV)r6U*IBwxrT&~^r}sliTHBe11Xn1iqwjdPBR4zSw@^KO|Pz;?ry z1lWzC0qOqJ%*!;GzBggAHLx24eD*%Fv0a;XwXmS{R=`dS@Oh7gy#gB?U?-jR(g3y; zRvW-y%WszPJ~?) z(9Sk;QV?W!4~!;yP@fONast@P7WN^GP3QzOpDk!CL9D%nb%#A4;ByZwXn&~S#O>Sw zyRERP0qodL!Q0^^SkU%cWMPlNN&?brNoO6jjgEu`<#R499^msH3wsxKUVvRG7qUS< zuY!#Yu-gq=9>B)as7nLbEwG?Af1iat1?wB&^KICSfc@e0u8n=UJ{E`@S$#H)s&RtJ zE`jOew8<`qacDWH-E|hbZ&~bawb*U6*xe1&`O~pvOv<+vR_5fg@mfK%FJb(50=uvu z#I8%X#~dbq`MONLY~1V_|wbnCbOP z@k!U_2dS5nV7eYncACYm)WXKVbUsa=6D)S;TkI+=c5^LkfyL(%*a=>3nEAX3rmv?> z_B+_f0K2Z7eCq9B+6{sY3$U9E)5lxgugR*ijjCXSJv+K?KL}e3)7#r*ccu6=+5Irx zC!6eLm~QhXd(Fb$u&})_T`#83Phq+Z>f?(PQp(qs4W#=zll6t^e41>qh2_C?`!wxN zhUt8o>~xs!&$zYh2g&DTnBHzCn+MbRG+6^o=fz}8VLC7AY+IkzDR#PkBttFKwm$1p z?9!Q1n_y8d=X67UkTSdq)A=;nA5+pZ+21U7f4A8E%VPJ1#qQ7^!TD?l)AecQvy;WH zyTz^#OmByDpXK}VVS2lFSLOS3g|^^xc}jXF8<&!v$CEL!gOC}vd>{UFD5&r zXE1AHVI3^&IG8Sm}Vzsm-tvUdzkzTcF#|{}raoZnF1ax(p`!$YS@o#jX{O zg3@biVI5&XdFf`c>t(SUWU-4_>|z$X5f-~q7P~Voc9Sf2Q!RE?7P}gYT?0(FB|iE= zj#Vpj8qW*(=m+U{*Rwz$r+XRw%RMlCzGSk;VEQ;~vfsk=IZ8Tfq4vOZo9N9xu7m9F z?_1a>Fx>`CyZsis!+QnWwTA`er87*|XL@?&`})I9_cGqcsIxj)Q2^Tv)90qsSM+05@{}3af!F z^Ol)xFYHZOiD0tlIZ)|y8;sG4Cl)&y#G&ij^m#N)=Y`_< zLGszf!g^R(zm)V$p9L^|{$jH8VETMV-&2uO;+Funaup95jK?V2nG%kj!Umi-{*n+(%^oyiu!belKX zVhg*>!mfhpGMGMZfax-rYy(VR)AP{}Qicavpz~?6hgqQ0Guf{!cF$PsUb3*?!`gbe zH%lPOA$;&7%&{um)Otu@Q zm+4qm6}y%Njs3OBy1=#v`1~C#Ar1(pU3U)rwJth1bqq-F!*iAM`&%(I?S@ZoJg%5*9PDK`xdZI_aBx^3z_!73zZCJ- zkw~)lw1vH3VXwe+n=pO81=Gh=lO6Gm#$%O!Mxpc41*Y?9vK}y#7x{4D*o*OxT zrF^4c`gm)y^HS0?*$fN20H*tL)2|{NLYL?VVeiBAb}-q;FkN<&?T6{Io9w9b8-40LNurWoXA3*Q!urB= zdZy1POt(RkO@?`0h<~l8^HKrJkuL6svD;v=`vFXs z-SqkM6rUVM{2*m`G{vXMeht%Y!eqNs(lgm#V7fkw{nXrT`)-Pz$v%ha`aIdNJA{kB zAlAmhI>2Kbek|)DNJvpQ;fWfP4Q{6sW4sk;fCGp6rU!W57YTH*`=_fJYO8@ z{UF=#dYHr#Om>5Xt+BARFuH6fm_GMf?B0gyIy3G5VX^xsOkew$c0HyBm#-%*s9uJ` z#s`#Pg~jLPu$%z9J1uNGEU4_ySkime!k&W#mG3nRd)wmk9gE$+Eq0&5g35QuwBT*j z%EAt{u)|_{mHrO|WWZDQTlUV-&8i4(jTRMu%?8*&TOUQxWeehY?{Y&m!pU3sd7{=#^Cnh ze4-!srw4F)ibQq7hjLy zdoA`dua>BmeC#CMcUUgJzZ!y%A#izz!W5Qm!1gK9n9TQ6Sa%oS=b#AwN?5-d+i#P` zt;DU+!>so)>r1&r;zN`?dCJ6keqKFg;iCHbDfP~T1yd?yLd03Ml~eR=J5#(FtA8$qMMX_b?V^Sd7J9O|kS0u!6v85PDvuCmLBF`pyw20+(+iQZp2I4H ziJr0`3lnEHf)IAzj6L-sO#G_!CyxwaoHo--2s=MfX=EYnykCN6zL{k@#!&w2!_=ML zvhHL$q0;f*2o=IcW-$q|xC6@rV*R+^JVF?SJvcg3n%NZ4eAsdyWyq|A3geJ&h`DcSu%`wXI|*cwmobMP!6iSd7vtsIbE{zagoeXm8Gdn zo0XmEBAMB%Lci#^N?vrFouh{8hMFw%zy+xDj^AduXpr|pWtZ{#^gS{B#;;G`#j8@v=+^rn->% zMVpy@y~8YYdcEwbU;)#=X1T|RsWWqIb}83UdS=aYE>**C0MB}!JFRcFIdCtOvq?SW z(l@-h_vYXlnTk8>y|&h!RJxgMh@GgqBD?BqUiKYp_cmMj3aqJ^SyfXtt9d!7@@8_+ zuJqOJo7}TBmWl7PG;MCDH`{q(Kz4~&xi2!v(wG-|*Z9q~8RrTiS^~wvIx7*G1?q-JH>nofK>}u}6d=;&z z(OZ`Fsc&IqQ4oEiy|8L_)k4`Hv&@3_BU^-X8Sni}UxBk`x@gAE?Qh!bvQRz0hIbe? z=K`#Xi7lI3mz9kVs~j7Z&3dn zk^6}=CaW6{1UtcQB<@VSn}?S&@M|_#-SR;D1Y#Dcv-l%}+B)-qu`lr*JaCkU{dd4+ zAl(~?XOXHB@$69zWZ_6+3G$5eExsp-ck$q|5Aiju>Nn&^ z1`MnrGdM6#IFpj7)!pp691{CJJ|Ud@;8j{XOq7Zh&vM>Py7OLPvXtk$>51qq%Q;a zCQ%Q^61OHF5#sHnFM}Xg;AbfDUs+$a@iC-x9Pw)Mbt3T$(vv*(B$f@`k$mM4KY<@T zc=q+P^Qp!EvEe#$mV>G&hirn(vEQua3`e z5{vJ3q%+X7y@hx=-z5$4CAQMH$mh?|9y9~rcax^X3NCRCZEhQ%WgNn*th1WtD>lMK z?;}Zb7y6Lp*G#6_64&)}^XspReQTBVt)MSL^51>K5nL*GT;L+jB7bUWIJq1w4LkuF8L{bP_EHl%Bk!-jO#$06zJq`Q``TDmpq;-njvt}O@kLcLKR)EBXNoo;vl zv9#?$=tLx4t8CjLNV+-cGNt>=MbaHh7bb@d>5AnrB3+{N4RVN*Zc`3n!;y5s(w#~d zITFQD0wqxi`UW~5Nk1|bO+$1uY6hx6G%e?lHjB6l%|;iXIj9=VMHiwPG!M;3wWtm) zKnqblYCwz7Md)I*7%f5HM3ihhTFk6uHsqyI#IKz~Gk zLVreYpueCu(Oc-R=x=Bb+Kb*s@1S?ld+6_IA9^2sfc}C0i9SRhp?{%|(I@Cr^l$VT z`W$_MzC`nCp+nJO=y22;9f8`Qwx}JFF@f#TQAp;5?||fYS;wGG=vdSl zbwS6WuBaR8j*dris@DVcL^-Gz>W%uKzNjDSj|Lz)ehfkby#N)WA{0Z#=wx&X8jemyr=byOB#NU1N}>`}iptO^RE|cY)6p4d3>u5hMB~s| z=xlTj8jmKRiD(i!7fnXzp>Lq`(G)ZlO+(Ys3{-(;qFJaCRiWAF0yGCzqq*opRDs(6`ZzXdU_v`rj0OLw-H~Kn!T?1d&z}GeKbq)OAuYvyp DjYJIA From 2711c4fa2cca2023067322474ac08cc2aa2daf29 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Sun, 20 Mar 2016 18:51:40 +1100 Subject: [PATCH 13/18] fix relative path to images directory Asciidoc seems to be picky about wanting the trailing slash in the attribute entry as opposed to being part of the image link --- .../children-aggregation-mapping.asciidoc | 2 +- .../children-aggregation-usage.asciidoc | 2 +- .../date-histogram-aggregation-usage.asciidoc | 2 +- .../date-range-aggregation-usage.asciidoc | 2 +- .../filter/filter-aggregation-usage.asciidoc | 2 +- .../filters-aggregation-usage.asciidoc | 2 +- .../geo-distance-aggregation-usage.asciidoc | 2 +- .../geo-hash-grid-aggregation-usage.asciidoc | 2 +- .../global/global-aggregation-usage.asciidoc | 2 +- .../histogram-aggregation-usage.asciidoc | 2 +- .../ip-range-aggregation-usage.asciidoc | 2 +- .../missing-aggregation-usage.asciidoc | 2 +- .../nested/nested-aggregation-usage.asciidoc | 2 +- .../range/range-aggregation-usage.asciidoc | 2 +- .../reverse-nested-aggregation-usage.asciidoc | 2 +- .../sampler-aggregation-usage.asciidoc | 2 +- ...gnificant-terms-aggregation-usage.asciidoc | 2 +- .../terms/terms-aggregation-usage.asciidoc | 2 +- .../average-aggregation-usage.asciidoc | 2 +- .../cardinality-aggregation-usage.asciidoc | 2 +- .../extended-stats-aggregation-usage.asciidoc | 2 +- .../geo-bounds-aggregation-usage.asciidoc | 2 +- .../metric/max/max-aggregation-usage.asciidoc | 2 +- .../metric/min/min-aggregation-usage.asciidoc | 2 +- ...ercentile-ranks-aggregation-usage.asciidoc | 2 +- .../percentiles-aggregation-usage.asciidoc | 2 +- ...scripted-metric-aggregation-usage.asciidoc | 2 +- .../stats/stats-aggregation-usage.asciidoc | 2 +- .../metric/sum/sum-aggregation-usage.asciidoc | 2 +- .../top-hits-aggregation-usage.asciidoc | 2 +- .../value-count-aggregation-usage.asciidoc | 2 +- .../average-bucket-aggregation-usage.asciidoc | 2 +- .../bucket-script-aggregation-usage.asciidoc | 2 +- ...bucket-selector-aggregation-usage.asciidoc | 2 +- .../cumulative-sum-aggregation-usage.asciidoc | 2 +- .../derivative-aggregation-usage.asciidoc | 2 +- .../max-bucket-aggregation-usage.asciidoc | 2 +- .../min-bucket-aggregation-usage.asciidoc | 2 +- ...ng-average-ewma-aggregation-usage.asciidoc | 2 +- ...age-holt-linear-aggregation-usage.asciidoc | 2 +- ...ge-holt-winters-aggregation-usage.asciidoc | 2 +- ...-average-linear-aggregation-usage.asciidoc | 2 +- ...-average-simple-aggregation-usage.asciidoc | 2 +- ...al-differencing-aggregation-usage.asciidoc | 2 +- .../sum-bucket-aggregation-usage.asciidoc | 2 +- .../writing-aggregations.asciidoc | 2 +- .../analyzers/analyzer-usage.asciidoc | 2 +- .../char-filters/char-filter-usage.asciidoc | 2 +- .../token-filters/token-filter-usage.asciidoc | 2 +- .../tokenizers/tokenizer-usage.asciidoc | 2 +- .../connection-pooling.asciidoc | 2 +- .../date-time-providers.asciidoc | 4 +-- .../keeping-track-of-nodes.asciidoc | 2 +- .../request-pipelines.asciidoc | 2 +- .../building-blocks/transports.asciidoc | 2 +- .../exceptions/unexpected-exceptions.asciidoc | 2 +- .../unrecoverable-exceptions.asciidoc | 2 +- .../failover/falling-over.asciidoc | 2 +- .../max-retries/respects-max-retry.asciidoc | 2 +- .../pinging/first-usage.asciidoc | 2 +- .../pinging/revival.asciidoc | 2 +- .../disable-sniff-ping-per-request.asciidoc | 2 +- .../request-timeouts-overrides.asciidoc | 2 +- .../respects-allowed-status-code.asciidoc | 2 +- .../respects-force-node.asciidoc | 2 +- .../respects-max-retry-overrides.asciidoc | 2 +- .../round-robin/round-robin.asciidoc | 2 +- .../round-robin/skip-dead-nodes.asciidoc | 2 +- .../round-robin/volatile-updates.asciidoc | 2 +- .../sniffing/on-connection-failure.asciidoc | 2 +- .../sniffing/on-stale-cluster-state.asciidoc | 2 +- .../sniffing/on-startup.asciidoc | 2 +- .../sniffing/role-detection.asciidoc | 2 +- .../covariant-search-results.asciidoc | 2 +- .../inference/document-paths.asciidoc | 2 +- .../inference/field-inference.asciidoc | 2 +- .../inference/ids-inference.asciidoc | 2 +- .../inference/indices-paths.asciidoc | 2 +- .../inference/property-inference.asciidoc | 2 +- .../high-level/mapping/auto-map.asciidoc | 2 +- .../low-level/connecting.asciidoc | 2 +- .../low-level/lifetimes.asciidoc | 2 +- .../low-level/post-data.asciidoc | 2 +- .../code-standards/descriptors.asciidoc | 2 +- .../code-standards/elastic-client.asciidoc | 2 +- .../naming-conventions.asciidoc | 2 +- docs/asciidoc/code-standards/queries.asciidoc | 2 +- .../serialization/properties.asciidoc | 2 +- .../date-math/date-math-expressions.asciidoc | 2 +- .../distance-unit/distance-units.asciidoc | 2 +- .../time-unit/time-units.asciidoc | 2 +- .../query-dsl/bool-dsl/bool-dsl.asciidoc | 4 +-- .../operators/and-operator-usage.asciidoc | 2 +- .../operators/not-operator-usage.asciidoc | 2 +- .../operators/or-operator-usage.asciidoc | 2 +- .../unary-add-operator-usage.asciidoc | 2 +- .../compound/and/and-query-usage.asciidoc | 2 +- .../bool-dsl-complex-query-usage.asciidoc | 2 +- .../compound/bool/bool-query-usage.asciidoc | 2 +- .../boosting/boosting-query-usage.asciidoc | 2 +- .../constant-score-query-usage.asciidoc | 2 +- .../dismax/dismax-query-usage.asciidoc | 2 +- .../filtered/filtered-query-usage.asciidoc | 2 +- .../function-score-query-usage.asciidoc | 2 +- .../indices-no-match-query-usage.asciidoc | 2 +- .../indices/indices-query-usage.asciidoc | 2 +- .../compound/limit/limit-query-usage.asciidoc | 2 +- .../compound/not/not-query-usage.asciidoc | 2 +- .../compound/or/or-query-usage.asciidoc | 2 +- .../common-terms/common-terms-usage.asciidoc | 2 +- .../match/match-phrase-prefix-usage.asciidoc | 2 +- .../match/match-phrase-usage.asciidoc | 2 +- .../full-text/match/match-usage.asciidoc | 2 +- .../multi-match/multi-match-usage.asciidoc | 2 +- .../query-string/query-string-usage.asciidoc | 2 +- .../simple-query-string-usage.asciidoc | 2 +- .../geo-bounding-box-query-usage.asciidoc | 2 +- .../geo-distance-range-query-usage.asciidoc | 2 +- .../geo-distance-query-usage.asciidoc | 2 +- .../geo-hash-cell-query-usage.asciidoc | 2 +- .../polygon/geo-polygon-query-usage.asciidoc | 2 +- .../circle/geo-shape-circle-usage.asciidoc | 2 +- .../envelope/geo-envelope-usage.asciidoc | 2 +- .../geo-indexed-shape-usage.asciidoc | 2 +- .../geo-line-string-usage.asciidoc | 2 +- .../geo-multi-line-string-usage.asciidoc | 2 +- .../geo-multi-point-usage.asciidoc | 2 +- .../geo/shape/point/geo-point-usage.asciidoc | 2 +- .../shape/polygon/geo-polygon-usage.asciidoc | 2 +- .../has-child/has-child-query-usage.asciidoc | 2 +- .../has-parent-query-usage.asciidoc | 2 +- .../nested/nested-query-usage.asciidoc | 2 +- .../raw/raw-combine-usage.asciidoc | 2 +- .../raw/raw-query-usage.asciidoc | 2 +- .../span-containing-query-usage.asciidoc | 2 +- .../first/span-first-query-usage.asciidoc | 2 +- .../span-multi-term-query-usage.asciidoc | 2 +- .../span/near/span-near-query-usage.asciidoc | 2 +- .../span/not/span-not-query-usage.asciidoc | 2 +- .../span/or/span-or-query-usage.asciidoc | 2 +- .../span/term/span-term-query-usage.asciidoc | 2 +- .../within/span-within-query-usage.asciidoc | 2 +- .../more-like-this-query-usage.asciidoc | 2 +- .../script/script-query-usage.asciidoc | 2 +- .../template/template-query-usage.asciidoc | 2 +- .../exists/exists-query-usage.asciidoc | 2 +- .../fuzzy/fuzzy-date-query-usage.asciidoc | 2 +- .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 2 +- .../fuzzy/fuzzy-query-usage.asciidoc | 2 +- .../term-level/ids/ids-query-usage.asciidoc | 2 +- .../missing/missing-query-usage.asciidoc | 2 +- .../prefix/prefix-query-usage.asciidoc | 2 +- .../range/date-range-query-usage.asciidoc | 2 +- .../range/numeric-range-query-usage.asciidoc | 2 +- .../range/term-range-query-usage.asciidoc | 2 +- .../regexp/regexp-query-usage.asciidoc | 2 +- .../term-level/term/term-query-usage.asciidoc | 2 +- .../terms/terms-lookup-query-usage.asciidoc | 2 +- .../terms/terms-query-usage.asciidoc | 2 +- .../term-level/type/type-query-usage.asciidoc | 2 +- .../wildcard/wildcard-query-usage.asciidoc | 2 +- .../search/request/explain-usage.asciidoc | 2 +- .../request/fielddata-fields-usage.asciidoc | 2 +- .../search/request/fields-usage.asciidoc | 2 +- .../request/from-and-size-usage.asciidoc | 2 +- .../request/highlighting-usage.asciidoc | 2 +- .../search/request/index-boost-usage.asciidoc | 2 +- .../search/request/inner-hits-usage.asciidoc | 2 +- .../search/request/min-score-usage.asciidoc | 2 +- .../search/request/post-filter-usage.asciidoc | 2 +- .../search/request/query-usage.asciidoc | 2 +- .../request/script-fields-usage.asciidoc | 2 +- .../search/request/sort-usage.asciidoc | 2 +- .../request/source-filtering-usage.asciidoc | 2 +- .../search/request/suggest-usage.asciidoc | 2 +- .../search/suggesters/suggest-api.asciidoc | 2 +- .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 9 ++++--- .../Files/CSharpDocumentationFile.cs | 26 +------------------ .../Documentation/Files/DocumentationFile.cs | 4 +-- src/CodeGeneration/Nest.Litterateur/LitUp.cs | 4 +-- .../BuildingBlocks/DateTimeProviders.Doc.cs | 2 +- src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs | 2 +- 182 files changed, 189 insertions(+), 214 deletions(-) diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index 71a0641511b..70e70691812 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[child-aggregation-mapping]] == Child Aggregation Mapping diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index bb284779908..2ed2a24e8ab 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[children-aggregation]] == Children Aggregation diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index ec328b430a1..30d07a142ad 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[date-histogram-aggregation]] == Date Histogram Aggregation diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index ad0f1119412..2c21bd989a1 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[date-range-aggregation]] == Date Range Aggregation diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index cc6503a9a07..88f94d3658e 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[filter-aggregation]] == Filter Aggregation diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index 06e9ddb6971..27f3ce39ff0 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[filters-aggregation]] == Filters Aggregation diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index 29d8efdf8e6..9edb9906470 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-distance-aggregation-usage]] == Geo Distance Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index 0e817451db7..b651c0ef828 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-hash-grid-aggregation-usage]] == Geo Hash Grid Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index d953b5db31e..f447353d008 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[global-aggregation-usage]] == Global Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index ead573835cd..5f4a00bfb05 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[histogram-aggregation-usage]] == Histogram Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index 6f905c04ec0..fecd01af6ed 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[ip-range-aggregation-usage]] == Ip Range Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index f491207773a..48d2e64bb67 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[missing-aggregation-usage]] == Missing Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index 8fe1697c02e..6279ce6fe40 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[nested-aggregation-usage]] == Nested Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index 9bb0e9fd873..e550a93c060 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[range-aggregation-usage]] == Range Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index d74428c9599..69ec97fe5f3 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[reverse-nested-aggregation-usage]] == Reverse Nested Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index d8adff2d033..33efc3ef196 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sampler-aggregation-usage]] == Sampler Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 8f1b68f86b5..3153fb26e3e 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[significant-terms-aggregation-usage]] == Significant Terms Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index 2c9f91b38cd..467a8d58302 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[terms-aggregation-usage]] == Terms Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index 5f682b88559..2af30584175 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[average-aggregation-usage]] == Average Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index a5d667cd13a..d9ec2a6417b 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[cardinality-aggregation-usage]] == Cardinality Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 93b66aece4f..2829ad893f4 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[extended-stats-aggregation-usage]] == Extended Stats Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index a156cb36937..ef236773293 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-bounds-aggregation-usage]] == Geo Bounds Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index 06fcfc5842e..f772d37d3de 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[max-aggregation-usage]] == Max Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index 76eb78e1ebb..43e5551264d 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[min-aggregation-usage]] == Min Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index 2740ff6fb1c..1862135e920 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[percentile-ranks-aggregation-usage]] == Percentile Ranks Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index 8f3a08348e4..ba48e51ef50 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[percentiles-aggregation-usage]] == Percentiles Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index ce36db3e8fc..b07c3a58e0e 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[scripted-metric-aggregation-usage]] == Scripted Metric Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index ef2904020f8..faed1169468 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[stats-aggregation-usage]] == Stats Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 968e2fac7d9..9c98b685ec0 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sum-aggregation-usage]] == Sum Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index a7f72d4bf52..956da9197ea 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[top-hits-aggregation-usage]] == Top Hits Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index f33d2244339..e0e2bc8edab 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[value-count-aggregation-usage]] == Value Count Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index 4612eb1787d..b51d1fd547d 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[average-bucket-aggregation-usage]] == Average Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index 1dfb654e956..6a1b6aebe68 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[bucket-script-aggregation-usage]] == Bucket Script Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 4e176279a11..12fee9af4d7 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[bucket-selector-aggregation-usage]] == Bucket Selector Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index 5c63328d90f..055fc570e7b 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[cumulative-sum-aggregation-usage]] == Cumulative Sum Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index 99678677cd8..39b19280222 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[derivative-aggregation-usage]] == Derivative Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index 8dde063be22..6f7df0a88aa 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[max-bucket-aggregation-usage]] == Max Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index 21cfd395fe9..dbaefa85fa4 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[min-bucket-aggregation-usage]] == Min Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index f0b8d34c50e..3739c16d106 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[moving-average-ewma-aggregation-usage]] == Moving Average Ewma Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index ac263b7bda9..310eaa02630 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[moving-average-holt-linear-aggregation-usage]] == Moving Average Holt Linear Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index 1ace862ad63..65483b9a63d 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[moving-average-holt-winters-aggregation-usage]] == Moving Average Holt Winters Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index 81ac24db151..a400d7c8673 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[moving-average-linear-aggregation-usage]] == Moving Average Linear Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index 95415163e02..c6e2123610b 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[moving-average-simple-aggregation-usage]] == Moving Average Simple Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index c159a8e2435..9931197bf34 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[serial-differencing-aggregation-usage]] == Serial Differencing Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index cf3b70f0461..d08593f0a7a 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sum-bucket-aggregation-usage]] == Sum Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index eade42c8ecc..15c5a1eb2e0 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images +:imagesdir: ../images/ [[writing-aggregations]] == Writing Aggregations diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc index 35935e3ae46..dd56131007b 100644 --- a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[analyzer-usage]] == Analyzer Usage diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc index a31cae8bc77..6716d582b88 100644 --- a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[char-filter-usage]] == Char Filter Usage diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc index 9285e22a10c..742485c7145 100644 --- a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[token-filter-usage]] == Token Filter Usage diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc index 989b51f9d42..d7fede38f0e 100644 --- a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[tokenizer-usage]] == Tokenizer Usage diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index e3fd25e8347..31d4f37c163 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[connection-pooling]] == Connection Pooling diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index ce6e66997b9..60be8825eb8 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[date-time-providers]] == Date time providers @@ -48,7 +48,7 @@ Plotting these defaults looks as followed: [[timeout]] .Default formula, x-axis time in minutes, y-axis number of attempts to revive -image::{imagesdir}/timeoutplot.png[dead timeout] +image::{imagesdir}timeoutplot.png[dead timeout] The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 73fd67953c7..cdbdd3a52f5 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[keeping-track-of-nodes]] == Keeping track of nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 9d28ee21c1d..cc9b801f8ca 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[request-pipeline]] == Request Pipeline diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index 545c4b01e9c..218a1348258 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[transports]] == Transports diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index df1d640d52d..e3aa170efea 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[unexpected-exceptions]] == Unexpected exceptions diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 81bef90f201..9fd9afaf691 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[unrecoverable-exceptions]] == Unrecoverable exceptions diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 166f6fc4f66..561641d169c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[fail-over]] == Fail over diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index 5cd23461c0b..7a0f8d2d9b1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[max-retries]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index 9d3b8440ea3..81c7ba17c33 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[pinging---first-usage]] == Pinging - First Usage diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 016bdb0b1d1..6e2ebf8cad7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[pinging---revival]] == Pinging - Revival diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 4999fb9a9fb..8798c5e75d2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[disabling-sniffing-and-pinging-on-a-request-basis]] == Disabling sniffing and pinging on a request basis diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 6bfb4465926..c5c5027f09e 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[request-timeouts]] == Request Timeouts diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 2659cd5c66b..c39f1d86f26 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[allowed-status-codes]] == Allowed status codes diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 0281d781a49..7782fd6d3fe 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[forcing-nodes]] == Forcing nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index bd77566dbe7..bcc4d11fc95 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[maximum-retries]] == Maximum Retries diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index c6d40229360..7be7bfbafc2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[round-robin]] == Round Robin diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 8f487c62761..5c57399a370 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[round-robin---skipping-dead-nodes]] == Round Robin - Skipping Dead Nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index 82798a9ba28..3572aae23db 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[volatile-updates]] == Volatile Updates diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index 144f2a93b8e..166e8cffad1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sniffing-on-connection-failure]] == Sniffing on connection failure diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index b17dff4f9b6..34cdbf24300 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sniffing-periodically]] == Sniffing periodically diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index 69798367b95..b8afe226e06 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sniffing-on-startup]] == Sniffing on startup diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index 4546a188faa..94bb0bfd3ba 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -4,7 +4,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[sniffing-role-detection]] == Sniffing role detection diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index cc484ba3ac2..62b1d148400 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[covariant-search-results]] == Covariant Search Results diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index 65859fb3d09..78e725fe4d4 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[document-paths]] == Document Paths diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index a6d79b098cd..ea1edbed492 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[strongly-typed-field-access]] == Strongly typed Field Access diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index 48a2fe0e1c8..89fe592551d 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[id-inference]] == Id Inference diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index 5f3697fe05e..c416342b292 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[indices-paths]] == Indices paths diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index b5de8285d7a..4678d237f47 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[property-names]] == Property Names diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index 7a18e25b20d..ad993b643f8 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[auto-map]] == Auto mapping properties diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 769ad663baa..2359f9e57d7 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[connecting]] == Connecting diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 72b2c7628e1..62a8c64b777 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[lifetimes]] == Lifetimes diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index c2b9f198987..aea574b4d1e 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[post-data]] == Post data diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index ca16da3c95d..5b65a1d8c65 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images +:imagesdir: ../images/ [[descriptors]] == Descriptors diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index 264e1c2aa7f..aa434df2fef 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images +:imagesdir: ../images/ [[elastic-client]] == Elastic Client diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 2bf7257b534..928aae50d02 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images +:imagesdir: ../images/ [[naming-conventions]] == Naming Conventions diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index 7f85834d595..91136723dd9 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../images +:imagesdir: ../images/ [[queries]] == Queries diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index 8f8c908902e..699310c30e2 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[properties]] == Properties diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index 5359dd44348..8903602eda1 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[date-math-expressions]] == Date Math Expressions diff --git a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc index 818a5eda9e4..83c1a043cad 100644 --- a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc +++ b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[distance-units]] == Distance Units diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index 38fd60e1977..ffe465ab7cc 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[time-units]] == Time units diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index 47cea117308..4cee5be53f4 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[bool-queries]] == Bool Queries @@ -28,7 +28,7 @@ Now, imagine multiple nested bools; you'll realise that this quickly becomes an [[indent]] .hadouken indenting example -image::{imagesdir}/hadouken-indentation.jpg[dead indent] +image::{imagesdir}hadouken-indentation.jpg[dead indent] === Operator Overloading diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc index f136ee3242d..d0741bb2dc2 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[and-operator-usage]] == And Operator Usage diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc index 133d6f59bcd..b4a163a38e4 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[not-operator-usage]] == Not Operator Usage diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc index 61b7a569850..80f474ad975 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[or-operator-usage]] == Or Operator Usage diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc index 7ce758c31bb..1363e9c70ed 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[unary-add-operator-usage]] == Unary Add Operator Usage diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index 1668a42e3fc..adc56e8cd2e 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[and-query-usage]] == And Query Usage diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc index 4337f66928f..ebd62d17f5e 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[bool-dsl-complex-query-usage]] == Bool Dsl Complex Query Usage diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc index 7d6c00be7dd..fe7c1a4bfd5 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[bool-query-usage]] == Bool Query Usage diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc index 2dce428df0f..8f20d2b14db 100644 --- a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[boosting-query-usage]] == Boosting Query Usage diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc index cbacc576cc4..50768ae2ced 100644 --- a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[constant-score-query-usage]] == Constant Score Query Usage diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc index d81f9d925a2..957510ac438 100644 --- a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[dismax-query-usage]] == Dismax Query Usage diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc index 669de744e80..f0a67232d96 100644 --- a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[filtered-query-usage]] == Filtered Query Usage diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc index e66783d641a..01dfbfc45e7 100644 --- a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[function-score-query-usage]] == Function Score Query Usage diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc index 99785e232c3..0bf71824bda 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[indices-no-match-query-usage]] == Indices No Match Query Usage diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc index eac9c0facde..9c88e4351af 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[indices-query-usage]] == Indices Query Usage diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc index 53ccae233be..2ba54bd24c0 100644 --- a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[limit-query-usage]] == Limit Query Usage diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc index c7b11df6810..30a63f28247 100644 --- a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[not-query-usage]] == Not Query Usage diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc index c03456414ab..97cb2f0f14e 100644 --- a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[or-query-usage]] == Or Query Usage diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc index dbe47dd5d8e..fdb556cfc8c 100644 --- a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[common-terms-usage]] == Common Terms Usage diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc index 5d4f532df1e..9fcef97e292 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[match-phrase-prefix-usage]] == Match Phrase Prefix Usage diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc index 266a5cc97ea..9763dc9f736 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[match-phrase-usage]] == Match Phrase Usage diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc index c592c6231d0..86ea6d8013d 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[match-usage]] == Match Usage diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index 4fcf3b0e86e..16aee90125f 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[multi-match-usage]] == Multi Match Usage diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc index 7bafe33fc63..732cb3a707e 100644 --- a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[query-string-usage]] == Query String Usage diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc index 6a7558ba504..dd12595eef9 100644 --- a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[simple-query-string-usage]] == Simple Query String Usage diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc index 01d5587519c..895f3c6d797 100644 --- a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-bounding-box-query-usage]] == Geo Bounding Box Query Usage diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc index 09b052a0f20..5fe0431730c 100644 --- a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-distance-range-query-usage]] == Geo Distance Range Query Usage diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc index 7788884d30f..7974b3c5a30 100644 --- a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-distance-query-usage]] == Geo Distance Query Usage diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc index 8f8d6807e2e..d671631c800 100644 --- a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-hash-cell-query-usage]] == Geo Hash Cell Query Usage diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc index 8e8498fdc6f..d2910881c62 100644 --- a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[geo-polygon-query-usage]] == Geo Polygon Query Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc index eeffd525250..9cb5f00e15c 100644 --- a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-shape-circle-usage]] == Geo Shape Circle Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc index 816c32f8773..ca574bb9ce4 100644 --- a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-envelope-usage]] == Geo Envelope Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc index 9f1dce81b18..2b26bf706aa 100644 --- a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-indexed-shape-usage]] == Geo Indexed Shape Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc index fe4963633ef..0403fbb3ca6 100644 --- a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-line-string-usage]] == Geo Line String Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc index a03ecf55b7e..e1ac11a6673 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-multi-line-string-usage]] == Geo Multi Line String Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc index f3354832e5c..e43fcebde8a 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-multi-point-usage]] == Geo Multi Point Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc index 9aa1c7eaae4..7968b28cc65 100644 --- a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-point-usage]] == Geo Point Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc index 252ee65cdd2..72d3f9da21e 100644 --- a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../../images +:imagesdir: ../../../../images/ [[geo-polygon-usage]] == Geo Polygon Usage diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc index 447ae857dd5..e9f6713e8b7 100644 --- a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[has-child-query-usage]] == Has Child Query Usage diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc index 871de853fb3..efd64321540 100644 --- a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[has-parent-query-usage]] == Has Parent Query Usage diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc index d51592548e2..5b2ca56ef6d 100644 --- a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[nested-query-usage]] == Nested Query Usage diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc index ec76753e7c8..69b596a1def 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[raw-combine-usage]] == Raw Combine Usage diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc index baa817e6656..0dcb9694cae 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[raw-query-usage]] == Raw Query Usage diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc index 65913dee504..b5ce94293a0 100644 --- a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-containing-query-usage]] == Span Containing Query Usage diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc index 72d0c668170..23f987c8c6d 100644 --- a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-first-query-usage]] == Span First Query Usage diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc index 7eb10ed85fd..7a596d350c8 100644 --- a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-multi-term-query-usage]] == Span Multi Term Query Usage diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc index 075ded4b988..a05440813f0 100644 --- a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-near-query-usage]] == Span Near Query Usage diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc index 83c36eec47c..c9b81fbc772 100644 --- a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-not-query-usage]] == Span Not Query Usage diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc index c8e2d30bdec..4090145c317 100644 --- a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-or-query-usage]] == Span Or Query Usage diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc index 0200123444f..d8ec50a627b 100644 --- a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-term-query-usage]] == Span Term Query Usage diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc index cbfea519677..d25aa2c8574 100644 --- a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[span-within-query-usage]] == Span Within Query Usage diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc index 99db1c33c50..54c421f4681 100644 --- a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[more-like-this-query-usage]] == More Like This Query Usage diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc index faa6fa0244b..00b86eadd36 100644 --- a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[script-query-usage]] == Script Query Usage diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc index 62c52762f3e..969e2088fe7 100644 --- a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[template-query-usage]] == Template Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc index 00e43fef34c..cde6ed1672c 100644 --- a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[exists-query-usage]] == Exists Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc index 31b1b0a2c4d..c225db88b59 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[fuzzy-date-query-usage]] == Fuzzy Date Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc index bf5258b4ff0..569bf80365a 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[fuzzy-numeric-query-usage]] == Fuzzy Numeric Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc index ea6d5656dc0..886533cf892 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[fuzzy-query-usage]] == Fuzzy Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc index 7de48d9906f..aa8cde22133 100644 --- a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[ids-query-usage]] == Ids Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc index aa2ee79493f..8c5ad8edbaa 100644 --- a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[missing-query-usage]] == Missing Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc index ea0ed815b9c..6c5d867cd0a 100644 --- a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[prefix-query-usage]] == Prefix Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc index d473cfbbd0f..8b5b377e7e9 100644 --- a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[date-range-query-usage]] == Date Range Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc index e635e8b51a7..23757ad419c 100644 --- a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[numeric-range-query-usage]] == Numeric Range Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc index a983edd09da..b695949a8b1 100644 --- a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[term-range-query-usage]] == Term Range Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc index 3f67103763a..27dabc3f5df 100644 --- a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[regexp-query-usage]] == Regexp Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc index ba19b2c31fd..08a80933ec9 100644 --- a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[term-query-usage]] == Term Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc index d5284bbb43a..4593044ad15 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[terms-lookup-query-usage]] == Terms Lookup Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc index 4db3031ad70..8aa8b0c441e 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[terms-query-usage]] == Terms Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc index bc6d60b8ddd..cce3aa33b5a 100644 --- a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[type-query-usage]] == Type Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc index 55e02f8fad4..b4ded36e094 100644 --- a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../../images +:imagesdir: ../../../images/ [[wildcard-query-usage]] == Wildcard Query Usage diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc index 93165b70a96..fdbe102da03 100644 --- a/docs/asciidoc/search/request/explain-usage.asciidoc +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[explain-usage]] == Explain Usage diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index 14568bb4a10..b0bf3b57ce0 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[fielddata-fields-usage]] == Fielddata Fields Usage diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index db46b6e9093..41a2c2f7d70 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[fields-usage]] == Fields Usage diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index fe4a86b80a3..2016ec3db1a 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[from-and-size-usage]] == From And Size Usage diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index 55b36c6bec2..8ff7e4c54ed 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[highlighting-usage]] == Highlighting Usage diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index 05e71818874..44c22ec9af4 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[index-boost-usage]] == Index Boost Usage diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc index 09b816231ba..bec91811afa 100644 --- a/docs/asciidoc/search/request/inner-hits-usage.asciidoc +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[inner-hits-usage]] == Inner Hits Usage diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index 0dae179eadf..cab10f64c30 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[min-score-usage]] == Min Score Usage diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index b652d34172a..84c2025102f 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[post-filter-usage]] == Post Filter Usage diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index c8621871eb3..3e3c456c6b8 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[query-usage]] == Query Usage diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index dd087a27bb8..eec71bbc0d4 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[script-fields-usage]] == Script Fields Usage diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 806b1a11633..60c5e89eda6 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[sort-usage]] == Sort Usage diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index 981f31df0f4..7a49f8d119f 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[source-filtering-usage]] == Source Filtering Usage diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index 4bf549170ca..7e994f8d40b 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[suggest-usage]] == Suggest Usage diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index 46a7da9556c..f4b6d42d13a 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -2,7 +2,7 @@ :github: https://github.com/elastic/elasticsearch-net -:imagesdir: ../../images +:imagesdir: ../../images/ [[suggest-api]] == Suggest API diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs index 78174292a71..6c6fdbbb3c1 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs @@ -10,7 +10,8 @@ namespace Nest.Litterateur.AsciiDoc { ///

- /// Visits the "raw" asciidoc generated using Roslyn and adds attribute entries, section titles + /// Visits the "raw" asciidoc generated using Roslyn and adds attribute entries, + /// section titles, rearranges sections, etc. /// public class AddAttributeEntriesVisitor : NoopVisitor { @@ -59,7 +60,7 @@ public override void Visit(Document document) _newDocument.Attributes.Add(new AttributeEntry("github", "https://github.com/elastic/elasticsearch-net")); } - if (!document.Attributes.Any(a => a.Name == "imagesdir")) + if (!document.Attributes.Any(a => a.Name == "imagesdir")) { var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; var currentDirectory = _destination.Directory.FullName; @@ -67,10 +68,10 @@ public override void Visit(Document document) var count = difference.Count(c => c == '\\'); var imagesDir = string.Join(string.Empty, Enumerable.Repeat("../", count)); - _newDocument.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}")); + _newDocument.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}/")); } - // see if the document has some kind of top level title. + // see if the document has some kind of top level title and add one with an anchor if not. if (document.Title == null && document.Elements.Count > 0 && !document.Elements.OfType().Any(s => s.Level == 2)) diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index 628d778f29d..729dfc42531 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -17,11 +17,8 @@ namespace Nest.Litterateur.Documentation.Files { public class CSharpDocumentationFile : DocumentationFile { - private readonly Dictionary _sections; - - internal CSharpDocumentationFile(FileInfo fileLocation, Dictionary sections) : base(fileLocation) + internal CSharpDocumentationFile(FileInfo fileLocation) : base(fileLocation) { - _sections = sections; } private string RenderBlocksToDocumentation(IEnumerable blocks) @@ -205,20 +202,6 @@ private void CleanDocumentAndWriteToFile(string body, FileInfo docFile) // tidy up the asciidoc var document = Document.Parse(body); - // extract section number from doc - var sectionAttributeEntry = document.Attributes.SingleOrDefault(a => a.Name == "section-number"); - decimal sectionValue; - - var sectionPath = GetPathRelativeToOutput(docFile); - if (sectionAttributeEntry != null && decimal.TryParse(sectionAttributeEntry.Value, out sectionValue)) - { - _sections.Add(sectionPath, sectionValue); - } - else - { - _sections.Add(sectionPath, 100); - } - // add attributes and write to destination using (var file = new StreamWriter(docFile.FullName)) { @@ -228,12 +211,5 @@ private void CleanDocumentAndWriteToFile(string body, FileInfo docFile) } } #endif - - private string GetPathRelativeToOutput(FileInfo docFileName) - { - var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; - var currentDirectory = docFileName.FullName; - return currentDirectory.Replace(targetDirectory, string.Empty).Replace("\\", "/").TrimStart('/'); - } } } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs index 6afad0534b4..381cbf949db 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/DocumentationFile.cs @@ -20,13 +20,13 @@ protected DocumentationFile(FileInfo fileLocation) public abstract void SaveToDocumentationFolder(); - public static DocumentationFile Load(FileInfo fileLocation, Dictionary sections) + public static DocumentationFile Load(FileInfo fileLocation) { var extension = fileLocation?.Extension; switch (extension) { case ".cs": - return new CSharpDocumentationFile(fileLocation, sections); + return new CSharpDocumentationFile(fileLocation); case ".gif": case ".jpg": case ".jpeg": diff --git a/src/CodeGeneration/Nest.Litterateur/LitUp.cs b/src/CodeGeneration/Nest.Litterateur/LitUp.cs index e7dea5d9ce6..17d7588dd59 100644 --- a/src/CodeGeneration/Nest.Litterateur/LitUp.cs +++ b/src/CodeGeneration/Nest.Litterateur/LitUp.cs @@ -11,13 +11,11 @@ public static class LitUp { private static readonly string[] SkipFolders = { "Nest.Tests.Literate", "Debug", "Release" }; - private static readonly Dictionary Sections = new Dictionary(); - public static IEnumerable InputFiles(string path) => from f in Directory.GetFiles(Program.InputDirPath, $"{path}", SearchOption.AllDirectories) let dir = new DirectoryInfo(f) where dir?.Parent != null && !SkipFolders.Contains(dir.Parent.Name) - select DocumentationFile.Load(new FileInfo(f), Sections); + select DocumentationFile.Load(new FileInfo(f)); public static IEnumerable> Input { diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs index efe95886e0d..36d001cf2e4 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs @@ -42,7 +42,7 @@ [U] public void DeadTimeoutCalculation() * *[[timeout]] *.Default formula, x-axis time in minutes, y-axis number of attempts to revive - *image::{imagesdir}/timeoutplot.png[dead timeout] + *image::{imagesdir}timeoutplot.png[dead timeout] * * The goal here is that whenever a node is resurrected and is found to still be offline, we send it * _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs index 5384b333457..30e29b5924f 100644 --- a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs +++ b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs @@ -35,7 +35,7 @@ public void VerboseWay() * *[[indent]] *.hadouken indenting example - *image::{imagesdir}/hadouken-indentation.jpg[dead indent] + *image::{imagesdir}hadouken-indentation.jpg[dead indent] * *=== Operator Overloading * From 5e540cd13b2ef414a15039b4fcdc9dd249a7cdc3 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Tue, 22 Mar 2016 12:12:14 +1100 Subject: [PATCH 14/18] Include Query DSL usage Fix indentation when the first character following the first set of tabs is an opening brace. This is a bit of a hack. there may be a nicer way of doing this but it works fine for the moment. Add Aggs vs Aggregations section --- docs/asciidoc/aggregations-usage.asciidoc | 90 +- docs/asciidoc/aggregations.asciidoc | 97 +- .../children-aggregation-mapping.asciidoc | 15 +- .../children-aggregation-usage.asciidoc | 40 +- .../date-histogram-aggregation-usage.asciidoc | 92 +- .../date-range-aggregation-usage.asciidoc | 52 +- .../filter/filter-aggregation-usage.asciidoc | 58 +- .../filters-aggregation-usage.asciidoc | 153 +- .../geo-distance-aggregation-usage.asciidoc | 40 +- .../geo-hash-grid-aggregation-usage.asciidoc | 26 +- .../global/global-aggregation-usage.asciidoc | 28 +- .../histogram-aggregation-usage.asciidoc | 26 +- .../ip-range-aggregation-usage.asciidoc | 32 +- .../missing-aggregation-usage.asciidoc | 14 +- .../nested/nested-aggregation-usage.asciidoc | 32 +- .../range/range-aggregation-usage.asciidoc | 36 +- .../reverse-nested-aggregation-usage.asciidoc | 64 +- .../sampler-aggregation-usage.asciidoc | 36 +- ...gnificant-terms-aggregation-usage.asciidoc | 36 +- .../terms/terms-aggregation-usage.asciidoc | 70 +- .../average-aggregation-usage.asciidoc | 34 +- .../cardinality-aggregation-usage.asciidoc | 16 +- .../extended-stats-aggregation-usage.asciidoc | 8 +- .../geo-bounds-aggregation-usage.asciidoc | 16 +- .../metric/max/max-aggregation-usage.asciidoc | 8 +- .../metric/min/min-aggregation-usage.asciidoc | 8 +- ...ercentile-ranks-aggregation-usage.asciidoc | 42 +- .../percentiles-aggregation-usage.asciidoc | 42 +- ...scripted-metric-aggregation-usage.asciidoc | 26 +- .../stats/stats-aggregation-usage.asciidoc | 8 +- .../metric/sum/sum-aggregation-usage.asciidoc | 8 +- .../top-hits-aggregation-usage.asciidoc | 136 +- .../value-count-aggregation-usage.asciidoc | 8 +- .../average-bucket-aggregation-usage.asciidoc | 48 +- .../bucket-script-aggregation-usage.asciidoc | 102 +- ...bucket-selector-aggregation-usage.asciidoc | 60 +- .../cumulative-sum-aggregation-usage.asciidoc | 42 +- .../derivative-aggregation-usage.asciidoc | 42 +- .../max-bucket-aggregation-usage.asciidoc | 40 +- .../min-bucket-aggregation-usage.asciidoc | 40 +- ...ng-average-ewma-aggregation-usage.asciidoc | 64 +- ...age-holt-linear-aggregation-usage.asciidoc | 68 +- ...ge-holt-winters-aggregation-usage.asciidoc | 88 +- ...-average-linear-aggregation-usage.asciidoc | 58 +- ...-average-simple-aggregation-usage.asciidoc | 62 +- ...al-differencing-aggregation-usage.asciidoc | 50 +- .../sum-bucket-aggregation-usage.asciidoc | 40 +- .../writing-aggregations.asciidoc | 111 +- docs/asciidoc/client-concepts.asciidoc | 8 - .../date-time-providers.asciidoc | 127 +- .../keeping-track-of-nodes.asciidoc | 2 +- .../request-pipelines.asciidoc | 8 +- .../exceptions/unexpected-exceptions.asciidoc | 108 +- .../unrecoverable-exceptions.asciidoc | 42 +- .../failover/falling-over.asciidoc | 72 +- .../max-retries/respects-max-retry.asciidoc | 178 +- .../pinging/first-usage.asciidoc | 92 +- .../pinging/revival.asciidoc | 60 +- .../disable-sniff-ping-per-request.asciidoc | 80 +- .../request-timeouts-overrides.asciidoc | 70 +- .../respects-allowed-status-code.asciidoc | 20 +- .../respects-force-node.asciidoc | 16 +- .../respects-max-retry-overrides.asciidoc | 60 +- .../round-robin/round-robin.asciidoc | 10 +- .../round-robin/skip-dead-nodes.asciidoc | 132 +- .../round-robin/volatile-updates.asciidoc | 4 +- .../sniffing/on-connection-failure.asciidoc | 154 +- .../sniffing/on-stale-cluster-state.asciidoc | 88 +- .../sniffing/on-startup.asciidoc | 180 +- .../sniffing/role-detection.asciidoc | 124 +- .../covariant-search-results.asciidoc | 525 +++-- .../inference/document-paths.asciidoc | 2 +- .../inference/features-inference.asciidoc | 35 + .../inference/field-inference.asciidoc | 186 +- .../inference/ids-inference.asciidoc | 40 +- .../inference/indices-paths.asciidoc | 39 +- .../inference/property-inference.asciidoc | 12 +- .../high-level/mapping/auto-map.asciidoc | 1963 +++++++++-------- .../low-level/connecting.asciidoc | 48 +- .../low-level/lifetimes.asciidoc | 46 +- .../low-level/post-data.asciidoc | 27 +- .../code-standards/descriptors.asciidoc | 64 +- .../code-standards/elastic-client.asciidoc | 86 +- .../naming-conventions.asciidoc | 124 +- docs/asciidoc/code-standards/queries.asciidoc | 26 +- docs/asciidoc/common-options.asciidoc | 6 +- .../date-math/date-math-expressions.asciidoc | 20 +- .../distance-unit/distance-units.asciidoc | 8 +- .../time-unit/time-units.asciidoc | 8 +- docs/asciidoc/connection-pooling.asciidoc | 15 +- docs/asciidoc/high-level.asciidoc | 55 +- docs/asciidoc/index.asciidoc | 5 +- docs/asciidoc/intro.asciidoc | 16 +- docs/asciidoc/low-level.asciidoc | 18 +- docs/asciidoc/query-dsl-usage.asciidoc | 132 +- docs/asciidoc/query-dsl.asciidoc | 138 +- .../query-dsl/bool-dsl/bool-dsl.asciidoc | 501 +++-- .../operators/and-operator-usage.asciidoc | 42 +- .../operators/not-operator-usage.asciidoc | 52 +- .../operators/or-operator-usage.asciidoc | 50 +- .../unary-add-operator-usage.asciidoc | 52 +- .../compound/and/and-query-usage.asciidoc | 45 +- .../bool-dsl-complex-query-usage.asciidoc | 219 +- .../compound/bool/bool-query-usage.asciidoc | 44 +- .../boosting/boosting-query-usage.asciidoc | 42 +- .../constant-score-query-usage.asciidoc | 36 +- .../dismax/dismax-query-usage.asciidoc | 48 +- .../filtered/filtered-query-usage.asciidoc | 39 +- .../function-score-query-usage.asciidoc | 86 +- .../indices-no-match-query-usage.asciidoc | 42 +- .../indices/indices-query-usage.asciidoc | 44 +- .../compound/limit/limit-query-usage.asciidoc | 36 +- .../compound/not/not-query-usage.asciidoc | 45 +- .../compound/or/or-query-usage.asciidoc | 45 +- .../common-terms/common-terms-usage.asciidoc | 57 +- .../match/match-phrase-prefix-usage.asciidoc | 72 +- .../match/match-phrase-usage.asciidoc | 72 +- .../full-text/match/match-usage.asciidoc | 72 +- .../multi-match/multi-match-usage.asciidoc | 75 +- .../query-string/query-string-usage.asciidoc | 108 +- .../simple-query-string-usage.asciidoc | 63 +- .../geo-bounding-box-query-usage.asciidoc | 62 +- .../geo-distance-range-query-usage.asciidoc | 66 +- .../geo-distance-query-usage.asciidoc | 57 +- .../geo-hash-cell-query-usage.asciidoc | 45 +- .../polygon/geo-polygon-query-usage.asciidoc | 48 +- .../circle/geo-shape-circle-usage.asciidoc | 26 +- .../envelope/geo-envelope-usage.asciidoc | 25 +- .../geo-indexed-shape-usage.asciidoc | 54 +- .../geo-line-string-usage.asciidoc | 25 +- .../geo-multi-line-string-usage.asciidoc | 25 +- .../geo-multi-point-usage.asciidoc | 25 +- .../geo/shape/point/geo-point-usage.asciidoc | 25 +- .../shape/polygon/geo-polygon-usage.asciidoc | 25 +- .../has-child/has-child-query-usage.asciidoc | 50 +- .../has-parent-query-usage.asciidoc | 45 +- .../nested/nested-query-usage.asciidoc | 42 +- .../raw/raw-combine-usage.asciidoc | 23 +- .../raw/raw-query-usage.asciidoc | 22 +- .../span-containing-query-usage.asciidoc | 43 +- .../first/span-first-query-usage.asciidoc | 47 +- .../span-multi-term-query-usage.asciidoc | 38 +- .../span/near/span-near-query-usage.asciidoc | 59 +- .../span/not/span-not-query-usage.asciidoc | 64 +- .../span/or/span-or-query-usage.asciidoc | 50 +- .../span/term/span-term-query-usage.asciidoc | 39 +- .../within/span-within-query-usage.asciidoc | 43 +- .../more-like-this-query-usage.asciidoc | 94 +- .../script/script-query-usage.asciidoc | 45 +- .../template/template-query-usage.asciidoc | 53 +- .../exists/exists-query-usage.asciidoc | 36 +- .../fuzzy/fuzzy-date-query-usage.asciidoc | 54 +- .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 54 +- .../fuzzy/fuzzy-query-usage.asciidoc | 54 +- .../term-level/ids/ids-query-usage.asciidoc | 39 +- .../missing/missing-query-usage.asciidoc | 42 +- .../prefix/prefix-query-usage.asciidoc | 42 +- .../range/date-range-query-usage.asciidoc | 54 +- .../range/numeric-range-query-usage.asciidoc | 48 +- .../range/term-range-query-usage.asciidoc | 48 +- .../regexp/regexp-query-usage.asciidoc | 45 +- .../term-level/term/term-query-usage.asciidoc | 39 +- .../terms/terms-lookup-query-usage.asciidoc | 51 +- .../terms/terms-query-usage.asciidoc | 45 +- .../term-level/type/type-query-usage.asciidoc | 36 +- .../wildcard/wildcard-query-usage.asciidoc | 42 +- .../request/fielddata-fields-usage.asciidoc | 8 +- .../search/request/fields-usage.asciidoc | 6 +- .../request/from-and-size-usage.asciidoc | 8 +- .../request/highlighting-usage.asciidoc | 172 +- .../search/request/index-boost-usage.asciidoc | 14 +- .../search/request/inner-hits-usage.asciidoc | 150 +- .../search/request/min-score-usage.asciidoc | 14 +- .../search/request/post-filter-usage.asciidoc | 2 +- .../search/request/query-usage.asciidoc | 12 +- .../request/script-fields-usage.asciidoc | 46 +- .../search/request/sort-usage.asciidoc | 134 +- .../request/source-filtering-usage.asciidoc | 26 +- .../search/request/suggest-usage.asciidoc | 232 +- .../search/suggesters/suggest-api.asciidoc | 230 +- ...Visitor.cs => GeneratedAsciidocVisitor.cs} | 63 +- .../AsciiDoc/RawAsciidocVisitor.cs | 95 + .../Files/CSharpDocumentationFile.cs | 2 +- .../Files/RawDocumentationFile.cs | 29 +- .../Nest.Litterateur/StringExtensions.cs | 38 +- .../Walkers/DocumentationFileWalker.cs | 6 +- .../ChildrenAggregationMapping.doc.cs | 5 +- .../Children/ChildrenAggregationUsageTests.cs | 21 +- .../DateHistogramAggregationUsageTests.cs | 12 +- .../DateRangeAggregationUsageTests.cs | 4 +- .../Filter/FilterAggregationUsageTests.cs | 4 +- .../Filters/FiltersAggregationUsageTests.cs | 20 +- .../Aggregations/WritingAggregations.doc.cs | 53 +- .../MaxRetries/RespectsMaxRetry.doc.cs | 41 +- ...sInference.cs => FeaturesInference.doc.cs} | 8 +- .../HighLevel/Inference/FieldInference.doc.cs | 55 +- .../HighLevel/Inference/IdsInference.doc.cs | 3 +- .../HighLevel/Inference/IndicesPaths.doc.cs | 19 +- .../Inference/PropertyInference.doc.cs | 10 +- .../HighLevel/Mapping/AutoMap.doc.cs | 70 +- .../ClientConcepts/LowLevel/Connecting.doc.cs | 3 +- .../ClientConcepts/LowLevel/PostData.doc.cs | 12 +- src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs | 107 +- .../Span/Not/SpanNotQueryUsageTests.cs | 16 +- .../Script/ScriptQueryUsageTests.cs | 3 - .../Template/TemplateQueryUsageTests.cs | 2 - src/Tests/aggregations.asciidoc | 3 +- src/Tests/client-concepts.asciidoc | 6 +- src/Tests/high-level.asciidoc | 40 +- src/Tests/index.asciidoc | 2 +- src/Tests/low-level.asciidoc | 10 +- src/Tests/query-dsl-usage.asciidoc | 2 +- src/Tests/query-dsl.asciidoc | 2 +- src/lib/dnx451/AsciiDoc.dll | Bin 70656 -> 74752 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 245248 -> 249344 bytes 215 files changed, 7720 insertions(+), 5672 deletions(-) create mode 100644 docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc rename src/CodeGeneration/Nest.Litterateur/AsciiDoc/{AsciiVisitor.cs => GeneratedAsciidocVisitor.cs} (76%) create mode 100644 src/CodeGeneration/Nest.Litterateur/AsciiDoc/RawAsciidocVisitor.cs rename src/Tests/ClientConcepts/HighLevel/Inference/{FeaturesInference.cs => FeaturesInference.doc.cs} (79%) diff --git a/docs/asciidoc/aggregations-usage.asciidoc b/docs/asciidoc/aggregations-usage.asciidoc index 1b9aafea645..a79afee8902 100644 --- a/docs/asciidoc/aggregations-usage.asciidoc +++ b/docs/asciidoc/aggregations-usage.asciidoc @@ -1,92 +1,92 @@ :includes-from-dirs: aggregations/bucket,aggregations/metric,aggregations/pipeline -include::aggregations/bucket/children/children-aggregation-mapping.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc[] -include::aggregations/bucket/children/children-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc[] -include::aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc[] -include::aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc[] -include::aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc[] -include::aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc[] -include::aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc[] -include::aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc[] -include::aggregations/bucket/global/global-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc[] -include::aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc[] -include::aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc[] -include::aggregations/bucket/missing/missing-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc[] -include::aggregations/bucket/nested/nested-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc[] -include::aggregations/bucket/range/range-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc[] -include::aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc[] -include::aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc[] -include::aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc[] -include::aggregations/bucket/terms/terms-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc[] -include::aggregations/metric/average/average-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc[] -include::aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc[] -include::aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc[] -include::aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc[] -include::aggregations/metric/max/max-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc[] -include::aggregations/metric/min/min-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc[] -include::aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc[] -include::aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc[] -include::aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc[] -include::aggregations/metric/stats/stats-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc[] -include::aggregations/metric/sum/sum-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc[] -include::aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc[] -include::aggregations/metric/value-count/value-count-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc[] -include::aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc[] -include::aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc[] -include::aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc[] -include::aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc[] -include::aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc[] -include::aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc[] -include::aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc[] -include::aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc[] -include::aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc[] -include::aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc[] -include::aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc[] -include::aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc[] -include::aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc[] -include::aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc[] +include::../../docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc[] diff --git a/docs/asciidoc/aggregations.asciidoc b/docs/asciidoc/aggregations.asciidoc index 38c5c57c03a..3fc54ece781 100644 --- a/docs/asciidoc/aggregations.asciidoc +++ b/docs/asciidoc/aggregations.asciidoc @@ -1,13 +1,104 @@ -:output-dir: aggregations +:output-dir: aggregations [[aggregations]] = Aggregations [partintro] -- -Something about aggregations +Aggregations are arguably one of the most powerful features of Elasticsearch and NEST +exposes all of the available Aggregation types + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + -- include::{output-dir}/writing-aggregations.asciidoc[] -include::aggregations-usage.asciidoc[] \ No newline at end of file +include::aggregations-usage.asciidoc[] + diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index 70e70691812..a7baf5059c9 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -5,7 +5,7 @@ :imagesdir: ../../../images/ [[child-aggregation-mapping]] -== Child Aggregation Mapping +== Child Aggregation Mapping To use the child aggregation you have to make sure a `_parent` mapping is in place, here we create the project @@ -15,12 +15,13 @@ To use the child aggregation you have to make sure [source,csharp] ---- var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c - .Mappings(map => map - .Map(tm => tm.AutoMap()) - .Map(tm => tm - .Parent() - ) - ) + .Mappings(map => map + .Map(tm => tm.AutoMap()) + .Map(tm => tm + .Parent() <1> + ) + ) ); ---- +<1> Set the parent of `CommitActivity` to the `Project` type diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index 2ed2a24e8ab..15175f7c864 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -4,13 +4,13 @@ :imagesdir: ../../../images/ -[[children-aggregation]] -== Children Aggregation +[[children-aggregation-usage]] +== Children Aggregation Usage A special single bucket aggregation that enables aggregating from buckets on parent document types to buckets on child documents. -Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] +Be sure to read {ref_current}/search-aggregations-bucket-children-aggregation.html[the elasticsearch documentation on Children Aggregation] === Fluent DSL Example @@ -18,12 +18,12 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation ---- s => s .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => childAggs - .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - ) - ) + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) + ) ) ---- @@ -33,22 +33,12 @@ s => s ---- new SearchRequest { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", "confidenceFactor") && - new MaxAggregation("max_per_child", "confidenceFactor") - } -} - -new SearchRequest -{ - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) - && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) - } + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", "confidenceFactor") && + new MaxAggregation("max_per_child", "confidenceFactor") + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index 30d07a142ad..407b221144c 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -4,16 +4,16 @@ :imagesdir: ../../../images/ -[[date-histogram-aggregation]] -== Date Histogram Aggregation +[[date-histogram-aggregation-usage]] +== Date Histogram Aggregation Usage A multi-bucket aggregation similar to the histogram except it can only be applied on date values. From a functionality perspective, this histogram supports the same features as the normal histogram. The main difference is that the interval can be specified by date/time expressions. -When specifying a format and extended_bounds, in order for Elasticsearch to be able to parse -the serialized DateTimes of extended_bounds correctly, the date_optional_time format is included -as part of the format value. +NOTE: When specifying a `format` **and** `extended_bounds`, in order for Elasticsearch to be able to parse +the serialized ``DateTime`` of `extended_bounds` correctly, the `date_optional_time` format is included +as part of the `format` value. Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. @@ -24,23 +24,23 @@ Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregati s => s .Size(0) .Aggregations(aggs => aggs - .DateHistogram("projects_started_per_month", date => date - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .MinimumDocumentCount(2) - .Format("yyyy-MM-dd'T'HH:mm:ss") - .ExtendedBounds(FixedDate.AddYears(-1), FixedDate.AddYears(1)) - .Order(HistogramOrder.CountAscending) - .Missing(FixedDate) - .Aggregations(childAggs => childAggs - .Nested("project_tags", n => n - .Path(p => p.Tags) - .Aggregations(nestedAggs => nestedAggs - .Terms("tags", avg => avg.Field(p => p.Tags.First().Name)) - ) - ) - ) - ) + .DateHistogram("projects_started_per_month", date => date + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .MinimumDocumentCount(2) + .Format("yyyy-MM-dd'T'HH:mm:ss") + .ExtendedBounds(FixedDate.AddYears(-1), FixedDate.AddYears(1)) + .Order(HistogramOrder.CountAscending) + .Missing(FixedDate) + .Aggregations(childAggs => childAggs + .Nested("project_tags", n => n + .Path(p => p.Tags) + .Aggregations(nestedAggs => nestedAggs + .Terms("tags", avg => avg.Field(p => p.Tags.First().Name)) + ) + ) + ) + ) ) ---- @@ -50,29 +50,29 @@ s => s ---- new SearchRequest { - Size = 0, - Aggregations = new DateHistogramAggregation("projects_started_per_month") - { - Field = Field(p => p.StartedOn), - Interval = DateInterval.Month, - MinimumDocumentCount = 2, - Format = "yyyy-MM-dd'T'HH:mm:ss", - ExtendedBounds = new ExtendedBounds - { - Minimum = FixedDate.AddYears(-1), - Maximum = FixedDate.AddYears(1), - }, - Order = HistogramOrder.CountAscending, - Missing = FixedDate, - Aggregations = new NestedAggregation("project_tags") - { - Path = Field(p => p.Tags), - Aggregations = new TermsAggregation("tags") - { - Field = Field(p => p.Tags.First().Name) - } - } - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = Field(p => p.StartedOn), + Interval = DateInterval.Month, + MinimumDocumentCount = 2, + Format = "yyyy-MM-dd'T'HH:mm:ss", + ExtendedBounds = new ExtendedBounds + { + Minimum = FixedDate.AddYears(-1), + Maximum = FixedDate.AddYears(1), + }, + Order = HistogramOrder.CountAscending, + Missing = FixedDate, + Aggregations = new NestedAggregation("project_tags") + { + Path = Field(p => p.Tags), + Aggregations = new TermsAggregation("tags") + { + Field = Field(p => p.Tags.First().Name) + } + } + } } ---- @@ -119,7 +119,7 @@ new SearchRequest === Handling responses Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily -in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] +in the correct type. <> [source,csharp] ---- diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index 2c21bd989a1..d27e1c5bad4 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -4,8 +4,8 @@ :imagesdir: ../../../images/ -[[date-range-aggregation]] -== Date Range Aggregation +[[date-range-aggregation-usage]] +== Date Range Aggregation Usage A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` and `to` values can be expressed in `DateMath` expressions, and it is also possible to specify a date format by which the from and @@ -21,17 +21,17 @@ Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.h ---- s => s .Aggregations(aggs => aggs - .DateRange("projects_date_ranges", date => date - .Field(p => p.StartedOn) - .Ranges( - r => r.From(DateMath.Anchored(FixedDate).Add("2d")).To(DateMath.Now), - r => r.To(DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour)), - r => r.From(DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m")) - ) - .Aggregations(childAggs => childAggs - .Terms("project_tags", avg => avg.Field(p => p.Tags)) - ) - ) + .DateRange("projects_date_ranges", date => date + .Field(p => p.StartedOn) + .Ranges( + r => r.From(DateMath.Anchored(FixedDate).Add("2d")).To(DateMath.Now), + r => r.To(DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour)), + r => r.From(DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m")) + ) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.Tags)) + ) + ) ) ---- @@ -41,18 +41,18 @@ s => s ---- new SearchRequest { - Aggregations = new DateRangeAggregation("projects_date_ranges") - { - Field = Field(p => p.StartedOn), - Ranges = new List - { - new DateRangeExpression { From = DateMath.Anchored(FixedDate).Add("2d"), To = DateMath.Now}, - new DateRangeExpression { To = DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour) }, - new DateRangeExpression { From = DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m") } - }, - Aggregations = - new TermsAggregation("project_tags") { Field = Field(p => p.Tags) } - } + Aggregations = new DateRangeAggregation("projects_date_ranges") + { + Field = Field(p => p.StartedOn), + Ranges = new List + { + new DateRangeExpression { From = DateMath.Anchored(FixedDate).Add("2d"), To = DateMath.Now}, + new DateRangeExpression { To = DateMath.Now.Add(TimeSpan.FromDays(1)).Subtract("30m").RoundTo(TimeUnit.Hour) }, + new DateRangeExpression { From = DateMath.Anchored("2012-05-05").Add(TimeSpan.FromDays(1)).Subtract("1m") } + }, + Aggregations = + new TermsAggregation("project_tags") { Field = Field(p => p.Tags) } + } } ---- @@ -92,7 +92,7 @@ new SearchRequest === Handling Responses Using the `.Agg` aggregation helper we can fetch our aggregation results easily -in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() +in the correct type. <> [source,csharp] ---- diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index 88f94d3658e..db5d7c97272 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -4,8 +4,8 @@ :imagesdir: ../../../images/ -[[filter-aggregation]] -== Filter Aggregation +[[filter-aggregation-usage]] +== Filter Aggregation Usage Defines a single bucket of all the documents in the current document set context that match a specified filter. Often this will be used to narrow down the current aggregation context to a specific set of documents. @@ -18,12 +18,12 @@ Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html ---- s => s .Aggregations(aggs => aggs - .Filter("bethels_projects", date => date - .Filter(q => q.Term(p => p.LeadDeveloper.FirstName, FirstNameToFind)) - .Aggregations(childAggs => childAggs - .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) - ) - ) + .Filter("bethels_projects", date => date + .Filter(q => q.Term(p => p.LeadDeveloper.FirstName, FirstNameToFind)) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) + ) + ) ) ---- @@ -33,12 +33,12 @@ s => s ---- new SearchRequest { - Aggregations = new FilterAggregation("bethels_projects") - { - Filter = new TermQuery {Field = Field(p => p.LeadDeveloper.FirstName), Value = FirstNameToFind}, - Aggregations = - new TermsAggregation("project_tags") {Field = Field(p => p.CuratedTags.First().Name)} - } + Aggregations = new FilterAggregation("bethels_projects") + { + Filter = new TermQuery {Field = Field(p => p.LeadDeveloper.FirstName), Value = FirstNameToFind}, + Aggregations = + new TermsAggregation("project_tags") {Field = Field(p => p.CuratedTags.First().Name)} + } } ---- @@ -70,7 +70,7 @@ new SearchRequest === Handling Responses Using the `.Aggs` aggregation helper we can fetch our aggregation results easily -in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() +in the correct type. <> [source,csharp] ---- @@ -97,13 +97,13 @@ to an empty object. ---- s => s .Aggregations(aggs => aggs - .Filter("empty_filter", date => date - .Filter(f => f - .Bool(b => b - .Filter(new QueryContainer[0]) - ) - ) - ) + .Filter("empty_filter", date => date + .Filter(f => f + .Bool(b => b + .Filter(new QueryContainer[0]) + ) + ) + ) ) ---- @@ -113,13 +113,13 @@ s => s ---- new SearchRequest { - Aggregations = new FilterAggregation("empty_filter") - { - Filter = new BoolQuery - { - Filter = new List() - } - } + Aggregations = new FilterAggregation("empty_filter") + { + Filter = new BoolQuery + { + Filter = new List() + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index 27f3ce39ff0..1b139fc2614 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -4,14 +4,14 @@ :imagesdir: ../../../images/ -[[filters-aggregation]] -== Filters Aggregation +[[filters-aggregation-usage]] +== Filters Aggregation Usage Defines a multi bucket aggregations where each bucket is associated with a filter. Each bucket will collect all documents that match its associated filter. For documents that do not match any filter, these will be collected in the _other bucket_. -Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. +Be sure to read the Elasticsearch documentation on {ref_current}/search-aggregations-bucket-filters-aggregation.html[Filters Aggregation]. [[named-filters]] [float] @@ -23,18 +23,18 @@ Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.htm ---- s => s .Aggregations(aggs => aggs - .Filters("projects_by_state", agg => agg - .OtherBucket() - .OtherBucketKey("other_states_of_being") - .NamedFilters(filters => filters - .Filter("belly_up", f => f.Term(p => p.State, StateOfBeing.BellyUp)) - .Filter("stable", f => f.Term(p => p.State, StateOfBeing.Stable)) - .Filter("very_active", f => f.Term(p => p.State, StateOfBeing.VeryActive)) - ) - .Aggregations(childAggs => childAggs - .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) - ) - ) + .Filters("projects_by_state", agg => agg + .OtherBucket() + .OtherBucketKey("other_states_of_being") + .NamedFilters(filters => filters + .Filter("belly_up", f => f.Term(p => p.State, StateOfBeing.BellyUp)) + .Filter("stable", f => f.Term(p => p.State, StateOfBeing.Stable)) + .Filter("very_active", f => f.Term(p => p.State, StateOfBeing.VeryActive)) + ) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) + ) + ) ) ---- @@ -44,19 +44,19 @@ s => s ---- new SearchRequest { - Aggregations = new FiltersAggregation("projects_by_state") - { - OtherBucket = true, - OtherBucketKey = "other_states_of_being", - Filters = new NamedFiltersContainer - { - { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, - { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, - { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } - }, - Aggregations = - new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } - } + Aggregations = new FiltersAggregation("projects_by_state") + { + OtherBucket = true, + OtherBucketKey = "other_states_of_being", + Filters = new NamedFiltersContainer + { + { "belly_up", Query.Term(p=>p.State, StateOfBeing.BellyUp) }, + { "stable", Query.Term(p=>p.State, StateOfBeing.Stable) }, + { "very_active", Query.Term(p=>p.State, StateOfBeing.VeryActive) } + }, + Aggregations = + new TermsAggregation("project_tags") { Field = Field(p => p.CuratedTags.First().Name) } + } } ---- @@ -108,7 +108,7 @@ new SearchRequest === Handling Responses Using the `.Agg` aggregation helper we can fetch our aggregation results easily -in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() +in the correct type. <> [source,csharp] ---- @@ -140,17 +140,17 @@ namedResult.DocCount.Should().Be(0); ---- s => s .Aggregations(aggs => aggs - .Filters("projects_by_state", agg => agg - .OtherBucket() - .AnonymousFilters( - f => f.Term(p => p.State, StateOfBeing.BellyUp), - f => f.Term(p => p.State, StateOfBeing.Stable), - f => f.Term(p => p.State, StateOfBeing.VeryActive) - ) - .Aggregations(childAggs => childAggs - .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) - ) - ) + .Filters("projects_by_state", agg => agg + .OtherBucket() + .AnonymousFilters( + f => f.Term(p => p.State, StateOfBeing.BellyUp), + f => f.Term(p => p.State, StateOfBeing.Stable), + f => f.Term(p => p.State, StateOfBeing.VeryActive) + ) + .Aggregations(childAggs => childAggs + .Terms("project_tags", avg => avg.Field(p => p.CuratedTags.First().Name)) + ) + ) ) ---- @@ -160,21 +160,21 @@ s => s ---- new SearchRequest { - Aggregations = new FiltersAggregation("projects_by_state") - { - OtherBucket = true, - Filters = new List - { - Query.Term(p=>p.State, StateOfBeing.BellyUp) , - Query.Term(p=>p.State, StateOfBeing.Stable) , - Query.Term(p=>p.State, StateOfBeing.VeryActive) - }, - Aggregations = - new TermsAggregation("project_tags") - { - Field = Field(p => p.CuratedTags.First().Name) - } - } + Aggregations = new FiltersAggregation("projects_by_state") + { + OtherBucket = true, + Filters = new List + { + Query.Term(p=>p.State, StateOfBeing.BellyUp) , + Query.Term(p=>p.State, StateOfBeing.Stable) , + Query.Term(p=>p.State, StateOfBeing.VeryActive) + }, + Aggregations = + new TermsAggregation("project_tags") + { + Field = Field(p => p.CuratedTags.First().Name) + } + } } ---- @@ -225,7 +225,7 @@ new SearchRequest === Handling Responses Using the `.Agg` aggregation helper we can fetch our aggregation results easily -in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() +in the correct type. <> [source,csharp] ---- @@ -236,7 +236,7 @@ filterAgg.Should().NotBeNull(); var results = filterAgg.AnonymousBuckets(); results.Count.Should().Be(4); singleBucket.DocCount.Should().BeGreaterThan(0); -results.Last().DocCount.Should().Be(0); //<1> +results.Last().DocCount.Should().Be(0); <1> ---- <1> The last bucket is the _other bucket_ @@ -250,9 +250,9 @@ results.Last().DocCount.Should().Be(0); //<1> ---- s => s .Aggregations(aggs => aggs - .Filters("empty_filters", agg => agg - .AnonymousFilters() - ) + .Filters("empty_filters", agg => agg + .AnonymousFilters() + ) ) ---- @@ -262,10 +262,10 @@ s => s ---- new SearchRequest { - Aggregations = new FiltersAggregation("empty_filters") - { - Filters = new List() - } + Aggregations = new FiltersAggregation("empty_filters") + { + Filters = new List() + } } ---- @@ -292,6 +292,7 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); ---- [[conditionless-filters]] +[float] == Conditionless Filters === Fluent DSL Example @@ -300,11 +301,11 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); ---- s => s .Aggregations(aggs => aggs - .Filters("conditionless_filters", agg => agg - .AnonymousFilters( - q => new QueryContainer() - ) - ) + .Filters("conditionless_filters", agg => agg + .AnonymousFilters( + q => new QueryContainer() + ) + ) ) ---- @@ -314,13 +315,13 @@ s => s ---- new SearchRequest { - Aggregations = new FiltersAggregation("conditionless_filters") - { - Filters = new List - { - new QueryContainer() - } - } + Aggregations = new FiltersAggregation("conditionless_filters") + { + Filters = new List + { + new QueryContainer() + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index 9edb9906470..59644c37817 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -13,15 +13,15 @@ ---- s => s .Aggregations(a => a - .GeoDistance("rings_around_amsterdam", g => g - .Field(p => p.Location) - .Origin(52.376, 4.894) - .Ranges( - r => r.To(100), - r => r.From(100).To(300), - r => r.From(300) - ) - ) + .GeoDistance("rings_around_amsterdam", g => g + .Field(p => p.Location) + .Origin(52.376, 4.894) + .Ranges( + r => r.To(100), + r => r.From(100).To(300), + r => r.From(300) + ) + ) ) ---- @@ -31,17 +31,17 @@ s => s ---- new SearchRequest { - Aggregations = new GeoDistanceAggregation("rings_around_amsterdam") - { - Field = Field((Project p) => p.Location), - Origin = "52.376, 4.894", - Ranges = new List - { - new Nest.Range { To = 100 }, - new Nest.Range { From = 100, To = 300 }, - new Nest.Range { From = 300 } - } - } + Aggregations = new GeoDistanceAggregation("rings_around_amsterdam") + { + Field = Field((Project p) => p.Location), + Origin = "52.376, 4.894", + Ranges = new List + { + new Nest.Range { To = 100 }, + new Nest.Range { From = 100, To = 300 }, + new Nest.Range { From = 300 } + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index b651c0ef828..1a2403a212e 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -13,12 +13,12 @@ ---- s => s .Aggregations(a => a - .GeoHash("my_geohash_grid", g => g - .Field(p => p.Location) - .GeoHashPrecision(GeoHashPrecision.Precision3) - .Size(1000) - .ShardSize(100) - ) + .GeoHash("my_geohash_grid", g => g + .Field(p => p.Location) + .GeoHashPrecision(GeoHashPrecision.Precision3) + .Size(1000) + .ShardSize(100) + ) ) ---- @@ -28,13 +28,13 @@ s => s ---- new SearchRequest { - Aggregations = new GeoHashGridAggregation("my_geohash_grid") - { - Field = Field(p => p.Location), - Precision = GeoHashPrecision.Precision3, - Size = 1000, - ShardSize = 100 - } + Aggregations = new GeoHashGridAggregation("my_geohash_grid") + { + Field = Field(p => p.Location), + Precision = GeoHashPrecision.Precision3, + Size = 1000, + ShardSize = 100 + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index f447353d008..95df9ed2413 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -13,13 +13,13 @@ ---- s => s .Aggregations(a => a - .Global("all_projects", g => g - .Aggregations(aa => aa - .Terms("names", t => t - .Field(p => p.Name) - ) - ) - ) + .Global("all_projects", g => g + .Aggregations(aa => aa + .Terms("names", t => t + .Field(p => p.Name) + ) + ) + ) ) ---- @@ -29,13 +29,13 @@ s => s ---- new SearchRequest { - Aggregations = new GlobalAggregation("all_projects") - { - Aggregations = new TermsAggregation("names") - { - Field = Field(p => p.Name) - } - } + Aggregations = new GlobalAggregation("all_projects") + { + Aggregations = new TermsAggregation("names") + { + Field = Field(p => p.Name) + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index 5f4a00bfb05..151408b1e3f 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -13,12 +13,12 @@ ---- s => s .Aggregations(a => a - .Histogram("commits", h => h - .Field(p => p.NumberOfCommits) - .Interval(100) - .Missing(0) - .Order(HistogramOrder.KeyDescending) - ) + .Histogram("commits", h => h + .Field(p => p.NumberOfCommits) + .Interval(100) + .Missing(0) + .Order(HistogramOrder.KeyDescending) + ) ) ---- @@ -28,13 +28,13 @@ s => s ---- new SearchRequest { - Aggregations = new HistogramAggregation("commits") - { - Field = Field(p => p.NumberOfCommits), - Interval = 100, - Missing = 0, - Order = HistogramOrder.KeyDescending - } + Aggregations = new HistogramAggregation("commits") + { + Field = Field(p => p.NumberOfCommits), + Interval = 100, + Missing = 0, + Order = HistogramOrder.KeyDescending + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index fecd01af6ed..323cc4ff3ae 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -13,13 +13,13 @@ ---- s => s .Aggregations(a => a - .IpRange("ip_ranges", ip => ip - .Field(p => p.LeadDeveloper.IPAddress) - .Ranges( - r => r.To("10.0.0.5"), - r => r.From("10.0.0.5") - ) - ) + .IpRange("ip_ranges", ip => ip + .Field(p => p.LeadDeveloper.IPAddress) + .Ranges( + r => r.To("10.0.0.5"), + r => r.From("10.0.0.5") + ) + ) ) ---- @@ -29,15 +29,15 @@ s => s ---- new SearchRequest { - Aggregations = new IpRangeAggregation("ip_ranges") - { - Field = Field((Project p) => p.LeadDeveloper.IPAddress), - Ranges = new List - { - new Nest.IpRange { To = "10.0.0.5" }, - new Nest.IpRange { From = "10.0.0.5" } - } - } + Aggregations = new IpRangeAggregation("ip_ranges") + { + Field = Field((Project p) => p.LeadDeveloper.IPAddress), + Ranges = new List + { + new Nest.IpRange { To = "10.0.0.5" }, + new Nest.IpRange { From = "10.0.0.5" } + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index 48d2e64bb67..d1285525650 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .Missing("projects_without_a_description", m => m - .Field(p => p.Description) - ) + .Missing("projects_without_a_description", m => m + .Field(p => p.Description) + ) ) ---- @@ -25,10 +25,10 @@ s => s ---- new SearchRequest { - Aggregations = new MissingAggregation("projects_without_a_description") - { - Field = Field(p => p.Description) - } + Aggregations = new MissingAggregation("projects_without_a_description") + { + Field = Field(p => p.Description) + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index 6279ce6fe40..2d8091a61ee 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -13,14 +13,14 @@ ---- s => s .Aggregations(a => a - .Nested("tags", n => n - .Path(p => p.Tags) - .Aggregations(aa => aa - .Terms("tag_names", t => t - .Field(p => p.Tags.Suffix("name")) - ) - ) - ) + .Nested("tags", n => n + .Path(p => p.Tags) + .Aggregations(aa => aa + .Terms("tag_names", t => t + .Field(p => p.Tags.Suffix("name")) + ) + ) + ) ) ---- @@ -30,14 +30,14 @@ s => s ---- new SearchRequest { - Aggregations = new NestedAggregation("tags") - { - Path = "tags", - Aggregations = new TermsAggregation("tag_names") - { - Field = "tags.name" - } - } + Aggregations = new NestedAggregation("tags") + { + Path = "tags", + Aggregations = new TermsAggregation("tag_names") + { + Field = "tags.name" + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index e550a93c060..5e238c80372 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -13,14 +13,14 @@ ---- s => s .Aggregations(a => a - .Range("commit_ranges", ra => ra - .Field(p => p.NumberOfCommits) - .Ranges( - r => r.To(100), - r => r.From(100).To(500), - r => r.From(500) - ) - ) + .Range("commit_ranges", ra => ra + .Field(p => p.NumberOfCommits) + .Ranges( + r => r.To(100), + r => r.From(100).To(500), + r => r.From(500) + ) + ) ) ---- @@ -30,16 +30,16 @@ s => s ---- new SearchRequest { - Aggregations = new RangeAggregation("commit_ranges") - { - Field = Field(p => p.NumberOfCommits), - Ranges = new List - { - { new Nest.Range { To = 100 } }, - { new Nest.Range { From = 100, To = 500 } }, - { new Nest.Range { From = 500 } } - } - } + Aggregations = new RangeAggregation("commit_ranges") + { + Field = Field(p => p.NumberOfCommits), + Ranges = new List + { + { new Nest.Range { To = 100 } }, + { new Nest.Range { From = 100, To = 500 } }, + { new Nest.Range { From = 500 } } + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index 69ec97fe5f3..916200e2ec8 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -13,23 +13,23 @@ ---- s => s .Aggregations(a => a - .Nested("tags", n => n - .Path(p => p.Tags) - .Aggregations(aa => aa - .Terms("tag_names", t => t - .Field(p => p.Tags.Suffix("name")) - .Aggregations(aaa => aaa - .ReverseNested("tags_to_project", r => r - .Aggregations(aaaa => aaaa - .Terms("top_projects_per_tag", tt => tt - .Field(p => p.Name) - ) - ) - ) - ) - ) - ) - ) + .Nested("tags", n => n + .Path(p => p.Tags) + .Aggregations(aa => aa + .Terms("tag_names", t => t + .Field(p => p.Tags.Suffix("name")) + .Aggregations(aaa => aaa + .ReverseNested("tags_to_project", r => r + .Aggregations(aaaa => aaaa + .Terms("top_projects_per_tag", tt => tt + .Field(p => p.Name) + ) + ) + ) + ) + ) + ) + ) ) ---- @@ -39,21 +39,21 @@ s => s ---- new SearchRequest { - Aggregations = new NestedAggregation("tags") - { - Path = "tags", - Aggregations = new TermsAggregation("tag_names") - { - Field = "tags.name", - Aggregations = new ReverseNestedAggregation("tags_to_project") - { - Aggregations = new TermsAggregation("top_projects_per_tag") - { - Field = Field(p => p.Name) - } - } - } - } + Aggregations = new NestedAggregation("tags") + { + Path = "tags", + Aggregations = new TermsAggregation("tag_names") + { + Field = "tags.name", + Aggregations = new ReverseNestedAggregation("tags_to_project") + { + Aggregations = new TermsAggregation("top_projects_per_tag") + { + Field = Field(p => p.Name) + } + } + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index 33efc3ef196..3ded3c03bf1 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -13,15 +13,15 @@ ---- s => s .Aggregations(aggs => aggs - .Sampler("sample", sm => sm - .ShardSize(200) - .Field(p => p.Name) - .Aggregations(aa => aa - .SignificantTerms("significant_names", st => st - .Field(p => p.Name) - ) - ) - ) + .Sampler("sample", sm => sm + .ShardSize(200) + .Field(p => p.Name) + .Aggregations(aa => aa + .SignificantTerms("significant_names", st => st + .Field(p => p.Name) + ) + ) + ) ) ---- @@ -31,15 +31,15 @@ s => s ---- new SearchRequest { - Aggregations = new SamplerAggregation("sample") - { - ShardSize = 200, - Field = "name", - Aggregations = new SignificantTermsAggregation("significant_names") - { - Field = "name" - } - } + Aggregations = new SamplerAggregation("sample") + { + ShardSize = 200, + Field = "name", + Aggregations = new SignificantTermsAggregation("significant_names") + { + Field = "name" + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 3153fb26e3e..be714e87a81 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -13,14 +13,14 @@ ---- s => s .Aggregations(a => a - .SignificantTerms("significant_names", st => st - .Field(p => p.Name) - .MinimumDocumentCount(10) - .MutualInformation(mi => mi - .BackgroundIsSuperSet() - .IncludeNegatives() - ) - ) + .SignificantTerms("significant_names", st => st + .Field(p => p.Name) + .MinimumDocumentCount(10) + .MutualInformation(mi => mi + .BackgroundIsSuperSet() + .IncludeNegatives() + ) + ) ) ---- @@ -30,16 +30,16 @@ s => s ---- new SearchRequest { - Aggregations = new SignificantTermsAggregation("significant_names") - { - Field = Field(p => p.Name), - MinimumDocumentCount = 10, - MutualInformation = new MutualInformationHeuristic - { - BackgroundIsSuperSet = true, - IncludeNegatives = true - } - } + Aggregations = new SignificantTermsAggregation("significant_names") + { + Field = Field(p => p.Name), + MinimumDocumentCount = 10, + MutualInformation = new MutualInformationHeuristic + { + BackgroundIsSuperSet = true, + IncludeNegatives = true + } + } } ---- diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index 467a8d58302..a5660ff1827 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -13,21 +13,21 @@ ---- s => s .Aggregations(a => a - .Terms("states", st => st - .Field(p => p.State) - .MinimumDocumentCount(2) - .Size(5) - .ShardSize(100) - .ShowTermDocumentCountError() - .ExecutionHint(TermsAggregationExecutionHint.Map) - .Missing("n/a") - .Script("'State of Being: '+_value") - .Order(TermsOrder.TermAscending) - .Order(TermsOrder.CountDescending) - .Meta(m => m - .Add("foo", "bar") - ) - ) + .Terms("states", st => st + .Field(p => p.State) + .MinimumDocumentCount(2) + .Size(5) + .ShardSize(100) + .ShowTermDocumentCountError() + .ExecutionHint(TermsAggregationExecutionHint.Map) + .Missing("n/a") + .Script("'State of Being: '+_value") + .Order(TermsOrder.TermAscending) + .Order(TermsOrder.CountDescending) + .Meta(m => m + .Add("foo", "bar") + ) + ) ) ---- @@ -37,26 +37,26 @@ s => s ---- new SearchRequest { - Aggregations = new TermsAggregation("states") - { - Field = Field(p => p.State), - MinimumDocumentCount = 2, - Size = 5, - ShardSize = 100, - ShowTermDocumentCountError = true, - ExecutionHint = TermsAggregationExecutionHint.Map, - Missing = "n/a", - Script = new InlineScript("'State of Being: '+_value"), - Order = new List - { - TermsOrder.TermAscending, - TermsOrder.CountDescending - }, - Meta = new Dictionary - { - { "foo", "bar" } - } - } + Aggregations = new TermsAggregation("states") + { + Field = Field(p => p.State), + MinimumDocumentCount = 2, + Size = 5, + ShardSize = 100, + ShowTermDocumentCountError = true, + ExecutionHint = TermsAggregationExecutionHint.Map, + Missing = "n/a", + Script = new InlineScript("'State of Being: '+_value"), + Order = new List + { + TermsOrder.TermAscending, + TermsOrder.CountDescending + }, + Meta = new Dictionary + { + { "foo", "bar" } + } + } } ---- diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index 2af30584175..69410c317f1 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -13,14 +13,14 @@ ---- s => s .Aggregations(a => a - .Average("average_commits", avg => avg - .Meta(m => m - .Add("foo", "bar") - ) - .Field(p => p.NumberOfCommits) - .Missing(10) - .Script("_value * 1.2") - ) + .Average("average_commits", avg => avg + .Meta(m => m + .Add("foo", "bar") + ) + .Field(p => p.NumberOfCommits) + .Missing(10) + .Script("_value * 1.2") + ) ) ---- @@ -30,15 +30,15 @@ s => s ---- new SearchRequest { - Aggregations = new AverageAggregation("average_commits", Field(p => p.NumberOfCommits)) - { - Meta = new Dictionary - { - { "foo", "bar" } - }, - Missing = 10, - Script = new InlineScript("_value * 1.2") - } + Aggregations = new AverageAggregation("average_commits", Field(p => p.NumberOfCommits)) + { + Meta = new Dictionary + { + { "foo", "bar" } + }, + Missing = 10, + Script = new InlineScript("_value * 1.2") + } } ---- diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index d9ec2a6417b..dab1cba4fc6 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -13,10 +13,10 @@ ---- s => s .Aggregations(a => a - .Cardinality("state_count", c => c - .Field(p => p.State) - .PrecisionThreshold(100) - ) + .Cardinality("state_count", c => c + .Field(p => p.State) + .PrecisionThreshold(100) + ) ) ---- @@ -26,10 +26,10 @@ s => s ---- new SearchRequest { - Aggregations = new CardinalityAggregation("state_count", Field(p => p.State)) - { - PrecisionThreshold = 100 - } + Aggregations = new CardinalityAggregation("state_count", Field(p => p.State)) + { + PrecisionThreshold = 100 + } } ---- diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 2829ad893f4..13caf7ff775 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .ExtendedStats("commit_stats", es => es - .Field(p => p.NumberOfCommits) - ) + .ExtendedStats("commit_stats", es => es + .Field(p => p.NumberOfCommits) + ) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - Aggregations = new ExtendedStatsAggregation("commit_stats", Field(p => p.NumberOfCommits)) + Aggregations = new ExtendedStatsAggregation("commit_stats", Field(p => p.NumberOfCommits)) } ---- diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index ef236773293..670c6ef6fad 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -13,10 +13,10 @@ ---- s => s .Aggregations(a => a - .GeoBounds("viewport", gb => gb - .Field(p => p.Location) - .WrapLongitude(true) - ) + .GeoBounds("viewport", gb => gb + .Field(p => p.Location) + .WrapLongitude(true) + ) ) ---- @@ -26,10 +26,10 @@ s => s ---- new SearchRequest { - Aggregations = new GeoBoundsAggregation("viewport", Field(p => p.Location)) - { - WrapLongitude = true - } + Aggregations = new GeoBoundsAggregation("viewport", Field(p => p.Location)) + { + WrapLongitude = true + } } ---- diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index f772d37d3de..2c8e8242868 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .Max("max_commits", m => m - .Field(p => p.NumberOfCommits) - ) + .Max("max_commits", m => m + .Field(p => p.NumberOfCommits) + ) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - Aggregations = new MaxAggregation("max_commits", Field(p => p.NumberOfCommits)) + Aggregations = new MaxAggregation("max_commits", Field(p => p.NumberOfCommits)) } ---- diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index 43e5551264d..4f7d6ad1dc9 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .Min("min_commits", m => m - .Field(p => p.NumberOfCommits) - ) + .Min("min_commits", m => m + .Field(p => p.NumberOfCommits) + ) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - Aggregations = new MinAggregation("min_commits", Field(p => p.NumberOfCommits)) + Aggregations = new MinAggregation("min_commits", Field(p => p.NumberOfCommits)) } ---- diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index 1862135e920..8adec6bdbda 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -13,17 +13,17 @@ ---- s => s .Aggregations(a => a - .PercentileRanks("commits_outlier", pr => pr - .Field(p => p.NumberOfCommits) - .Values(15, 30) - .Method(m => m - .TDigest(td => td - .Compression(200) - ) - ) - .Script("doc['numberOfCommits'].value * 1.2") - .Missing(0) - ) + .PercentileRanks("commits_outlier", pr => pr + .Field(p => p.NumberOfCommits) + .Values(15, 30) + .Method(m => m + .TDigest(td => td + .Compression(200) + ) + ) + .Script("doc['numberOfCommits'].value * 1.2") + .Missing(0) + ) ) ---- @@ -33,16 +33,16 @@ s => s ---- new SearchRequest { - Aggregations = new PercentileRanksAggregation("commits_outlier", Field(p => p.NumberOfCommits)) - { - Values = new List { 15, 30 }, - Method = new TDigestMethod - { - Compression = 200 - }, - Script = (InlineScript)"doc['numberOfCommits'].value * 1.2", - Missing = 0 - } + Aggregations = new PercentileRanksAggregation("commits_outlier", Field(p => p.NumberOfCommits)) + { + Values = new List { 15, 30 }, + Method = new TDigestMethod + { + Compression = 200 + }, + Script = (InlineScript)"doc['numberOfCommits'].value * 1.2", + Missing = 0 + } } ---- diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index ba48e51ef50..d3918a86202 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -13,17 +13,17 @@ ---- s => s .Aggregations(a => a - .Percentiles("commits_outlier", pr => pr - .Field(p => p.NumberOfCommits) - .Percents(95, 99, 99.9) - .Method(m => m - .HDRHistogram(hdr => hdr - .NumberOfSignificantValueDigits(3) - ) - ) - .Script("doc['numberOfCommits'].value * 1.2") - .Missing(0) - ) + .Percentiles("commits_outlier", pr => pr + .Field(p => p.NumberOfCommits) + .Percents(95, 99, 99.9) + .Method(m => m + .HDRHistogram(hdr => hdr + .NumberOfSignificantValueDigits(3) + ) + ) + .Script("doc['numberOfCommits'].value * 1.2") + .Missing(0) + ) ) ---- @@ -33,16 +33,16 @@ s => s ---- new SearchRequest { - Aggregations = new PercentilesAggregation("commits_outlier", Field(p => p.NumberOfCommits)) - { - Percents = new[] { 95, 99, 99.9 }, - Method = new HDRHistogramMethod - { - NumberOfSignificantValueDigits = 3 - }, - Script = new InlineScript("doc['numberOfCommits'].value * 1.2"), - Missing = 0 - } + Aggregations = new PercentilesAggregation("commits_outlier", Field(p => p.NumberOfCommits)) + { + Percents = new[] { 95, 99, 99.9 }, + Method = new HDRHistogramMethod + { + NumberOfSignificantValueDigits = 3 + }, + Script = new InlineScript("doc['numberOfCommits'].value * 1.2"), + Missing = 0 + } } ---- diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index b07c3a58e0e..e93b1a34588 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -13,12 +13,12 @@ ---- s => s .Aggregations(a => a - .ScriptedMetric("sum_the_hard_way", sm => sm - .InitScript("_agg['commits'] = []") - .MapScript("if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }") - .CombineScript("sum = 0; for (c in _agg.commits) { sum += c }; return sum") - .ReduceScript("sum = 0; for (a in _aggs) { sum += a }; return sum") - ) + .ScriptedMetric("sum_the_hard_way", sm => sm + .InitScript("_agg['commits'] = []") + .MapScript("if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }") + .CombineScript("sum = 0; for (c in _agg.commits) { sum += c }; return sum") + .ReduceScript("sum = 0; for (a in _aggs) { sum += a }; return sum") + ) ) ---- @@ -28,13 +28,13 @@ s => s ---- new SearchRequest { - Aggregations = new ScriptedMetricAggregation("sum_the_hard_way") - { - InitScript = new InlineScript("_agg['commits'] = []"), - MapScript = new InlineScript("if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }"), - CombineScript = new InlineScript("sum = 0; for (c in _agg.commits) { sum += c }; return sum"), - ReduceScript = new InlineScript("sum = 0; for (a in _aggs) { sum += a }; return sum") - } + Aggregations = new ScriptedMetricAggregation("sum_the_hard_way") + { + InitScript = new InlineScript("_agg['commits'] = []"), + MapScript = new InlineScript("if (doc['state'].value == \"Stable\") { _agg.commits.add(doc['numberOfCommits']) }"), + CombineScript = new InlineScript("sum = 0; for (c in _agg.commits) { sum += c }; return sum"), + ReduceScript = new InlineScript("sum = 0; for (a in _aggs) { sum += a }; return sum") + } } ---- diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index faed1169468..4508c2ad5d5 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .Stats("commit_stats", st => st - .Field(p => p.NumberOfCommits) - ) + .Stats("commit_stats", st => st + .Field(p => p.NumberOfCommits) + ) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - Aggregations = new StatsAggregation("commit_stats", Field(p => p.NumberOfCommits)) + Aggregations = new StatsAggregation("commit_stats", Field(p => p.NumberOfCommits)) } ---- diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 9c98b685ec0..01c966930c0 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .Sum("commits_sum", sm => sm - .Field(p => p.NumberOfCommits) - ) + .Sum("commits_sum", sm => sm + .Field(p => p.NumberOfCommits) + ) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - Aggregations = new SumAggregation("commits_sum", Field(p => p.NumberOfCommits)) + Aggregations = new SumAggregation("commits_sum", Field(p => p.NumberOfCommits)) } ---- diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index 956da9197ea..f344702a819 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -13,41 +13,41 @@ ---- s => s .Aggregations(a => a - .Terms("states", t => t - .Field(p => p.State) - .Aggregations(aa => aa - .TopHits("top_state_hits", th => th - .Sort(srt => srt - .Field(p => p.StartedOn) - .Order(SortOrder.Descending) - ) - .Source(src => src - .Include(fs => fs - .Field(p => p.Name) - .Field(p => p.StartedOn) - ) - ) - .Size(1) - .Version() - .Explain() - .FielddataFields(fd => fd - .Field(p => p.State) - .Field(p => p.NumberOfCommits) - ) - .Highlight(h => h - .Fields( - hf => hf.Field(p => p.Tags), - hf => hf.Field(p => p.Description) - ) - ) - .ScriptFields(sfs => sfs - .ScriptField("commit_factor", sf => sf - .Inline("doc['numberOfCommits'].value * 2") - ) - ) - ) - ) - ) + .Terms("states", t => t + .Field(p => p.State) + .Aggregations(aa => aa + .TopHits("top_state_hits", th => th + .Sort(srt => srt + .Field(p => p.StartedOn) + .Order(SortOrder.Descending) + ) + .Source(src => src + .Include(fs => fs + .Field(p => p.Name) + .Field(p => p.StartedOn) + ) + ) + .Size(1) + .Version() + .Explain() + .FielddataFields(fd => fd + .Field(p => p.State) + .Field(p => p.NumberOfCommits) + ) + .Highlight(h => h + .Fields( + hf => hf.Field(p => p.Tags), + hf => hf.Field(p => p.Description) + ) + ) + .ScriptFields(sfs => sfs + .ScriptField("commit_factor", sf => sf + .Inline("doc['numberOfCommits'].value * 2") + ) + ) + ) + ) + ) ) ---- @@ -57,39 +57,39 @@ s => s ---- new SearchRequest { - Aggregations = new TermsAggregation("states") - { - Field = Field(p => p.State), - Aggregations = new TopHitsAggregation("top_state_hits") - { - Sort = new List - { - { - new SortField { Field = Field(p => p.StartedOn), Order = SortOrder.Descending } - } - }, - Source = new SourceFilter - { - Include = new [] { "name", "startedOn" } - }, - Size = 1, - Version = true, - Explain = true, - FielddataFields = new [] { "state", "numberOfCommits" }, - Highlight = new Highlight - { - Fields = new Dictionary - { - { Field(p => p.Tags), new HighlightField() }, - { Field(p => p.Description), new HighlightField() } - } - }, - ScriptFields = new ScriptFields - { - { "commit_factor", new ScriptField { Script = new InlineScript("doc['numberOfCommits'].value * 2") } } - } - } - } + Aggregations = new TermsAggregation("states") + { + Field = Field(p => p.State), + Aggregations = new TopHitsAggregation("top_state_hits") + { + Sort = new List + { + { + new SortField { Field = Field(p => p.StartedOn), Order = SortOrder.Descending } + } + }, + Source = new SourceFilter + { + Include = new [] { "name", "startedOn" } + }, + Size = 1, + Version = true, + Explain = true, + FielddataFields = new [] { "state", "numberOfCommits" }, + Highlight = new Highlight + { + Fields = new Dictionary + { + { Field(p => p.Tags), new HighlightField() }, + { Field(p => p.Description), new HighlightField() } + } + }, + ScriptFields = new ScriptFields + { + { "commit_factor", new ScriptField { Script = new InlineScript("doc['numberOfCommits'].value * 2") } } + } + } + } } ---- diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index e0e2bc8edab..b7e9641fc88 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .Aggregations(a => a - .ValueCount("commit_count", c => c - .Field(p => p.NumberOfCommits) - ) + .ValueCount("commit_count", c => c + .Field(p => p.NumberOfCommits) + ) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - Aggregations = new ValueCountAggregation("commit_count", Field(p => p.NumberOfCommits)) + Aggregations = new ValueCountAggregation("commit_count", Field(p => p.NumberOfCommits)) } ---- diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index b51d1fd547d..b51898f2570 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -14,19 +14,19 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - ) - ) - .AverageBucket("average_commits_per_month", aaa => aaa - .BucketsPath("projects_started_per_month>commits") - .GapPolicy(GapPolicy.InsertZeros) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .AverageBucket("average_commits_per_month", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + .GapPolicy(GapPolicy.InsertZeros) + ) ) ---- @@ -35,19 +35,19 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = new SumAggregation("commits", "numberOfCommits") -} -&& new AverageBucketAggregation("average_commits_per_month", "projects_started_per_month>commits") -{ - GapPolicy = GapPolicy.InsertZeros + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") + } + && new AverageBucketAggregation("average_commits_per_month", "projects_started_per_month>commits") + { + GapPolicy = GapPolicy.InsertZeros + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index 6a1b6aebe68..5313f8f5a7b 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -14,32 +14,32 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .Filter("stable_state", f => f - .Filter(ff => ff - .Term(p => p.State, "Stable") - ) - .Aggregations(aaa => aaa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - ) - ) - .BucketScript("stable_percentage", bs => bs - .BucketsPath(bp => bp - .Add("totalCommits", "commits") - .Add("stableCommits", "stable_state>commits") - ) - .Script("stableCommits / totalCommits * 100") - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .Filter("stable_state", f => f + .Filter(ff => ff + .Term(p => p.State, "Stable") + ) + .Aggregations(aaa => aaa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .BucketScript("stable_percentage", bs => bs + .BucketsPath(bp => bp + .Add("totalCommits", "commits") + .Add("stableCommits", "stable_state>commits") + ) + .Script("stableCommits / totalCommits * 100") + ) + ) + ) ) ---- @@ -48,33 +48,33 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new FilterAggregation("stable_state") - { - Filter = new TermQuery - { - Field = "state", - Value = "Stable" - }, - Aggregations = new SumAggregation("commits", "numberOfCommits") - } && - new BucketScriptAggregation("stable_percentage", new MultiBucketsPath - { - { "totalCommits", "commits" }, - { "stableCommits", "stable_state>commits" } - }) - { - Script = (InlineScript)"stableCommits / totalCommits * 100" - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new FilterAggregation("stable_state") + { + Filter = new TermQuery + { + Field = "state", + Value = "Stable" + }, + Aggregations = new SumAggregation("commits", "numberOfCommits") + } && + new BucketScriptAggregation("stable_percentage", new MultiBucketsPath + { + { "totalCommits", "commits" }, + { "stableCommits", "stable_state>commits" } + }) + { + Script = (InlineScript)"stableCommits / totalCommits * 100" + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 12fee9af4d7..67bc25de59b 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -14,21 +14,21 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .BucketSelector("commits_bucket_filter", bs => bs - .BucketsPath(bp => bp - .Add("totalCommits", "commits") - ) - .Script("totalCommits >= 500") - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .BucketSelector("commits_bucket_filter", bs => bs + .BucketsPath(bp => bp + .Add("totalCommits", "commits") + ) + .Script("totalCommits >= 500") + ) + ) + ) ) ---- @@ -37,23 +37,23 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new BucketSelectorAggregation("commits_bucket_filter", new MultiBucketsPath - { - { "totalCommits", "commits" }, - }) - { - Script = (InlineScript)"totalCommits >= 500" - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new BucketSelectorAggregation("commits_bucket_filter", new MultiBucketsPath + { + { "totalCommits", "commits" }, + }) + { + Script = (InlineScript)"totalCommits >= 500" + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index 055fc570e7b..0106cac1193 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -28,18 +28,18 @@ commitsDerivative.Value.Should().NotBe(null); s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .CumulativeSum("cumulative_commits", d => d - .BucketsPath("commits") - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .CumulativeSum("cumulative_commits", d => d + .BucketsPath("commits") + ) + ) + ) ) ---- @@ -48,17 +48,17 @@ s => s [source,csharp] ---- new SearchRequest - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new CumulativeSumAggregation("cumulative_commits", "commits") + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new CumulativeSumAggregation("cumulative_commits", "commits") + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index 39b19280222..f312a81f3e8 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -28,18 +28,18 @@ commitsDerivative.Value.Should().NotBe(null); s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .Derivative("commits_derivative", d => d - .BucketsPath("commits") - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .Derivative("commits_derivative", d => d + .BucketsPath("commits") + ) + ) + ) ) ---- @@ -48,17 +48,17 @@ s => s [source,csharp] ---- new SearchRequest - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new DerivativeAggregation("commits_derivative", "commits") + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new DerivativeAggregation("commits_derivative", "commits") + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index 6f7df0a88aa..05f6811050e 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -14,18 +14,18 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - ) - ) - .MaxBucket("max_commits_per_month", aaa => aaa - .BucketsPath("projects_started_per_month>commits") - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .MaxBucket("max_commits_per_month", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + ) ) ---- @@ -34,16 +34,16 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = new SumAggregation("commits", "numberOfCommits") + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") + } + && new MaxBucketAggregation("max_commits_per_month", "projects_started_per_month>commits") } -&& new MaxBucketAggregation("max_commits_per_month", "projects_started_per_month>commits") - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index dbaefa85fa4..ab8bec24559 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -14,18 +14,18 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - ) - ) - .MinBucket("min_commits_per_month", aaa => aaa - .BucketsPath("projects_started_per_month>commits") - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .MinBucket("min_commits_per_month", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + ) ) ---- @@ -34,16 +34,16 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = new SumAggregation("commits", "numberOfCommits") + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") + } + && new MinBucketAggregation("min_commits_per_month", "projects_started_per_month>commits") } -&& new MinBucketAggregation("min_commits_per_month", "projects_started_per_month>commits") - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index 3739c16d106..786eec57ee3 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -14,23 +14,23 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .MovingAverage("commits_moving_avg", mv => mv - .BucketsPath("commits") - .Model(m => m - .Ewma(e => e - .Alpha(0.3f) - ) - ) - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Model(m => m + .Ewma(e => e + .Alpha(0.3f) + ) + ) + ) + ) + ) ) ---- @@ -39,23 +39,23 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new MovingAverageAggregation("commits_moving_avg", "commits") - { - Model = new EwmaModel - { - Alpha = 0.3f, - } - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Model = new EwmaModel + { + Alpha = 0.3f, + } + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index 310eaa02630..8b2738167bf 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -14,24 +14,24 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .MovingAverage("commits_moving_avg", mv => mv - .BucketsPath("commits") - .Model(m => m - .HoltLinear(hl => hl - .Alpha(0.5f) - .Beta(0.5f) - ) - ) - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Model(m => m + .HoltLinear(hl => hl + .Alpha(0.5f) + .Beta(0.5f) + ) + ) + ) + ) + ) ) ---- @@ -40,24 +40,24 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new MovingAverageAggregation("commits_moving_avg", "commits") - { - Model = new HoltLinearModel - { - Alpha = 0.5f, - Beta = 0.5f, - } - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Model = new HoltLinearModel + { + Alpha = 0.5f, + Beta = 0.5f, + } + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index 65483b9a63d..7ec758fe642 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -14,29 +14,29 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .MovingAverage("commits_moving_avg", mv => mv - .BucketsPath("commits") - .Window(60) - .Model(m => m - .HoltWinters(hw => hw - .Type(HoltWintersType.Multiplicative) - .Alpha(0.5f) - .Beta(0.5f) - .Gamma(0.5f) - .Period(30) - .Pad(false) - ) - ) - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Window(60) + .Model(m => m + .HoltWinters(hw => hw + .Type(HoltWintersType.Multiplicative) + .Alpha(0.5f) + .Beta(0.5f) + .Gamma(0.5f) + .Period(30) + .Pad(false) + ) + ) + ) + ) + ) ) ---- @@ -45,29 +45,29 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new MovingAverageAggregation("commits_moving_avg", "commits") - { - Window = 60, - Model = new HoltWintersModel - { - Type = HoltWintersType.Multiplicative, - Alpha = 0.5f, - Beta = 0.5f, - Gamma = 0.5f, - Period = 30, - Pad = false - } - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Window = 60, + Model = new HoltWintersModel + { + Type = HoltWintersType.Multiplicative, + Alpha = 0.5f, + Beta = 0.5f, + Gamma = 0.5f, + Period = 30, + Pad = false + } + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index a400d7c8673..a6f24fb454b 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -14,22 +14,22 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .MovingAverage("commits_moving_avg", mv => mv - .BucketsPath("commits") - .GapPolicy(GapPolicy.InsertZeros) - .Model(m => m - .Linear() - ) - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .GapPolicy(GapPolicy.InsertZeros) + .Model(m => m + .Linear() + ) + ) + ) + ) ) ---- @@ -38,21 +38,21 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new MovingAverageAggregation("commits_moving_avg", "commits") - { - GapPolicy = GapPolicy.InsertZeros, - Model = new LinearModel() - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + GapPolicy = GapPolicy.InsertZeros, + Model = new LinearModel() + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index c6e2123610b..5f4e11d7c0b 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -14,23 +14,23 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .MovingAverage("commits_moving_avg", mv => mv - .BucketsPath("commits") - .Window(30) - .Predict(10) - .Model(m => m - .Simple() - ) - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .MovingAverage("commits_moving_avg", mv => mv + .BucketsPath("commits") + .Window(30) + .Predict(10) + .Model(m => m + .Simple() + ) + ) + ) + ) ) ---- @@ -39,22 +39,22 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new MovingAverageAggregation("commits_moving_avg", "commits") - { - Window = 30, - Predict = 10, - Model = new SimpleModel() - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new MovingAverageAggregation("commits_moving_avg", "commits") + { + Window = 30, + Predict = 10, + Model = new SimpleModel() + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index 9931197bf34..5bb13c323f5 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -28,19 +28,19 @@ commits.Value.Should().NotBe(null); s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - .SerialDifferencing("thirtieth_difference", d => d - .BucketsPath("commits") - .Lag(30) - ) - ) - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + .SerialDifferencing("thirtieth_difference", d => d + .BucketsPath("commits") + .Lag(30) + ) + ) + ) ) ---- @@ -49,20 +49,20 @@ s => s [source,csharp] ---- new SearchRequest - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = - new SumAggregation("commits", "numberOfCommits") && - new SerialDifferencingAggregation("thirtieth_difference", "commits") - { - Lag = 30 - } + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = + new SumAggregation("commits", "numberOfCommits") && + new SerialDifferencingAggregation("thirtieth_difference", "commits") + { + Lag = 30 + } + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index d08593f0a7a..42bef649d07 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -14,18 +14,18 @@ s => s .Size(0) .Aggregations(a => a - .DateHistogram("projects_started_per_month", dh => dh - .Field(p => p.StartedOn) - .Interval(DateInterval.Month) - .Aggregations(aa => aa - .Sum("commits", sm => sm - .Field(p => p.NumberOfCommits) - ) - ) - ) - .SumBucket("sum_of_commits", aaa => aaa - .BucketsPath("projects_started_per_month>commits") - ) + .DateHistogram("projects_started_per_month", dh => dh + .Field(p => p.StartedOn) + .Interval(DateInterval.Month) + .Aggregations(aa => aa + .Sum("commits", sm => sm + .Field(p => p.NumberOfCommits) + ) + ) + ) + .SumBucket("sum_of_commits", aaa => aaa + .BucketsPath("projects_started_per_month>commits") + ) ) ---- @@ -34,16 +34,16 @@ s => s [source,csharp] ---- new SearchRequest() - { -Size = 0, -Aggregations = new DateHistogramAggregation("projects_started_per_month") { - Field = "startedOn", - Interval = DateInterval.Month, - Aggregations = new SumAggregation("commits", "numberOfCommits") + Size = 0, + Aggregations = new DateHistogramAggregation("projects_started_per_month") + { + Field = "startedOn", + Interval = DateInterval.Month, + Aggregations = new SumAggregation("commits", "numberOfCommits") + } + && new SumBucketAggregation("sum_of_commits", "projects_started_per_month>commits") } -&& new SumBucketAggregation("sum_of_commits", "projects_started_per_month>commits") - } ---- [source,javascript] diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 15c5a1eb2e0..de13cad4025 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -7,7 +7,6 @@ [[writing-aggregations]] == Writing Aggregations -Aggregations are arguably one of the most powerful features of Elasticsearch. NEST allows you to write your aggregations using * a strict fluent DSL @@ -32,12 +31,12 @@ It benefits from types that are carried over to sub aggregations ---- s => s .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => childAggs - .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) - ) - ) + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) + ) ) ---- @@ -45,18 +44,18 @@ s => s The object initializer syntax (OIS) is a one-to-one mapping with how aggregations have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one -mapping, being dictionary based in C means it can grow exponentially in complexity rather quickly. +mapping, being dictionary based in C# means it can grow exponentially in complexity rather quickly. [source,csharp] ---- new SearchRequest { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", "confidenceFactor") - && new MaxAggregation("max_per_child", "confidenceFactor") - } + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", "confidenceFactor") + && new MaxAggregation("max_per_child", "confidenceFactor") + } } ---- @@ -64,7 +63,7 @@ new SearchRequest For this reason the OIS syntax can be shortened dramatically by using `*Agg` related family, These allow you to forego introducing intermediary Dictionaries to represent the aggregation DSL. -It also allows you to combine multiple aggregations using bitwise AND (`&&`) operator. +It also allows you to combine multiple aggregations using bitwise AND `&&`) operator. Compare the following example with the previous vanilla OIS syntax @@ -72,12 +71,12 @@ Compare the following example with the previous vanilla OIS syntax ---- new SearchRequest { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) - && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) - } + Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) + { + Aggregations = + new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) + && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) + } } ---- @@ -85,25 +84,73 @@ new SearchRequest An advanced scenario may involve an existing collection of aggregation functions that should be set as aggregations on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor -(`childAggs` below) in turn, returning the descriptor after each function application. +`childAggs` below) in turn, returning the descriptor after each function application. [source,csharp] ---- -var aggregations = new List, IAggregationContainer>> //<1> +var aggregations = new List, IAggregationContainer>> <1> { - a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), - a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + a => a.Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)), + a => a.Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) }; return s => s - .Aggregations(aggs => aggs - .Children("name_of_child_agg", child => child - .Aggregations(childAggs => - aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) //<2> - ) - ) - ); + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => + aggregations.Aggregate(childAggs, (acc, agg) => { agg(acc); return acc; }) <2> + ) + ) + ); ---- <1> a list of aggregation functions to apply <2> Using LINQ's `Aggregate()` function to accumulate/apply all of the aggregation functions +[[aggs-vs-aggregations]] +=== Aggs vs. Aggregations + +The response exposesboth `.Aggregations` and `.Aggs` properties for handling aggregations. Why two properties you ask? +Well, the former is a dictionary of aggregation names to `IAggregate` types, a common interface for +aggregation responses (termed __Aggregates__ in NEST), and the latter, is a convenience helper to get the right type +of aggregation response out of the dictionary based on a key name. + +This is better illustrated with an example + +Let's imagine we make the following request. + +[source,csharp] +---- +s => s + .Aggregations(aggs => aggs +.Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) +) + ) +---- + +=== Aggs usage + +Now, using `.Aggs`, we can easily get the `Children` aggregation response out and from that, +the `Average` and `Max` sub aggregations. + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); + +var childAggregation = response.Aggs.Children("name_of_child_agg"); + +var averagePerChild = childAggregation.Average("average_per_child"); + +averagePerChild.Should().NotBeNull(); <1> + +var maxPerChild = childAggregation.Max("max_per_child"); + +maxPerChild.Should().NotBeNull(); <2> +---- +<1> Do something with the average per child. Here we just assert it's not null + +<2> Do something with the max per child. Here we just assert it's not null + diff --git a/docs/asciidoc/client-concepts.asciidoc b/docs/asciidoc/client-concepts.asciidoc index eb7ac6d6167..9c20575e2e1 100644 --- a/docs/asciidoc/client-concepts.asciidoc +++ b/docs/asciidoc/client-concepts.asciidoc @@ -1,12 +1,4 @@ -[[client-concepts]] -= Client Concepts - include::low-level.asciidoc[] include::high-level.asciidoc[] -include::connection-pooling.asciidoc[] - - - - diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 60be8825eb8..905e673a20b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -1,64 +1,63 @@ -:section-number: 4.5 - -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images/ - -[[date-time-providers]] -== Date time providers - -Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` -in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover -without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. - -[source,csharp] ----- -var dateTimeProvider = DateTimeProvider.Default; ----- - -dates are always returned in UTC - -[source,csharp] ----- -dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); ----- - -Another responsibility of this interface is to calculate the time a node has to be taken out of rotation -based on the number of attempts to revive it. For very advanced use cases, this might be something of interest -to provide a custom implementation for. - -[source,csharp] ----- -var dateTimeProvider = DateTimeProvider.Default; ----- - -The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the -default values for `timeout` and `maxTimeout` are - -[source,csharp] ----- -var timeout = TimeSpan.FromMinutes(1); - -var maxTimeout = TimeSpan.FromMinutes(30); ----- - -Plotting these defaults looks as followed: - -[[timeout]] -.Default formula, x-axis time in minutes, y-axis number of attempts to revive -image::{imagesdir}timeoutplot.png[dead timeout] - -The goal here is that whenever a node is resurrected and is found to still be offline, we send it -_back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. - -[source,csharp] ----- -var timeouts = Enumerable.Range(0, 30) - .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) - .ToList(); - -increasedTimeout.Should().BeWithin(maxTimeout); ----- - +:section-number: 4.5 + +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[date-time-providers]] +== Date time providers + +Not typically something you'll have to pass to the client but all calls to `System.DateTime.UtcNow` +in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover +without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. + +[source,csharp] +---- +var dateTimeProvider = DateTimeProvider.Default; +---- + +dates are always returned in UTC + +[source,csharp] +---- +dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); +---- + +Another responsibility of this interface is to calculate the time a node has to be taken out of rotation +based on the number of attempts to revive it. For very advanced use cases, this might be something of interest +to provide a custom implementation for. + +[source,csharp] +---- +var dateTimeProvider = DateTimeProvider.Default; +---- + +The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the +default values for `timeout` and `maxTimeout` are + +[source,csharp] +---- +var timeout = TimeSpan.FromMinutes(1); + +var maxTimeout = TimeSpan.FromMinutes(30); +---- + +Plotting these defaults looks as followed: + +[[timeout]] +.Default formula, x-axis time in minutes, y-axis number of attempts to revive +image::{imagesdir}timeoutplot.png[dead timeout] + +The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. + +[source,csharp] +---- +var timeouts = Enumerable.Range(0, 30) + .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) + .ToList(); + +increasedTimeout.Should().BeWithin(maxTimeout); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index cdbdd3a52f5..3d9fa5746ae 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -21,7 +21,7 @@ node.Uri.Should().NotBeNull(); node.Uri.Port.Should().Be(9200); ---- -By default master eligible and holds data is presumed to be true +By default master eligible and holds data is presumed to be true * [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index cc9b801f8ca..00930feafb5 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -34,10 +34,10 @@ to create it var requestPipelineFactory = new RequestPipelineFactory(); var requestPipeline = requestPipelineFactory.Create( - settings, - DateTimeProvider.Default, //<1> - new MemoryStreamFactory(), - new SearchRequestParameters()); + settings, + DateTimeProvider.Default, <1> + new MemoryStreamFactory(), + new SearchRequestParameters()); requestPipeline.Should().BeOfType(); requestPipeline.GetType().Should().Implement(); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index e3aa170efea..e054b702a20 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -15,27 +15,27 @@ will recover from WebExceptions but others will be grounds for immediately exiti [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall { - { AuditEvent.HealthyResponse, 9200 }, - } + new ClientCall { + { AuditEvent.HealthyResponse, 9200 }, + } ); audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); - e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); - } + new ClientCall { + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); + } ); e.FailureReason.Should().Be(PipelineFailure.Unexpected); e.InnerException.Should().NotBeNull(); @@ -51,28 +51,28 @@ can still see the audit trail for the whole coordinated request. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) + .Nodes(10) #if DOTNETCORE - .ClientCalls(r => r.OnPort(9200).FailAlways(new System.Net.Http.HttpRequestException("recover"))) + .ClientCalls(r => r.OnPort(9200).FailAlways(new System.Net.Http.HttpRequestException("recover"))) #else - .ClientCalls(r => r.OnPort(9200).FailAlways(new WebException("recover"))) + .ClientCalls(r => r.OnPort(9200).FailAlways(new WebException("recover"))) #endif - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.BadResponse, 9200 }, - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); - e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); - } + new ClientCall { + { AuditEvent.BadResponse, 9200 }, + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); + e.InnerException.Should().NotBeNull(); + e.InnerException.Message.Should().Be("boom!"); + } ); e.FailureReason.Should().Be(PipelineFailure.Unexpected); @@ -89,37 +89,37 @@ However the client call on 9201 throws a hard exception we can not recover from [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(r => r.OnPort(9200).FailAlways(new Exception("ping exception"))) - .Ping(r => r.OnPort(9201).SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) - .StaticConnectionPool() - .AllDefaults() + .Nodes(10) + .Ping(r => r.OnPort(9200).FailAlways(new Exception("ping exception"))) + .Ping(r => r.OnPort(9201).SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).FailAlways(new Exception("boom!"))) + .StaticConnectionPool() + .AllDefaults() ); ---- [source,csharp] ---- audit = await audit.TraceUnexpectedException( - new ClientCall { - { AuditEvent.PingFailure, 9200 }, - { AuditEvent.PingSuccess, 9201 }, - { AuditEvent.BadResponse, 9201 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.Unexpected); + new ClientCall { + { AuditEvent.PingFailure, 9200 }, + { AuditEvent.PingSuccess, 9201 }, + { AuditEvent.BadResponse, 9201 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.Unexpected); e.InnerException.Should().NotBeNull(); - e.InnerException.Message.Should().Be("boom!"); + e.InnerException.Message.Should().Be("boom!"); e.SeenExceptions.Should().NotBeEmpty(); - var pipelineException = e.SeenExceptions.First(); - pipelineException.FailureReason.Should().Be(PipelineFailure.PingFailure); - pipelineException.InnerException.Message.Should().Be("ping exception"); + var pipelineException = e.SeenExceptions.First(); + pipelineException.FailureReason.Should().Be(PipelineFailure.PingFailure); + pipelineException.InnerException.Message.Should().Be("ping exception"); var pingException = e.AuditTrail.First(a => a.Event == AuditEvent.PingFailure).Exception; - pingException.Should().NotBeNull(); - pingException.Message.Should().Be("ping exception"); + pingException.Should().NotBeNull(); + pingException.Message.Should().Be("ping exception"); - } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 9fd9afaf691..7b9df3334ef 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -19,8 +19,8 @@ The following are recoverable exceptions ---- var recoverablExceptions = new[] { - new PipelineException(PipelineFailure.BadResponse), - new PipelineException(PipelineFailure.PingFailure), + new PipelineException(PipelineFailure.BadResponse), + new PipelineException(PipelineFailure.PingFailure), }; recoverablExceptions.Should().OnlyContain(e => e.Recoverable); @@ -32,12 +32,12 @@ and the unrecoverable exceptions ---- var unrecoverableExceptions = new[] { - new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), - new PipelineException(PipelineFailure.SniffFailure), - new PipelineException(PipelineFailure.Unexpected), - new PipelineException(PipelineFailure.BadAuthentication), - new PipelineException(PipelineFailure.MaxRetriesReached), - new PipelineException(PipelineFailure.MaxTimeoutReached) + new PipelineException(PipelineFailure.CouldNotStartSniffOnStartup), + new PipelineException(PipelineFailure.SniffFailure), + new PipelineException(PipelineFailure.Unexpected), + new PipelineException(PipelineFailure.BadAuthentication), + new PipelineException(PipelineFailure.MaxRetriesReached), + new PipelineException(PipelineFailure.MaxTimeoutReached) }; unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); @@ -49,11 +49,11 @@ As an example, let's set up a 10 node cluster that will always succeed when ping [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(r => r.SucceedAlways()) - .ClientCalls(r => r.FailAlways(401)) - .StaticConnectionPool() - .AllDefaults() + .Nodes(10) + .Ping(r => r.SucceedAlways()) + .ClientCalls(r => r.FailAlways(401)) + .StaticConnectionPool() + .AllDefaults() ); ---- @@ -63,14 +63,14 @@ followed by a bad response as a result of a bad authentication response [source,csharp] ---- audit = await audit.TraceElasticsearchException( - new ClientCall { - { AuditEvent.PingSuccess, 9200 }, - { AuditEvent.BadResponse, 9200 }, - }, - (e) => - { - e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); - } + new ClientCall { + { AuditEvent.PingSuccess, 9200 }, + { AuditEvent.BadResponse, 9200 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 561641d169c..9186510e22b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -13,17 +13,17 @@ the call to a node throws an exception or returns a 502 or 503 [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } ); ---- @@ -34,18 +34,18 @@ Will be treated as an error that requires retrying [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(502)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.FailAlways(502)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } ); ---- @@ -56,37 +56,37 @@ Will be treated as an error that requires retrying [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(503)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.FailAlways(503)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { HealthyResponse, 9201 }, - } + new ClientCall { + { BadResponse, 9200 }, + { HealthyResponse, 9201 }, + } ); ---- -If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. +If a call returns a valid _for the request*_) http status code other then 502/503. the request won't be retried. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(418)) - .ClientCalls(r => r.OnPort(9201).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.FailAlways(418)) + .ClientCalls(r => r.OnPort(9201).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - } + new ClientCall { + { BadResponse, 9200 }, + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index 7a0f8d2d9b1..ae988a04eb7 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -4,153 +4,155 @@ :imagesdir: ../../../images/ -[[max-retries]] - [[max-retries]] == Max Retries -By default retry as many times as we have nodes. However retries still respect the request timeout. -Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can -but give up after 20 seconds +By default, NEST will retry as many times as there are nodes in the cluster that the client knows about. +Retries still respects the request timeout however, +meaning if you have a 100 node cluster and a request timeout of 20 seconds, +the client will retry as many times as it before giving up at the request timeout of 20 seconds. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { BadResponse, 9205 }, - { BadResponse, 9206 }, - { BadResponse, 9207 }, - { BadResponse, 9208 }, - { HealthyResponse, 9209 } - } + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 } + } ); ---- -When you have a 100 node cluster you might want to ensure a fixed number of retries. -Remember that the actual number of requests is initial attempt + set number of retries +When you have a 100 node cluster, you might want to ensure a fixed number of retries. + +IMPORTANT: the actual number of requests is **initial attempt + set number of retries** [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(3)) + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(3)) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { MaxRetriesReached } - } + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { MaxRetriesReached } + } ); ---- -In our previous test we simulated very fast failures, in the real world a call might take upwards of a second -Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. -In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted +In our previous test we simulated very fast failures, but in the real world a call might take upwards of a second. +In this next example, we simulate a particular heavy search that takes 10 seconds to fail, and set a request timeout of 20 seconds. +We see that the request is tried twice and gives up before a third call is attempted, since the call takes 10 seconds and thus can be +tried twice (initial call and one retry) before the request timeout. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxTimeoutReached } - } + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxTimeoutReached } + } ); ---- -If you set smaller request time outs you might not want it to also affect the retry timeout, therefor you can configure these separately too. -Here we simulate calls taking 3 seconds, a request time out of 2 and an overall retry timeout of 10 seconds. -We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 -wins over the configured request timeout +If you set a smaller request timeout you might not want it to also affect the retry timeout. +In cases like this, you can configure the `MaxRetryTimeout` separately. +Here we simulate calls taking 3 seconds, a request timeout of 2 seconds and a max retry timeout of 10 seconds. +We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that +our max retry timeout of 10 seconds wins over the configured request timeout [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).FailAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { MaxTimeoutReached } - } + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { MaxTimeoutReached } + } ); ---- -If your retry policy expands beyond available nodes we won't retry the same node twice +If your retry policy expands beyond the number of available nodes, the client **won't** retry the same node twice [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(2) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) + .Nodes(2) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(2)).MaxRetryTimeout(TimeSpan.FromSeconds(10))) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxRetriesReached } - } + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxRetriesReached } + } ); ---- -This makes setting any retry setting on a single node connection pool a NOOP, this is by design! -Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and -not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. +This makes setting any retry setting on a single node connection pool a no-op by design! +Connection pooling and failover is all about trying to fail sanely whilst still utilizing the available resources and +not giving up on the fail fast principle; **It is NOT a mechanism for forcing requests to succeed.** [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .SingleNodeConnection() - .Settings(s => s.DisablePing().MaximumRetries(10)) + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .SingleNodeConnection() + .Settings(s => s.DisablePing().MaximumRetries(10)) ); audit = await audit.TraceCall( - new ClientCall { - { BadResponse, 9200 } - } + new ClientCall { + { BadResponse, 9200 } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index 81c7ba17c33..2b1e5071f14 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -18,11 +18,11 @@ A cluster with 2 nodes where the second node fails on ping [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(2) - .Ping(p => p.Succeeds(Always)) - .Ping(p => p.OnPort(9201).FailAlways()) - .StaticConnectionPool() - .AllDefaults() + .Nodes(2) + .Ping(p => p.Succeeds(Always)) + .Ping(p => p.OnPort(9201).FailAlways()) + .StaticConnectionPool() + .AllDefaults() ); ---- @@ -37,18 +37,18 @@ Finally we assert that the connectionpool has one node that is marked as dead ---- await audit.TraceCalls( new ClientCall { - { PingSuccess, 9200}, - { HealthyResponse, 9200}, - { pool => - { - pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); - } } - }, + { PingSuccess, 9200}, + { HealthyResponse, 9200}, + { pool => + { + pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); + } } + }, new ClientCall { - { PingFailure, 9201}, - { HealthyResponse, 9200}, + { PingFailure, 9201}, + { HealthyResponse, 9200}, { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - } + } ); ---- @@ -57,12 +57,12 @@ A cluster with 4 nodes where the second and third pings fail [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .Ping(p => p.SucceedAlways()) - .Ping(p => p.OnPort(9201).FailAlways()) - .Ping(p => p.OnPort(9202).FailAlways()) - .StaticConnectionPool() - .AllDefaults() + .Nodes(4) + .Ping(p => p.SucceedAlways()) + .Ping(p => p.OnPort(9201).FailAlways()) + .Ping(p => p.OnPort(9202).FailAlways()) + .StaticConnectionPool() + .AllDefaults() ); ---- @@ -78,20 +78,20 @@ Finally we assert that the connectionpool has two nodes that are marked as dead ---- await audit.TraceCalls( new ClientCall { - { PingSuccess, 9200}, - { HealthyResponse, 9200}, - { pool => - { - pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); - } } - }, + { PingSuccess, 9200}, + { HealthyResponse, 9200}, + { pool => + { + pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); + } } + }, new ClientCall { - { PingFailure, 9201}, - { PingFailure, 9202}, - { PingSuccess, 9203}, - { HealthyResponse, 9203}, + { PingFailure, 9201}, + { PingFailure, 9202}, + { PingSuccess, 9203}, + { HealthyResponse, 9203}, { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - } + } ); ---- @@ -100,22 +100,22 @@ new ClientCall { [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .Ping(p => p.SucceedAlways()) - .StaticConnectionPool() - .AllDefaults() + .Nodes(4) + .Ping(p => p.SucceedAlways()) + .StaticConnectionPool() + .AllDefaults() ); await audit.TraceCalls( - new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }, - new ClientCall { { PingSuccess, 9201}, { HealthyResponse, 9201} }, - new ClientCall { { PingSuccess, 9202}, { HealthyResponse, 9202} }, - new ClientCall { { PingSuccess, 9203}, { HealthyResponse, 9203} }, - new ClientCall { { HealthyResponse, 9200} }, - new ClientCall { { HealthyResponse, 9201} }, - new ClientCall { { HealthyResponse, 9202} }, - new ClientCall { { HealthyResponse, 9203} }, - new ClientCall { { HealthyResponse, 9200} } + new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200} }, + new ClientCall { { PingSuccess, 9201}, { HealthyResponse, 9201} }, + new ClientCall { { PingSuccess, 9202}, { HealthyResponse, 9202} }, + new ClientCall { { PingSuccess, 9203}, { HealthyResponse, 9203} }, + new ClientCall { { HealthyResponse, 9200} }, + new ClientCall { { HealthyResponse, 9201} }, + new ClientCall { { HealthyResponse, 9202} }, + new ClientCall { { HealthyResponse, 9203} }, + new ClientCall { { HealthyResponse, 9200} } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 6e2ebf8cad7..67440272733 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -15,43 +15,43 @@ before the actual call to make sure its up and running. If its still down we put [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(3) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9202).Fails(Once)) - .Ping(p => p.SucceedAlways()) - .StaticConnectionPool() - .AllDefaults() + .Nodes(3) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9202).Fails(Once)) + .Ping(p => p.SucceedAlways()) + .StaticConnectionPool() + .AllDefaults() ); audit = await audit.TraceCalls( - new ClientCall { { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, - new ClientCall { { PingSuccess, 9201 }, { HealthyResponse, 9201 } }, - new ClientCall { - { PingSuccess, 9202}, - { BadResponse, 9202}, - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.First(n=>!n.IsAlive).DeadUntil.Should().BeAfter(DateTime.UtcNow) } - } + new ClientCall { { PingSuccess, 9200 }, { HealthyResponse, 9200 } }, + new ClientCall { { PingSuccess, 9201 }, { HealthyResponse, 9201 } }, + new ClientCall { + { PingSuccess, 9202}, + { BadResponse, 9202}, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.First(n=>!n.IsAlive).DeadUntil.Should().BeAfter(DateTime.UtcNow) } + } ); audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } } + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } } ); audit.ChangeTime(d => d.AddMinutes(20)); audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { - { Resurrection, 9202 }, - { PingSuccess, 9202 }, - { HealthyResponse, 9202 } - } + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { + { Resurrection, 9202 }, + { PingSuccess, 9202 }, + { HealthyResponse, 9202 } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 8798c5e75d2..5e2bd823275 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -20,10 +20,10 @@ Let's set up the cluster and configure clients to **always** sniff on startup [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) //<1> + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) <1> ); ---- <1> sniff on startup @@ -38,24 +38,24 @@ And after that no sniff on startup will happen again [source,csharp] ---- audit = await audit.TraceCalls( -new ClientCall(r => r.DisableSniffing()) //<1> - { - { PingSuccess, 9200 }, //<2> - { HealthyResponse, 9200 } - }, +new ClientCall(r => r.DisableSniffing()) <1> + { + { PingSuccess, 9200 }, <2> + { HealthyResponse, 9200 } + }, new ClientCall() - { - { SniffOnStartup }, //<3> - { SniffSuccess, 9200 }, - { PingSuccess, 9200 }, - { HealthyResponse, 9200 } - }, + { + { SniffOnStartup }, <3> + { SniffSuccess, 9200 }, + { PingSuccess, 9200 }, + { HealthyResponse, 9200 } + }, new ClientCall() - { - { PingSuccess, 9201 }, - { HealthyResponse, 9201 } - } - ); + { + { PingSuccess, 9201 }, + { HealthyResponse, 9201 } + } +); ---- <1> disable sniffing @@ -68,19 +68,19 @@ Now, let's disable pinging on the request [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) ); audit = await audit.TraceCall( - new ClientCall(r => r.DisablePing()) //<1> - { - { SniffOnStartup }, - { SniffSuccess, 9200 }, //<2> - { HealthyResponse, 9200 } - } - ); + new ClientCall(r => r.DisablePing()) <1> + { + { SniffOnStartup }, + { SniffSuccess, 9200 }, <2> + { HealthyResponse, 9200 } + } +); ---- <1> disable ping @@ -91,18 +91,18 @@ Finally, let's demonstrate disabling both sniff and ping on the request [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup()) + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup()) ); audit = await audit.TraceCall( - new ClientCall(r=>r.DisableSniffing().DisablePing()) //<1> - { - { HealthyResponse, 9200 } //<2> - } - ); + new ClientCall(r=>r.DisableSniffing().DisablePing()) <1> + { + { HealthyResponse, 9200 } <2> + } +); ---- <1> diable ping and sniff diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index c5c5027f09e..43f35f438c2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -18,11 +18,11 @@ before the max request time out kills the client call. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(10))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().RequestTimeout(TimeSpan.FromSeconds(20))) ); ---- @@ -32,21 +32,21 @@ We should now see more nodes being tried. [source,csharp] ---- audit = await audit.TraceCalls( - new ClientCall { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { MaxTimeoutReached } - }, + new ClientCall { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { MaxTimeoutReached } + }, new ClientCall(r => r.RequestTimeout(TimeSpan.FromSeconds(80))) - { - { BadResponse, 9203 }, - { BadResponse, 9204 }, - { BadResponse, 9205 }, - { BadResponse, 9206 }, - { BadResponse, 9207 }, - { BadResponse, 9208 }, - { HealthyResponse, 9209 }, - } + { + { BadResponse, 9203 }, + { BadResponse, 9204 }, + { BadResponse, 9205 }, + { BadResponse, 9206 }, + { BadResponse, 9207 }, + { BadResponse, 9208 }, + { HealthyResponse, 9209 }, + } ); ---- @@ -63,11 +63,11 @@ before the max request time out kills the client call. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) - .ClientCalls(r => r.SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) + .Nodes(10) + .Ping(p => p.SucceedAlways().Takes(TimeSpan.FromSeconds(20))) + .ClientCalls(r => r.SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.RequestTimeout(TimeSpan.FromSeconds(10)).PingTimeout(TimeSpan.FromSeconds(10))) ); ---- @@ -81,18 +81,18 @@ We should now see more nodes being tried before the request timeout is hit. ---- audit = await audit.TraceCalls( new ClientCall { - { PingFailure, 9200 }, - { MaxTimeoutReached } - }, + { PingFailure, 9200 }, + { MaxTimeoutReached } + }, new ClientCall(r => r.PingTimeout(TimeSpan.FromSeconds(2))) - { - { PingFailure, 9202 }, - { PingFailure, 9203 }, - { PingFailure, 9204 }, - { PingFailure, 9205 }, - { PingFailure, 9206 }, - { MaxTimeoutReached } - } + { + { PingFailure, 9202 }, + { PingFailure, 9203 }, + { PingFailure, 9204 }, + { PingFailure, 9205 }, + { PingFailure, 9206 }, + { MaxTimeoutReached } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index c39f1d86f26..7fbf81a9fed 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -12,18 +12,18 @@ [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways(400)) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(0)) + .Nodes(10) + .ClientCalls(r => r.FailAlways(400)) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(0)) ); audit = await audit.TraceCalls( - new ClientCall() { - { BadResponse, 9200 } - }, - new ClientCall(r => r.AllowedStatusCodes(400)) { - { HealthyResponse, 9201 } - } + new ClientCall() { + { BadResponse, 9200 } + }, + new ClientCall(r => r.AllowedStatusCodes(400)) { + { HealthyResponse, 9201 } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 7782fd6d3fe..8349ebbef31 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -15,16 +15,16 @@ request configuration. This will ignore the pool and not retry. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9208).FailAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9208).FailAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { - { BadResponse, 9208 } - } + new ClientCall(r => r.ForceNode(new Uri("http://localhost:9208"))) { + { BadResponse, 9208 } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index bcc4d11fc95..15ad8ed5a77 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -16,19 +16,19 @@ but give up after 20 seconds [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing()) + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing()) ); audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(2)) { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { MaxRetriesReached } - } + new ClientCall(r => r.MaxRetries(2)) { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { MaxRetriesReached } + } ); ---- @@ -38,20 +38,20 @@ Remember that the actual number of requests is initial attempt + set number of r [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways()) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .StaticConnectionPool() - .Settings(s => s.DisablePing().MaximumRetries(5)) + .Nodes(10) + .ClientCalls(r => r.FailAlways()) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .StaticConnectionPool() + .Settings(s => s.DisablePing().MaximumRetries(5)) ); audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(2)) { - { BadResponse, 9200 }, - { BadResponse, 9201 }, - { BadResponse, 9202 }, - { MaxRetriesReached } - } + new ClientCall(r => r.MaxRetries(2)) { + { BadResponse, 9200 }, + { BadResponse, 9201 }, + { BadResponse, 9202 }, + { MaxRetriesReached } + } ); ---- @@ -62,17 +62,17 @@ not giving up on the fail fast principle. It's *NOT* a mechanism for forcing req [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) - .ClientCalls(r => r.OnPort(9209).SucceedAlways()) - .SingleNodeConnection() - .Settings(s => s.DisablePing().MaximumRetries(10)) + .Nodes(10) + .ClientCalls(r => r.FailAlways().Takes(TimeSpan.FromSeconds(3))) + .ClientCalls(r => r.OnPort(9209).SucceedAlways()) + .SingleNodeConnection() + .Settings(s => s.DisablePing().MaximumRetries(10)) ); audit = await audit.TraceCall( - new ClientCall(r => r.MaxRetries(10)) { - { BadResponse, 9200 } - } + new ClientCall(r => r.MaxRetries(10)) { + { BadResponse, 9200 } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index 7be7bfbafc2..b0a11d96e03 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -36,9 +36,9 @@ e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. [source,csharp] ---- var startingPositions = Enumerable.Range(0, NumberOfNodes) - .Select(i => pool.CreateView().First()) - .Select(n => n.Uri.Port) - .ToList(); + .Select(i => pool.CreateView().First()) + .Select(n => n.Uri.Port) + .ToList(); var expectedOrder = Enumerable.Range(9200, NumberOfNodes); @@ -60,8 +60,8 @@ comes 9200 again var threadedStartPositions = new ConcurrentBag(); var threads = Enumerable.Range(0, 20) - .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) - .ToList(); + .Select(i => CreateThreadCallingGetNext(pool, threadedStartPositions)) + .ToList(); t.Start(); diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 5c57399a370..e04b858a954 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -108,12 +108,12 @@ A cluster with 2 nodes where the second node fails on ping [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .ClientCalls(p => p.Succeeds(Always)) - .ClientCalls(p => p.OnPort(9201).FailAlways()) - .ClientCalls(p => p.OnPort(9203).FailAlways()) - .StaticConnectionPool() - .Settings(p=>p.DisablePing()) + .Nodes(4) + .ClientCalls(p => p.Succeeds(Always)) + .ClientCalls(p => p.OnPort(9201).FailAlways()) + .ClientCalls(p => p.OnPort(9203).FailAlways()) + .StaticConnectionPool() + .Settings(p=>p.DisablePing()) ); ---- @@ -130,35 +130,35 @@ The next call goes to 9203 which fails so we should wrap over ---- await audit.TraceCalls( new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0) } - }, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0) } + }, new ClientCall { - { BadResponse, 9201}, - { HealthyResponse, 9202}, + { BadResponse, 9201}, + { HealthyResponse, 9202}, { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } - }, + }, new ClientCall { - { BadResponse, 9203}, - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - }, - new ClientCall { - { HealthyResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } - } + { BadResponse, 9203}, + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + } ); ---- @@ -167,10 +167,10 @@ A cluster with 2 nodes where the second node fails on ping [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(4) - .ClientCalls(p => p.Fails(Always)) - .StaticConnectionPool() - .Settings(p=>p.DisablePing()) + .Nodes(4) + .ClientCalls(p => p.Fails(Always)) + .StaticConnectionPool() + .Settings(p=>p.DisablePing()) ); ---- @@ -184,37 +184,37 @@ nodes ---- await audit.TraceCalls( new ClientCall { - { BadResponse, 9200}, - { BadResponse, 9201}, - { BadResponse, 9202}, - { BadResponse, 9203}, - { MaxRetriesReached }, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, + { BadResponse, 9200}, + { BadResponse, 9201}, + { BadResponse, 9202}, + { BadResponse, 9203}, + { MaxRetriesReached }, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, new ClientCall { - { AllNodesDead }, - { Resurrection, 9201}, - { BadResponse, 9201}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9202}, - { BadResponse, 9202}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9203}, - { BadResponse, 9203}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - }, - new ClientCall { - { AllNodesDead }, - { Resurrection, 9200}, - { BadResponse, 9200}, - { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } - } + { AllNodesDead }, + { Resurrection, 9201}, + { BadResponse, 9201}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9202}, + { BadResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9203}, + { BadResponse, 9203}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9200}, + { BadResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index 3572aae23db..aba5be664b3 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -29,8 +29,8 @@ callSniffing.ShouldNotThrow(); [source,csharp] ---- var threads = Enumerable.Range(0, 50) - .Select(i => CreateReadAndUpdateThread(pool)) - .ToList(); + .Select(i => CreateReadAndUpdateThread(pool)) + .ToList(); t.Start(); diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index 166e8cffad1..ba017205415 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -29,23 +29,23 @@ longer fails but looks completely different (9210-9212) we should be able to han [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(5) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .ClientCalls(r => r.OnPort(9201).Fails(Once)) + .Nodes(5) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .ClientCalls(r => r.OnPort(9201).Fails(Once)) .Sniff(p => p.SucceedAlways(Framework.Cluster - .Nodes(3) - .MasterEligible(9200, 9202) - .ClientCalls(r => r.OnPort(9201).Fails(Once)) + .Nodes(3) + .MasterEligible(9200, 9202) + .ClientCalls(r => r.OnPort(9201).Fails(Once)) .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(3, 9210) - .MasterEligible(9210, 9212) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s.DisablePing().SniffOnStartup(false)) + .Nodes(3, 9210) + .MasterEligible(9210, 9212) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s.DisablePing().SniffOnStartup(false)) ); ---- @@ -59,32 +59,32 @@ We assert we do a sniff on the first master node in our updated cluster ---- audit = await audit.TraceCalls( new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(5) } - }, - new ClientCall { - { BadResponse, 9201}, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(5) } + }, + new ClientCall { + { BadResponse, 9201}, { SniffOnFail }, - { SniffSuccess, 9202}, - { HealthyResponse, 9200}, + { SniffSuccess, 9202}, + { HealthyResponse, 9200}, { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { - { BadResponse, 9201}, + }, + new ClientCall { + { BadResponse, 9201}, { SniffOnFail }, - { SniffSuccess, 9200}, - { HealthyResponse, 9210}, - { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } } + { SniffSuccess, 9200}, + { HealthyResponse, 9210}, + { pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } }, + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } } ); ---- @@ -94,22 +94,22 @@ Only we enable pinging (default is true) and make the ping fail [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(5) - .MasterEligible(9202, 9203, 9204) - .Ping(r => r.OnPort(9201).Fails(Once)) - .Sniff(p => p.SucceedAlways(Framework.Cluster - .Nodes(3) - .MasterEligible(9200, 9202) - .Ping(r => r.OnPort(9201).Fails(Once)) - .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(3, 9210) - .MasterEligible(9210, 9211) - .Ping(r => r.SucceedAlways()) - .Sniff(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s.SniffOnStartup(false)) + .Nodes(5) + .MasterEligible(9202, 9203, 9204) + .Ping(r => r.OnPort(9201).Fails(Once)) + .Sniff(p => p.SucceedAlways(Framework.Cluster + .Nodes(3) + .MasterEligible(9200, 9202) + .Ping(r => r.OnPort(9201).Fails(Once)) + .Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(3, 9210) + .MasterEligible(9210, 9211) + .Ping(r => r.SucceedAlways()) + .Sniff(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s.SniffOnStartup(false)) ); ---- @@ -124,33 +124,33 @@ We assert we do a sniff on the first master node in our updated cluster [source,csharp] ---- audit = await audit.TraceCalls( - new ClientCall { - { PingSuccess, 9200 }, - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(5) } - }, - new ClientCall { - { PingFailure, 9201}, + new ClientCall { + { PingSuccess, 9200 }, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(5) } + }, + new ClientCall { + { PingFailure, 9201}, { SniffOnFail }, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200}, + { SniffSuccess, 9202}, + { PingSuccess, 9200}, + { HealthyResponse, 9200}, { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { - { PingFailure, 9201}, + }, + new ClientCall { + { PingFailure, 9201}, { SniffOnFail }, - { SniffSuccess, 9200}, - { PingSuccess, 9210}, - { HealthyResponse, 9210}, - { pool => pool.Nodes.Count.Should().Be(3) } - }, - new ClientCall { { PingSuccess, 9211 }, { HealthyResponse, 9211 } }, - new ClientCall { { PingSuccess, 9212 }, { HealthyResponse, 9212 } }, + { SniffSuccess, 9200}, + { PingSuccess, 9210}, + { HealthyResponse, 9210}, + { pool => pool.Nodes.Count.Should().Be(3) } + }, + new ClientCall { { PingSuccess, 9211 }, { HealthyResponse, 9211 } }, + new ClientCall { { PingSuccess, 9212 }, { HealthyResponse, 9212 } }, new ClientCall { { HealthyResponse, 9210 } }, - new ClientCall { { HealthyResponse, 9211 } }, - new ClientCall { { HealthyResponse, 9212 } }, - new ClientCall { { HealthyResponse, 9210 } } + new ClientCall { { HealthyResponse, 9211 } }, + new ClientCall { { HealthyResponse, 9212 } }, + new ClientCall { { HealthyResponse, 9210 } } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index 34cdbf24300..f9893d493c1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -17,26 +17,26 @@ but without sniffing periodically it will never find the nodes that have been ad [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(s => s.SucceedAlways(Framework.Cluster - .Nodes(100) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - .Sniff(ss => ss.SucceedAlways(Framework.Cluster - .Nodes(10) - .MasterEligible(9202, 9203, 9204) - .ClientCalls(r => r.SucceedAlways()) - )) - )) - .SniffingConnectionPool() - .Settings(s => s - .DisablePing() - .SniffOnConnectionFault(false) - .SniffOnStartup(false) - .SniffLifeSpan(TimeSpan.FromMinutes(30)) - ) + .Nodes(10) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(s => s.SucceedAlways(Framework.Cluster + .Nodes(100) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + .Sniff(ss => ss.SucceedAlways(Framework.Cluster + .Nodes(10) + .MasterEligible(9202, 9203, 9204) + .ClientCalls(r => r.SucceedAlways()) + )) + )) + .SniffingConnectionPool() + .Settings(s => s + .DisablePing() + .SniffOnConnectionFault(false) + .SniffOnStartup(false) + .SniffLifeSpan(TimeSpan.FromMinutes(30)) + ) ); ---- @@ -45,20 +45,20 @@ healty cluster all nodes return healthy responses [source,csharp] ---- audit = await audit.TraceCalls( - new ClientCall { { HealthyResponse, 9200 } }, - new ClientCall { { HealthyResponse, 9201 } }, - new ClientCall { { HealthyResponse, 9202 } }, - new ClientCall { { HealthyResponse, 9203 } }, - new ClientCall { { HealthyResponse, 9204 } }, - new ClientCall { { HealthyResponse, 9205 } }, - new ClientCall { { HealthyResponse, 9206 } }, - new ClientCall { { HealthyResponse, 9207 } }, - new ClientCall { { HealthyResponse, 9208 } }, - new ClientCall { { HealthyResponse, 9209 } }, - new ClientCall { - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(10) } - } + new ClientCall { { HealthyResponse, 9200 } }, + new ClientCall { { HealthyResponse, 9201 } }, + new ClientCall { { HealthyResponse, 9202 } }, + new ClientCall { { HealthyResponse, 9203 } }, + new ClientCall { { HealthyResponse, 9204 } }, + new ClientCall { { HealthyResponse, 9205 } }, + new ClientCall { { HealthyResponse, 9206 } }, + new ClientCall { { HealthyResponse, 9207 } }, + new ClientCall { { HealthyResponse, 9208 } }, + new ClientCall { { HealthyResponse, 9209 } }, + new ClientCall { + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(10) } + } ); ---- @@ -75,12 +75,12 @@ a sniff is done first and it prefers the first node master node [source,csharp] ---- audit = await audit.TraceCalls( - new ClientCall { + new ClientCall { { SniffOnStaleCluster }, - { SniffSuccess, 9202 }, - { HealthyResponse, 9201 }, - { pool => pool.Nodes.Count.Should().Be(100) } - } + { SniffSuccess, 9202 }, + { HealthyResponse, 9201 }, + { pool => pool.Nodes.Count.Should().Be(100) } + } ); audit.ChangeTime(d => d.AddMinutes(31)); @@ -91,12 +91,12 @@ a sniff is done first and it prefers the first node master node [source,csharp] ---- audit = await audit.TraceCalls( - new ClientCall { + new ClientCall { { SniffOnStaleCluster }, - { SniffSuccess, 9202 }, - { HealthyResponse, 9200 }, - { pool => pool.Nodes.Count.Should().Be(10) } - } + { SniffSuccess, 9202 }, + { HealthyResponse, 9200 }, + { pool => pool.Nodes.Count.Should().Be(10) } + } ); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index b8afe226e06..07cdd01401d 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -14,140 +14,140 @@ Connection pools that return true for `SupportsReseeding` by default sniff on st [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() ); await audit.TraceCalls( - new ClientCall - { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} - }, - new ClientCall - { - { PingSuccess, 9201}, - { HealthyResponse, 9201} - } + new ClientCall + { + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} + }, + new ClientCall + { + { PingSuccess, 9201}, + { HealthyResponse, 9201} + } ); ---- [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always, Framework.Cluster.Nodes(8, startFrom: 9204))) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always, Framework.Cluster.Nodes(8, startFrom: 9204))) + .SniffingConnectionPool() + .AllDefaults() ); await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess, 9204}, - { HealthyResponse, 9204} -}); +{ SniffOnStartup}, +{ SniffFailure, 9200}, +{ SniffFailure, 9201}, +{ SniffSuccess, 9202}, +{ PingSuccess, 9204}, +{ HealthyResponse, 9204} + }); ---- [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9209).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9209).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() ); await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffFailure, 9202}, - { SniffFailure, 9203}, - { SniffFailure, 9204}, - { SniffFailure, 9205}, - { SniffFailure, 9206}, - { SniffFailure, 9207}, - { SniffFailure, 9208}, - { SniffSuccess, 9209}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} -}); +{ SniffOnStartup}, +{ SniffFailure, 9200}, +{ SniffFailure, 9201}, +{ SniffFailure, 9202}, +{ SniffFailure, 9203}, +{ SniffFailure, 9204}, +{ SniffFailure, 9205}, +{ SniffFailure, 9206}, +{ SniffFailure, 9207}, +{ SniffFailure, 9208}, +{ SniffSuccess, 9209}, +{ PingSuccess, 9200}, +{ HealthyResponse, 9200} + }); ---- [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(new[] { - new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, - new Node(new Uri("http://localhost:9201")) { MasterEligible = false }, - new Node(new Uri("http://localhost:9202")) { MasterEligible = true }, - }) - .Sniff(s => s.Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(new[] { + new Node(new Uri("http://localhost:9200")) { MasterEligible = false }, + new Node(new Uri("http://localhost:9201")) { MasterEligible = false }, + new Node(new Uri("http://localhost:9202")) { MasterEligible = true }, + }) + .Sniff(s => s.Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() ); await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} -}); +{ SniffOnStartup}, +{ SniffSuccess, 9202}, +{ PingSuccess, 9200}, +{ HealthyResponse, 9200} + }); ---- [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(new[] { - new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, - new Node(new Uri("http://localhost:9201")) { MasterEligible = true }, - new Node(new Uri("http://localhost:9202")) { MasterEligible = false }, - }) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(new[] { + new Node(new Uri("http://localhost:9200")) { MasterEligible = true }, + new Node(new Uri("http://localhost:9201")) { MasterEligible = true }, + new Node(new Uri("http://localhost:9202")) { MasterEligible = false }, + }) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() ); await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess, 9200}, - { HealthyResponse, 9200} -}); +{ SniffOnStartup}, +{ SniffFailure, 9200}, +{ SniffFailure, 9201}, +{ SniffSuccess, 9202}, +{ PingSuccess, 9200}, +{ HealthyResponse, 9200} + }); ---- [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202).Succeeds(Always)) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202).Succeeds(Always)) + .SniffingConnectionPool() + .AllDefaults() ); await audit.TraceCall(new ClientCall { - { SniffOnStartup}, - { SniffFailure, 9200}, - { SniffFailure, 9201}, - { SniffSuccess, 9202}, - { PingSuccess , 9200}, - { HealthyResponse, 9200} + { SniffOnStartup}, + { SniffFailure, 9200}, + { SniffFailure, 9201}, + { SniffSuccess, 9202}, + { PingSuccess , 9200}, + { HealthyResponse, 9200} }); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index 94bb0bfd3ba..c676e67fa36 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -15,28 +15,28 @@ We use this information when selecting a node to perform an API call on. [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202) - .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202)) - ) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202) + .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202)) + ) + .SniffingConnectionPool() + .AllDefaults() ) { - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); - }, - - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); - } + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); + }, + + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); + } }; await audit.TraceStartup(); @@ -45,29 +45,29 @@ await audit.TraceStartup(); [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.SucceedAlways() - .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202).SniffShouldReturnFqdn()) - ) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.SucceedAlways() + .Succeeds(Always, Framework.Cluster.Nodes(8).StoresNoData(9200, 9201, 9202).SniffShouldReturnFqdn()) + ) + .SniffingConnectionPool() + .AllDefaults() ) { - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); - pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); - }, - - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); - pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); - } + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(10); + pool.Nodes.Should().OnlyContain(n => n.Uri.Host == "localhost"); + }, + + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); + pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Host.Contains("/")); + } }; await audit.TraceStartup(); @@ -105,10 +105,10 @@ await pipeline.SniffAsync(); [source,csharp] ---- this._settings = - this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; + this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; var pipeline = new RequestPipeline(this._settings, DateTimeProvider.Default, new MemoryStreamFactory(), - new SearchRequestParameters()); + new SearchRequestParameters()); ---- [source,csharp] @@ -123,27 +123,27 @@ var node = nodes.First(); [source,csharp] ---- var audit = new Auditor(() => Framework.Cluster - .Nodes(10) - .Sniff(s => s.Fails(Always)) - .Sniff(s => s.OnPort(9202) - .Succeeds(Always, Framework.Cluster.Nodes(8).MasterEligible(9200, 9201, 9202)) - ) - .SniffingConnectionPool() - .AllDefaults() + .Nodes(10) + .Sniff(s => s.Fails(Always)) + .Sniff(s => s.OnPort(9202) + .Succeeds(Always, Framework.Cluster.Nodes(8).MasterEligible(9200, 9201, 9202)) + ) + .SniffingConnectionPool() + .AllDefaults() ) { - AssertPoolBeforeCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(10); - pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); - }, - AssertPoolAfterCall = (pool) => - { - pool.Should().NotBeNull(); - pool.Nodes.Should().HaveCount(8); - pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); - } + AssertPoolBeforeCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(10); + pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(10); + }, + AssertPoolAfterCall = (pool) => + { + pool.Should().NotBeNull(); + pool.Nodes.Should().HaveCount(8); + pool.Nodes.Where(n => n.MasterEligible).Should().HaveCount(3); + } }; await audit.TraceStartup(); ---- diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index 62b1d148400..383eca9f0b9 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -1,263 +1,262 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images/ - -[[covariant-search-results]] -== Covariant Search Results - -NEST directly supports returning covariant result sets. -Meaning a result can be typed to an interface or base class -but the actual instance type of the result can be that of the subclass directly - -Let's look at an example; Imagine we want to search over multiple types that all implement -`ISearchResult` - -[source,csharp] ----- -public interface ISearchResult -{ - string Name { get; set; } -} ----- - -We have three implementations of `ISearchResult` namely `A`, `B` and `C` - -[source,csharp] ----- -public class A : ISearchResult -{ - public string Name { get; set; } - public int PropertyOnA { get; set; } -} - -public class B : ISearchResult -{ - public string Name { get; set; } - public int PropertyOnB { get; set; } -} - -public class C : ISearchResult -{ - public string Name { get; set; } - public int PropertyOnC { get; set; } -} ----- - -=== Using Types - -The most straightforward way to search over multiple types is to -type the response to the parent interface or base class -and pass the actual types we want to search over using `.Type()` - -[source,csharp] ----- -var result = this._client.Search(s => s - .Type(Types.Type(typeof(A), typeof(B), typeof(C))) - .Size(100) -); ----- - -NEST will translate this to a search over `/index/a,b,c/_search`; -hits that have "_type" : "a` will be serialized to `A` and so forth - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - -[source,csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source,csharp] ----- -var aDocuments = result.Documents.OfType
(); - -var bDocuments = result.Documents.OfType(); -var cDocuments = result.Documents.OfType(); -aDocuments.Count().Should().Be(25); -bDocuments.Count().Should().Be(25); -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - -[source,csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- - -=== Using ConcreteTypeSelector - -A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to - -[source,csharp] ----- -var result = this._client.Search(s => s - .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) - .Size(100) -); ----- - -here for each hit we'll call the delegate passed to ConcreteTypeSelector where - -* `d` is a representation of the `_source` exposed as a `dynamic` type - -* a typed `h` which represents the encapsulating hit of the source i.e. `Hit` - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - -[source,csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source,csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); - -var cDocuments = result.Documents.OfType(); - -aDocuments.Count().Should().Be(25); - -bDocuments.Count().Should().Be(25); - -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - -[source,csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); - -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- - -Scroll also supports CovariantSearchResponses - -The Scroll API is a continuation of the previous Search example so Types() are lost. -You can hint at the types using `.CovariantTypes()` - -[source,csharp] ----- -var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s - .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) -); ----- - -NEST will translate this to a search over `/index/a,b,c/_search`; -hits that have "_type" : "a` will be serialized to `A` and so forth - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - -[source,csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source,csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); - -var cDocuments = result.Documents.OfType(); - -aDocuments.Count().Should().Be(25); - -bDocuments.Count().Should().Be(25); - -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - -[source,csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); - -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- - -The more low level concrete type selector can also be specified on scroll - -[source,csharp] ----- -var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s - .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) -); ----- - -As before, within the delegate passed to `.ConcreteTypeSelector` - -* `d` is the `_source` typed as `dynamic` - -* `h` is the encapsulating typed hit - -Here we assume our response is valid and that we received the 100 documents -we are expecting. Remember `result.Documents` is an `IEnumerable` - -[source,csharp] ----- -result.IsValid.Should().BeTrue(); - -result.Documents.Count().Should().Be(100); ----- - -To prove the returned result set is covariant we filter the documents based on their -actual type and assert the returned subsets are the expected sizes - -[source,csharp] ----- -var aDocuments = result.Documents.OfType(); - -var bDocuments = result.Documents.OfType(); - -var cDocuments = result.Documents.OfType(); - -aDocuments.Count().Should().Be(25); - -bDocuments.Count().Should().Be(25); - -cDocuments.Count().Should().Be(50); ----- - -and assume that properties that only exist on the subclass itself are properly filled - -[source,csharp] ----- -aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); - -bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); - -cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); ----- - +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[covariant-search-results]] +== Covariant Search Results + +NEST directly supports returning covariant result sets. +Meaning a result can be typed to an interface or base class +but the actual instance type of the result can be that of the subclass directly + +Let's look at an example; Imagine we want to search over multiple types that all implement `ISearchResult` + +[source,csharp] +---- +public interface ISearchResult +{ + string Name { get; set; } +} +---- + +We have three implementations of `ISearchResult` namely `A`, `B` and `C` + +[source,csharp] +---- +public class A : ISearchResult +{ + public string Name { get; set; } + public int PropertyOnA { get; set; } +} + +public class B : ISearchResult +{ + public string Name { get; set; } + public int PropertyOnB { get; set; } +} + +public class C : ISearchResult +{ + public string Name { get; set; } + public int PropertyOnC { get; set; } +} +---- + +=== Using Types + +The most straightforward way to search over multiple types is to +type the response to the parent interface or base class +and pass the actual types we want to search over using `.Type()` + +[source,csharp] +---- +var result = this._client.Search(s => s + .Type(Types.Type(typeof(A), typeof(B), typeof(C))) + .Size(100) +); +---- + +NEST will translate this to a search over `/index/a,b,c/_search`; +hits that have `"_type" : "a"` will be serialized to `A` and so forth + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); +var cDocuments = result.Documents.OfType(); +aDocuments.Count().Should().Be(25); +bDocuments.Count().Should().Be(25); +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +=== Using ConcreteTypeSelector + +A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to + +[source,csharp] +---- +var result = this._client.Search(s => s + .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) + .Size(100) +); +---- + +here for each hit we'll call the delegate passed to `ConcreteTypeSelector where + +* `d` is a representation of the `_source` exposed as a `dynamic` type + +* a typed `h` which represents the encapsulating hit of the source i.e. `Hit` + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); + +var cDocuments = result.Documents.OfType(); + +aDocuments.Count().Should().Be(25); + +bDocuments.Count().Should().Be(25); + +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); + +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +Scroll also supports CovariantSearchResponses + +The Scroll API is a continuation of the previous Search example so Types() are lost. +You can hint at the types using `.CovariantTypes()` + +[source,csharp] +---- +var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s + .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) +); +---- + +NEST will translate this to a search over `/index/a,b,c/_search`; +hits that have `"_type" : "a"` will be serialized to `A` and so forth + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); + +var cDocuments = result.Documents.OfType(); + +aDocuments.Count().Should().Be(25); + +bDocuments.Count().Should().Be(25); + +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); + +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + +The more low level concrete type selector can also be specified on scroll + +[source,csharp] +---- +var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s + .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) +); +---- + +As before, within the delegate passed to `.ConcreteTypeSelector` + +* `d` is the `_source` typed as `dynamic` + +* `h` is the encapsulating typed hit + +Here we assume our response is valid and that we received the 100 documents +we are expecting. Remember `result.Documents` is an `IEnumerable` + +[source,csharp] +---- +result.IsValid.Should().BeTrue(); + +result.Documents.Count().Should().Be(100); +---- + +To prove the returned result set is covariant we filter the documents based on their +actual type and assert the returned subsets are the expected sizes + +[source,csharp] +---- +var aDocuments = result.Documents.OfType(); + +var bDocuments = result.Documents.OfType(); + +var cDocuments = result.Documents.OfType(); + +aDocuments.Count().Should().Be(25); + +bDocuments.Count().Should().Be(25); + +cDocuments.Count().Should().Be(50); +---- + +and assume that properties that only exist on the subclass itself are properly filled + +[source,csharp] +---- +aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); + +bDocuments.Should().OnlyContain(a => a.PropertyOnB > 0); + +cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index 78e725fe4d4..d586e2ca949 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -119,7 +119,7 @@ when comparing with the full blown constructor and passing document manually, ---- request = new IndexRequest(IndexName.From(), TypeName.From(), 2) { - Document = project + Document = project }; ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc new file mode 100644 index 00000000000..984d30e38bb --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc @@ -0,0 +1,35 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[features-inference]] +== Features Inference + +Some URIs in Elasticsearch take a `Feature` enum. +Within NEST, route values on the URI are represented as classes that implement an interface, `IUrlParameter`. +Since enums _cannot_ implement interfaces in C#, a route parameter that would be of type `Feature` is represented using the `Features` class that +the `Feature` enum implicitly converts to. + +=== Constructor + +Using the `Features` constructor directly is possible but rather involved + +[source,csharp] +---- +Features fieldString = Feature.Mappings | Feature.Aliases; +Expect("_mappings,_aliases") + .WhenSerializing(fieldString); +---- + +=== Implicit conversion + +Here we instantiate a GET index request whichs takes two features, settings and warmers. +Notice how we can use the `Feature` enum directly. + +[source,csharp] +---- +var request = new GetIndexRequest(All, Feature.Settings | Feature.Warmers); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index ea1edbed492..8894ae008d3 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -4,14 +4,16 @@ :imagesdir: ../../../images/ -[[strongly-typed-field-access]] -== Strongly typed Field Access +[[field-inference]] +== Field Inference Several places in the elasticsearch API expect the path to a field from your original source document as a string. -NEST allows you to use C expressions to strongly type these field path strings. +NEST allows you to use C# expressions to strongly type these field path strings. These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: +=== Constructor + Using the constructor directly is possible but rather involved [source,csharp] @@ -19,7 +21,7 @@ Using the constructor directly is possible but rather involved var fieldString = new Field { Name = "name" }; ---- -especially when using C expressions since these can not be simply new'ed +This is more cumbersome when using C# expressions since they cannot be instantiated easily [source,csharp] ---- @@ -27,18 +29,20 @@ Expression> expression = p => p.Name; var fieldExpression = Field.Create(expression); Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); ---- -Therefore you can also implicitly convert strings and expressions to `Field`s +=== Implicit Conversion + +Therefore you can also implicitly convert strings and expressions to ``Field``s [source,csharp] ---- Field fieldString = "name"; ---- -but for expressions this is still rather involved +but for expressions this is _still_ rather involved [source,csharp] ---- @@ -47,11 +51,13 @@ Expression> expression = p => p.Name; Field fieldExpression = expression; Expect("name") - .WhenSerializing(fieldExpression) - .WhenSerializing(fieldString); + .WhenSerializing(fieldExpression) + .WhenSerializing(fieldString); ---- -to ease creating `Field`s from expressions there is a static Property class you can use +=== ``Nest.Infer`` + +to ease creating ``Field``s from expressions there is a static `Infer` class you can use [source,csharp] ---- @@ -65,24 +71,27 @@ but for expressions this is still rather involved var fieldExpression = Infer.Field(p => p.Name); ---- -this can be even shortened even further using static imports in c 6 i.e. - `using static Nest.Static;` +this can be even shortened even further using a https://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. + `using static Nest.Infer;` [source,csharp] ---- fieldExpression = Field(p => p.Name); ---- -Now this is much much terser then our first example using the constructor! +Now that is much terser then our first example using the constructor! [source,csharp] ---- Expect("name") - .WhenSerializing(fieldString) - .WhenSerializing(fieldExpression); + .WhenSerializing(fieldString) + .WhenSerializing(fieldExpression); ---- -By default, NEST will camel-case all field names to be more _javascript-y_ +=== Field name casing + +By default, NEST will camel-case **all** field names to better align with typical +javascript/json conventions using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior @@ -93,14 +102,15 @@ var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUppe setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); ---- -However string are *always* passed along verbatim +However ``string``s are *always* passed along verbatim [source,csharp] ---- setup.Expect("NaMe").WhenSerializing("NaMe"); ---- -if you want the same behavior for expressions simply do nothing in the default inferrer +if you want the same behavior for expressions, simply pass a Func to `DefaultFieldNameInferrer` +to make no changes to the name [source,csharp] ---- @@ -111,7 +121,7 @@ setup.Expect("Name").WhenSerializing(Field(p => p.Name)); === Complex field name expressions -You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName +You can follow your property expression to any depth. Here we are traversing to the ``LeadDeveloper``'s `FirstName` [source,csharp] ---- @@ -125,8 +135,7 @@ When dealing with collection indexers, the indexer access is ignored allowing yo Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ---- -NOTE: Similarly, LINQ's `.First()` method also works -remember these are expressions and not actual code that will be executed +Similarly, LINQ's `.First()` method also works [source,csharp] ---- @@ -137,6 +146,8 @@ Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0] Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); ---- +NOTE: Remember, these are _expressions_ and not actual code that will be executed + An indexer on a dictionary is assumed to describe a property name [source,csharp] @@ -158,9 +169,9 @@ Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[va ---- If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow -you to analyze a string in a number of different ways, these _"virtual" sub fields +you to analyze a string in a number of different ways, these __"virtual"__ sub fields do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that -should be mapped and link:../mapping/auto-map[how they are mapped] +should be mapped and <> [source,csharp] ---- @@ -204,10 +215,10 @@ Here we have a list of expressions ---- var expressions = new List>> { - p => p.Name, - p => p.Description, - p => p.CuratedTags.First().Name, - p => p.LeadDeveloper.FirstName + p => p.Name, + p => p.Description, + p => p.CuratedTags.First().Name, + p => p.LeadDeveloper.FirstName }; ---- @@ -216,7 +227,7 @@ and we want to append the suffix "raw" to each [source,csharp] ---- var fieldExpressions = - expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); + expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); Expect("name.raw").WhenSerializing(fieldExpressions[0]); @@ -235,8 +246,8 @@ When using NEST's property attributes you can specify a new name for the propert ---- public class BuiltIn { - [String(Name = "naam")] - public string Name { get; set; } + [String(Name = "naam")] + public string Name { get; set; } } ---- @@ -253,8 +264,8 @@ the `JsonPropertyAttribute` into account ---- public class SerializerSpecific { - [JsonProperty("nameInJson")] - public string Name { get; set; } + [JsonProperty("nameInJson")] + public string Name { get; set; } } ---- @@ -270,9 +281,9 @@ NEST takes precedence ---- public class Both { - [String(Name = "naam")] - [JsonProperty("nameInJson")] - public string Name { get; set; } + [String(Name = "naam")] + [JsonProperty("nameInJson")] + public string Name { get; set; } } ---- @@ -282,7 +293,7 @@ Expect("naam").WhenSerializing(Field(p => p.Name)); Expect(new { - naam = "Martijn Laarman" + naam = "Martijn Laarman" }).WhenSerializing(new Both { Name = "Martijn Laarman" }); ---- @@ -319,15 +330,16 @@ fieldNameOnA.Should().Be("c.name"); fieldNameOnB.Should().Be("c.name"); ---- -now we create a new connectionsettings with a remap for C on class A to `d` -now when we resolve the field path for A will be different +now we create a new connectionsettings with a remap for `C` on class `A` to `"d"` +now when we resolve the field path for property `C` on `A`, it will be different than +for property `C` on `B` [source,csharp] ---- var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s - .InferMappingFor(m => m - .Rename(p => p.C, "d") - ) + .InferMappingFor(m => m + .Rename(p => p.C, "d") + ) ); var newClient = new ElasticClient(newConnectionSettings); @@ -370,28 +382,28 @@ The following example class will demonstrate this precedence ---- class Precedence { - // Even though this property has a NEST property mapping and a JsonProperty attribute, - // We are going to provide a hard rename for it on ConnectionSettings later that should win. - [String(Name = "renamedIgnoresNest")] - [JsonProperty("renamedIgnoresJsonProperty")] - public string RenamedOnConnectionSettings { get; set; } - - // This property has both a NEST attribute and a JsonProperty, NEST should win. - [String(Name = "nestAtt")] - [JsonProperty("jsonProp")] - public string NestAttribute { get; set; } - - // We should take the json property into account by itself - [JsonProperty("jsonProp")] - public string JsonProperty { get; set; } - - // This property we are going to special case in our custom serializer to resolve to ask - [JsonProperty("dontaskme")] - public string AskSerializer { get; set; } - - // We are going to register a DefaultFieldNameInferrer on ConnectionSettings - // that will uppercase all properties. - public string DefaultFieldNameInferrer { get; set; } + // Even though this property has a NEST property mapping and a JsonProperty attribute, + // We are going to provide a hard rename for it on ConnectionSettings later that should win. + [String(Name = "renamedIgnoresNest")] + [JsonProperty("renamedIgnoresJsonProperty")] + public string RenamedOnConnectionSettings { get; set; } + + // This property has both a NEST attribute and a JsonProperty, NEST should win. + [String(Name = "nestAtt")] + [JsonProperty("jsonProp")] + public string NestAttribute { get; set; } + + // We should take the json property into account by itself + [JsonProperty("jsonProp")] + public string JsonProperty { get; set; } + + // This property we are going to special case in our custom serializer to resolve to ask + [JsonProperty("dontaskme")] + public string AskSerializer { get; set; } + + // We are going to register a DefaultFieldNameInferrer on ConnectionSettings + // that will uppercase all properties. + public string DefaultFieldNameInferrer { get; set; } } ---- @@ -401,14 +413,14 @@ Here we create a custom serializer that renames any property named `AskSerialize ---- class CustomSerializer : JsonNetSerializer { - public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } - - public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) - { - return memberInfo.Name == nameof(Precedence.AskSerializer) - ? new PropertyMapping { Name = "ask" } - : base.CreatePropertyMapping(memberInfo); - } + public CustomSerializer(IConnectionSettingsValues settings) : base(settings) { } + + public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) + { + return memberInfo.Name == nameof(Precedence.AskSerializer) + ? new PropertyMapping { Name = "ask" } + : base.CreatePropertyMapping(memberInfo); + } } ---- @@ -418,11 +430,11 @@ and all properties that are not mapped verbatim should be uppercased [source,csharp] ---- var usingSettings = WithConnectionSettings(s => s - - .InferMappingFor(m => m - .Rename(p => p.RenamedOnConnectionSettings, "renamed") - ) - .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) + + .InferMappingFor(m => m + .Rename(p => p.RenamedOnConnectionSettings, "renamed") + ) + .DefaultFieldNameInferrer(p => p.ToUpperInvariant()) ).WithSerializer(s => new CustomSerializer(s)); usingSettings.Expect("renamed").ForField(Field(p => p.RenamedOnConnectionSettings)); @@ -442,18 +454,18 @@ The same naming rules also apply when indexing a document ---- usingSettings.Expect(new [] { - "ask", - "DEFAULTFIELDNAMEINFERRER", - "jsonProp", - "nestAtt", - "renamed" + "ask", + "DEFAULTFIELDNAMEINFERRER", + "jsonProp", + "nestAtt", + "renamed" }).AsPropertiesOf(new Precedence { - RenamedOnConnectionSettings = "renamed on connection settings", - NestAttribute = "using a nest attribute", - JsonProperty = "the default serializer resolves json property attributes", - AskSerializer = "serializer fiddled with this one", - DefaultFieldNameInferrer = "shouting much?" + RenamedOnConnectionSettings = "renamed on connection settings", + NestAttribute = "using a nest attribute", + JsonProperty = "the default serializer resolves json property attributes", + AskSerializer = "serializer fiddled with this one", + DefaultFieldNameInferrer = "shouting much?" }); ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index 89fe592551d..e3b70d1f834 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -4,8 +4,8 @@ :imagesdir: ../../../images/ -[[id-inference]] -== Id Inference +[[ids-inference]] +== Ids Inference === Implicit Conversions @@ -45,9 +45,9 @@ Imagine your codebase has the following type that we want to index into Elastics ---- class MyDTO { - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } } ---- @@ -58,9 +58,9 @@ and create a cached fast func delegate based on the properties getter ---- var dto = new MyDTO { - Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), - Name = "x", - OtherName = "y" + Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), + Name = "x", + OtherName = "y" }; Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); @@ -72,9 +72,9 @@ Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property [source,csharp] ---- WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.Name) - ) + .InferMappingFor(m => m + .IdProperty(p => p.Name) + ) ).Expect("x").WhenInferringIdOn(dto); ---- @@ -86,9 +86,9 @@ with different inference rules [source,csharp] ---- WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) ).Expect("y").WhenInferringIdOn(dto); ---- @@ -102,9 +102,9 @@ to the name of the property that should be used for the document id [ElasticsearchType(IdProperty = nameof(Name))] class MyOtherDTO { - public Guid Id { get; set; } - public string Name { get; set; } - public string OtherName { get; set; } + public Guid Id { get; set; } + public string Name { get; set; } + public string OtherName { get; set; } } ---- @@ -126,9 +126,9 @@ that will infer the document id from the property `OtherName`: [source,csharp] ---- WithConnectionSettings(x => x - .InferMappingFor(m => m - .IdProperty(p => p.OtherName) - ) + .InferMappingFor(m => m + .IdProperty(p => p.OtherName) + ) ).Expect("y").WhenInferringIdOn(dto); ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index c416342b292..89a5731bbb8 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -7,9 +7,11 @@ [[indices-paths]] == Indices paths -Some API's in elasticsearch take one or many index name or a special "all" marker to send the request to all the indices +Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices In nest this is encoded using `Indices` +=== Implicit Conversion + Several types implicitly convert to `Indices` [source,csharp] @@ -19,37 +21,46 @@ Nest.Indices multipleIndicesFromString = "name1, name2"; Nest.Indices allFromString = "_all"; Nest.Indices allWithOthersFromString = "_all, name2"; singleIndexFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(1).And.Contain("name") + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(1).And.Contain("name") ); multipleIndicesFromString.Match( - all => all.Should().BeNull(), - many => many.Indices.Should().HaveCount(2).And.Contain("name2") + all => all.Should().BeNull(), + many => many.Indices.Should().HaveCount(2).And.Contain("name2") ); allFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() ); allWithOthersFromString.Match( - all => all.Should().NotBeNull(), - many => many.Indices.Should().BeNull() + all => all.Should().NotBeNull(), + many => many.Indices.Should().BeNull() ); ---- -to ease creating Field's from expressions there is a static Property class you can use +=== Using `Nest.Indices` + +To ease creating ``Indice``s from expressions, there is a static `Nest.Indices` class you can use [source,csharp] ---- -var all = Nest.Indices.All; +var all = Nest.Indices.All; <1> -var many = Nest.Indices.Index("name1", "name2"); +var many = Nest.Indices.Index("name1", "name2"); <2> -var manyTyped = Nest.Indices.Index().And(); +var manyTyped = Nest.Indices.Index().And(); <3> var singleTyped = Nest.Indices.Index(); var singleString = Nest.Indices.Index("name1"); -var invalidSingleString = Nest.Indices.Index("name1, name2"); +var invalidSingleString = Nest.Indices.Index("name1, name2"); <4> ---- +<1> Using "_all" indices + +<2> specifying multiple indices using strings + +<3> speciying multiple using types + +<4> **invalid** single index name diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index 4678d237f47..c1e746c38a9 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -4,8 +4,10 @@ :imagesdir: ../../../images/ -[[property-names]] -== Property Names +[[property-inference]] +== Property Name Inference + +=== Using `.Suffix()` extension method on `object` Property names resolve to the last token. An example using the `.Suffix()` extension @@ -15,6 +17,8 @@ Expression> expression = p => p.Name.Suffix("raw"); Expect("raw").WhenSerializing(expression); ---- +=== `.ApplySuffix()` extension method on Expression Delegates + And an example using the `.ApplySuffix()` extension on lambda expressions [source,csharp] @@ -26,8 +30,8 @@ expression.AppendSuffix("raw"); Expect("raw").WhenSerializing(expression); ---- -Property names cannot contain a `.` in order to prevent the potential for collision with a field that -may have {ref_current}/_multi_fields.html[`multi_fields`] +Property names cannot contain a ``.``. in order to prevent the potential for collision with a field that +may have {ref_current}/_multi_fields.html`multi_fields`] [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index ad993b643f8..952e059c6b0 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -1,975 +1,988 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../../images/ - -[[auto-map]] -== Auto mapping properties - -When creating a mapping (either when creating an index or via the put mapping API), -NEST offers a feature called AutoMap(), which will automagically infer the correct -Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if -you're using attributes to map your properties, then calling AutoMap() is required -in order for your attributes to be applied. We'll look at examples of both. - -For these examples, we'll define two POCOS, `Company`, which has a name -and a collection of Employees, and `Employee` which has various properties of -different types, and itself has a collection of `Employee` types. - -[source,csharp] ----- -public class Company -{ - public string Name { get; set; } - public List Employees { get; set; } -} - -public class Employee -{ - public string FirstName { get; set; } - public string LastName { get; set; } - public int Salary { get; set; } - public DateTime Birthday { get; set; } - public bool IsManager { get; set; } - public List Employees { get; set; } - public TimeSpan Hours { get; set;} -} ----- - -=== Manual mapping - -To create a mapping for our Company type, we can use the fluent API -and map each property explicitly - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .Properties(ps => ps - .String(s => s - .Name(c => c.Name) - ) - .Object(o => o - .Name(c => c.Employees) - .Properties(eps => eps - .String(s => s - .Name(e => e.FirstName) - ) - .String(s => s - .Name(e => e.LastName) - ) - .Number(n => n - .Name(e => e.Salary) - .Type(NumberType.Integer) - ) - ) - ) - ) - ) - ); ----- - -This is all fine and dandy and useful for some use cases however in most cases -this can become verbose and wieldy. The majority of the time you simply just want to map *all* -the properties of a POCO in a single go. - -[source,csharp] ----- -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - name = new - { - type = "string" - }, - employees = new - { - type = "object", - properties = new - { - firstName = new - { - type = "string" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - } - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -=== Simple Automapping - -This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, -explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap()) - .Map(m => m.AutoMap()) - ); ----- - -Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. -In this example, - -* Birthday was mapped as a date, - -* Hours was mapped as a long (ticks) - -* IsManager was mapped as a boolean, - -* Salary as an integer - -* Employees as an object -and the remaining string properties as strings. - -[source,csharp] ----- -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - employees = new - { - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - type = "object" - }, - name = new - { - type = "string" - } - } - }, - employee = new - { - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -[[automapping-with-overrides]] -== Automapping with overrides - -In most cases, you'll want to map more than just the vanilla datatypes and also provide -various options on your properties (analyzer, docvalues, etc...). In that case, it's -possible to use AutoMap() in conjuction with explicitly mapped properties. - -Here we are using AutoMap() to automatically map our company type, but then we're -overriding our employee property and making it a `nested` type, since by default, -AutoMap() will infer objects as `object`. - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - .Properties(ps => ps - .Nested(n => n - .Name(c => c.Employees) - .Properties(eps => eps - // snip - ) - ) - ) - ) - ); - -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - name = new - { - type = "string" - }, - employees = new - { - type = "nested", - properties = new {} - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -[[automap-with-attributes]] -== Automap with attributes - -It is also possible to define your mappings using attributes on your POCOS. When you -use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. -Here we define the same two types but this time using attributes. - -[source,csharp] ----- -[ElasticsearchType(Name = "company")] -public class CompanyWithAttributes -{ - [String(Analyzer = "keyword", NullValue = "null", Similarity = SimilarityOption.BM25)] - public string Name { get; set; } - - [String] - public TimeSpan? HeadOfficeHours { get; set; } - - [Object(Path = "employees", Store = false)] - public List Employees { get; set; } -} - -[ElasticsearchType(Name = "employee")] -public class EmployeeWithAttributes -{ - [String] - public string FirstName { get; set; } - - [String] - public string LastName { get; set; } - - [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)] - public int Salary { get; set; } - - [Date(Format = "MMddyyyy", NumericResolution = NumericResolutionUnit.Seconds)] - public DateTime Birthday { get; set; } - - [Boolean(NullValue = false, Store = true)] - public bool IsManager { get; set; } - - [Nested(Path = "employees")] - [JsonProperty("empl")] - public List Employees { get; set; } -} ----- - - Then map the types by calling `.AutoMap()` - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap()) - .Map(m => m.AutoMap()) - ); - -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - employees = new - { - path = "employees", - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - store = false, - type = "object" - }, - name = new - { - analyzer = "keyword", - null_value = "null", - similarity = "BM25", - type = "string" - }, - headOfficeHours = new - { - type = "string" - } - } - }, - employee = new - { - properties = new - { - birthday = new - { - format = "MMddyyyy", - numeric_resolution = "seconds", - type = "date" - }, - empl = new - { - path = "employees", - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - type = "nested" - }, - firstName = new - { - type = "string" - }, - isManager = new - { - null_value = false, - store = true, - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - coerce = true, - doc_values = false, - ignore_malformed = true, - type = "double" - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -Just as we were able to override the inferred properties in our earlier example, explicit (manual) -mappings also take precedence over attributes. Therefore we can also override any mappings applied -via any attributes defined on the POCO - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - .Properties(ps => ps - .Nested(n => n - .Name(c => c.Employees) - ) - ) - ) - .Map(m => m - .AutoMap() - .TtlField(ttl => ttl - .Enable() - .Default("10m") - ) - .Properties(ps => ps - .String(s => s - .Name(e => e.FirstName) - .Fields(fs => fs - .String(ss => ss - .Name("firstNameRaw") - .Index(FieldIndexOption.NotAnalyzed) - ) - .TokenCount(t => t - .Name("length") - .Analyzer("standard") - ) - ) - ) - .Number(n => n - .Name(e => e.Salary) - .Type(NumberType.Double) - .IgnoreMalformed(false) - ) - .Date(d => d - .Name(e => e.Birthday) - .Format("MM-dd-yy") - ) - ) - ) - ); - -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - employees = new - { - type = "nested" - }, - name = new - { - analyzer = "keyword", - null_value = "null", - similarity = "BM25", - type = "string" - }, - headOfficeHours = new - { - type = "string" - } - } - }, - employee = new - { - _ttl = new - { - enabled = true, - @default = "10m" - }, - properties = new - { - birthday = new - { - format = "MM-dd-yy", - type = "date" - }, - empl = new - { - path = "employees", - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - hours = new - { - type = "long" - }, - isManager = new - { - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "integer" - } - }, - type = "nested" - }, - firstName = new - { - fields = new - { - firstNameRaw = new - { - index = "not_analyzed", - type = "string" - }, - length = new - { - type = "token_count", - analyzer = "standard" - } - }, - type = "string" - }, - isManager = new - { - null_value = false, - store = true, - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - ignore_malformed = false, - type = "double" - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -[[ignoring-properties]] -== Ignoring Properties - -Properties on a POCO can be ignored in a few ways: - -* Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO - -* Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings - -* Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` - -This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the -property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` - -[source,csharp] ----- -[ElasticsearchType(Name = "company")] -public class CompanyWithAttributesAndPropertiesToIgnore -{ - public string Name { get; set; } - - [String(Ignore = true)] - public string PropertyToIgnore { get; set; } - - public string AnotherPropertyToIgnore { get; set; } - - [JsonIgnore] - public string JsonIgnoredProperty { get; set; } -} ----- - -All of the properties except `Name` have been ignored in the mapping - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m - .AutoMap() - ) - ); - -var expected = new -{ - mappings = new - { - company = new - { - properties = new - { - name = new - { - type = "string" - } - } - } - } -}; - -var settings = WithConnectionSettings(s => s - .InferMappingFor(i => i - .Ignore(p => p.AnotherPropertyToIgnore) - ) -); - -settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -[[mapping-recursion]] -== Mapping Recursion - -If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive -in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only -traverse a single depth when it encounters recursive instances like this. Hence, in the -previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. -This is done as a safe-guard to prevent stack overflows and all the fun that comes with -infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is -often an edge case to have deeply nested mappings like this. However, you may still have -the need to do this, so you can control the recursion depth of `.AutoMap()`. - -Let's introduce a very simple class, `A`, which itself has a property -Child of type `A`. - -[source,csharp] ----- -public class A -{ - public A Child { get; set; } -} ----- - -By default, `.AutoMap()` only goes as far as depth 1 - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap()) - ); ----- - -Thus we do not map properties on the second occurrence of our Child property - -[source,csharp] ----- -var expected = new -{ - mappings = new - { - a = new - { - properties = new - { - child = new - { - properties = new { }, - type = "object" - } - } - } - } -}; - -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); ----- - -Now lets specify a maxRecursion of 3 - -[source,csharp] ----- -var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap(3)) - ); ----- - -`.AutoMap()` has now mapped three levels of our Child property - -[source,csharp] ----- -var expectedWithMaxRecursion = new -{ - mappings = new - { - a = new - { - properties = new - { - child = new - { - type = "object", - properties = new - { - child = new - { - type = "object", - properties = new - { - child = new - { - type = "object", - properties = new - { - child = new - { - type = "object", - properties = new { } - } - } - } - } - } - } - } - } - } - } -}; - -Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); ----- - -[[applying-conventions-through-the-visitor-pattern]] -== Applying conventions through the Visitor pattern - -It is also possible to apply a transformation on all or specific properties. - -AutoMap internally implements the https://en.wikipedia.org/wiki/Visitorpattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, -does nothing and acts as a blank canvas for you to implement your own visiting methods. - -For instance, lets create a custom visitor that disables doc values for numeric and boolean types. -(Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) - -[source,csharp] ----- -public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor -{ - // Override the Visit method on INumberProperty and set DocValues = false - public override void Visit(INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) - { - type.DocValues = false; - } - - // Similarily, override the Visit method on IBooleanProperty and set DocValues = false - public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) - { - type.DocValues = false; - } -} ----- - -Now we can pass an instance of our custom visitor to `.AutoMap()` - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) //<1> - ); ----- -<1> Pass your `IPropertyVisitor` implementation to `.AutoMap` - -and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) -it will apply the transformation defined in each `Visit()` respectively, which in this example -disables {ref_current}/doc-values.html[doc values]. - -[source,csharp] ----- -var expected = new -{ - mappings = new - { - employee = new - { - properties = new - { - birthday = new - { - type = "date" - }, - employees = new - { - properties = new { }, - type = "object" - }, - firstName = new - { - type = "string" - }, - isManager = new - { - doc_values = false, - type = "boolean" - }, - lastName = new - { - type = "string" - }, - salary = new - { - doc_values = false, - type = "integer" - } - } - } - } -}; ----- - -You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit -directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types -to an Elasticsearch string (`IStringProperty`). - -[source,csharp] ----- -public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor -{ - public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => - new StringProperty(); -} ----- - -[source,csharp] ----- -var descriptor = new CreateIndexDescriptor("myindex") - .Mappings(ms => ms - .Map(m => m.AutoMap(new EverythingIsAStringPropertyVisitor())) - ); - -var expected = new -{ - mappings = new - { - employee = new - { - properties = new - { - birthday = new - { - type = "string" - }, - employees = new - { - type = "string" - }, - firstName = new - { - type = "string" - }, - isManager = new - { - type = "string" - }, - lastName = new - { - type = "string" - }, - salary = new - { - type = "string" - } - } - } - } -}; ----- - +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[auto-map]] +== Auto mapping properties + +When creating a mapping (either when creating an index or via the put mapping API), +NEST offers a feature called AutoMap(), which will automagically infer the correct +Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, if +you're using attributes to map your properties, then calling AutoMap() is required +in order for your attributes to be applied. We'll look at examples of both. + +For these examples, we'll define two POCOS, `Company`, which has a name +and a collection of Employees, and `Employee` which has various properties of +different types, and itself has a collection of `Employee` types. + +[source,csharp] +---- +public class Company +{ + public string Name { get; set; } + public List Employees { get; set; } +} + +public class Employee +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public int Salary { get; set; } + public DateTime Birthday { get; set; } + public bool IsManager { get; set; } + public List Employees { get; set; } + public TimeSpan Hours { get; set;} +} +---- + +=== Manual mapping + +To create a mapping for our Company type, we can use the fluent API +and map each property explicitly + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .Properties(ps => ps + .String(s => s + .Name(c => c.Name) + ) + .Object(o => o + .Name(c => c.Employees) + .Properties(eps => eps + .String(s => s + .Name(e => e.FirstName) + ) + .String(s => s + .Name(e => e.LastName) + ) + .Number(n => n + .Name(e => e.Salary) + .Type(NumberType.Integer) + ) + ) + ) + ) + ) + ); +---- + +This is all fine and dandy and useful for some use cases however in most cases +this can become verbose and wieldy. The majority of the time you simply just want to map *all* +the properties of a POCO in a single go. + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + name = new + { + type = "string" + }, + employees = new + { + type = "object", + properties = new + { + firstName = new + { + type = "string" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + } + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +=== Simple Automapping + +This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, +explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap()) + .Map(m => m.AutoMap()) + ); +---- + +Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. +In this example, + +* Birthday was mapped as a date, + +* Hours was mapped as a long (ticks) + +* IsManager was mapped as a boolean, + +* Salary as an integer + +* Employees as an object +and the remaining string properties as strings. + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + employees = new + { + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + type = "object" + }, + name = new + { + type = "string" + } + } + }, + employee = new + { + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +[[auto-mapping-with-overrides]] +[float] +== Auto mapping with overrides + +In most cases, you'll want to map more than just the vanilla datatypes and also provide +various options for your properties (analyzer to use, whether to enable doc_values, etc...). +In that case, it's possible to use `.AutoMap()` in conjuction with explicitly mapped properties. + +Here we are using `.AutoMap()` to automatically map our company type, but then we're +overriding our employee property and making it a `nested` type, since by default, `.AutoMap()` will infer objects as `object`. + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .AutoMap() + .Properties(ps => ps + .Nested(n => n + .Name(c => c.Employees) + .Properties(eps => eps + // snip + ) + ) + ) + ) + ); + +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + name = new + { + type = "string" + }, + employees = new + { + type = "nested", + properties = new {} + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +[[attribute-mapping]] +[float] +== Attribute mapping + +It is also possible to define your mappings using attributes on your POCOs. When you +use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. +Here we define the same two types as before, but this time using attributes to define the mappings. + +[source,csharp] +---- +[ElasticsearchType(Name = "company")] +public class CompanyWithAttributes +{ + [String(Analyzer = "keyword", NullValue = "null", Similarity = SimilarityOption.BM25)] + public string Name { get; set; } + + [String] + public TimeSpan? HeadOfficeHours { get; set; } + + [Object(Path = "employees", Store = false)] + public List Employees { get; set; } +} + +[ElasticsearchType(Name = "employee")] +public class EmployeeWithAttributes +{ + [String] + public string FirstName { get; set; } + + [String] + public string LastName { get; set; } + + [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)] + public int Salary { get; set; } + + [Date(Format = "MMddyyyy", NumericResolution = NumericResolutionUnit.Seconds)] + public DateTime Birthday { get; set; } + + [Boolean(NullValue = false, Store = true)] + public bool IsManager { get; set; } + + [Nested(Path = "employees")] + [JsonProperty("empl")] + public List Employees { get; set; } +} +---- + +Then we map the types by calling `.AutoMap()` + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap()) + .Map(m => m.AutoMap()) + ); + +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + employees = new + { + path = "employees", + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + store = false, + type = "object" + }, + name = new + { + analyzer = "keyword", + null_value = "null", + similarity = "BM25", + type = "string" + }, + headOfficeHours = new + { + type = "string" + } + } + }, + employee = new + { + properties = new + { + birthday = new + { + format = "MMddyyyy", + numeric_resolution = "seconds", + type = "date" + }, + empl = new + { + path = "employees", + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + type = "nested" + }, + firstName = new + { + type = "string" + }, + isManager = new + { + null_value = false, + store = true, + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + coerce = true, + doc_values = false, + ignore_malformed = true, + type = "double" + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +Just as we were able to override the inferred properties in our earlier example, explicit (manual) +mappings also take precedence over attributes. Therefore we can also override any mappings applied +via any attributes defined on the POCO + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .AutoMap() + .Properties(ps => ps + .Nested(n => n + .Name(c => c.Employees) + ) + ) + ) + .Map(m => m + .AutoMap() + .TtlField(ttl => ttl + .Enable() + .Default("10m") + ) + .Properties(ps => ps + .String(s => s + .Name(e => e.FirstName) + .Fields(fs => fs + .String(ss => ss + .Name("firstNameRaw") + .Index(FieldIndexOption.NotAnalyzed) + ) + .TokenCount(t => t + .Name("length") + .Analyzer("standard") + ) + ) + ) + .Number(n => n + .Name(e => e.Salary) + .Type(NumberType.Double) + .IgnoreMalformed(false) + ) + .Date(d => d + .Name(e => e.Birthday) + .Format("MM-dd-yy") + ) + ) + ) + ); + +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + employees = new + { + type = "nested" + }, + name = new + { + analyzer = "keyword", + null_value = "null", + similarity = "BM25", + type = "string" + }, + headOfficeHours = new + { + type = "string" + } + } + }, + employee = new + { + _ttl = new + { + enabled = true, + @default = "10m" + }, + properties = new + { + birthday = new + { + format = "MM-dd-yy", + type = "date" + }, + empl = new + { + path = "employees", + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + hours = new + { + type = "long" + }, + isManager = new + { + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "integer" + } + }, + type = "nested" + }, + firstName = new + { + fields = new + { + firstNameRaw = new + { + index = "not_analyzed", + type = "string" + }, + length = new + { + type = "token_count", + analyzer = "standard" + } + }, + type = "string" + }, + isManager = new + { + null_value = false, + store = true, + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + ignore_malformed = false, + type = "double" + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +[[ignoring-properties]] +[float] +== Ignoring Properties + +Properties on a POCO can be ignored in a few ways: + +* Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO + +* Using the `.InferMappingFor(Func, IClrTypeMapping> selector)` on the connection settings + +* Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` + +This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the +property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` + +[source,csharp] +---- +[ElasticsearchType(Name = "company")] +public class CompanyWithAttributesAndPropertiesToIgnore +{ + public string Name { get; set; } + + [String(Ignore = true)] + public string PropertyToIgnore { get; set; } + + public string AnotherPropertyToIgnore { get; set; } + + [JsonIgnore] + public string JsonIgnoredProperty { get; set; } +} +---- + +All of the properties except `Name` have been ignored in the mapping + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .AutoMap() + ) + ); + +var expected = new +{ + mappings = new + { + company = new + { + properties = new + { + name = new + { + type = "string" + } + } + } + } +}; + +var settings = WithConnectionSettings(s => s + .InferMappingFor(i => i + .Ignore(p => p.AnotherPropertyToIgnore) + ) +); + +settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +[[mapping-recursion]] +[float] +== Mapping Recursion + +If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive +in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only +traverse a single depth when it encounters recursive instances like this. Hence, in the +previous examples, the collection of type `Employee` on the `Employee` class did not get any of its properties mapped. +This is done as a safe-guard to prevent stack overflows and all the fun that comes with +infinite recursion. Additionally, in most cases, when it comes to Elasticsearch mappings, it is +often an edge case to have deeply nested mappings like this. However, you may still have +the need to do this, so you can control the recursion depth of `.AutoMap()`. + +Let's introduce a very simple class, `A`, which itself has a property +Child of type `A`. + +[source,csharp] +---- +public class A +{ + public A Child { get; set; } +} +---- + +By default, `.AutoMap()` only goes as far as depth 1 + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap()) + ); +---- + +Thus we do not map properties on the second occurrence of our Child property + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + a = new + { + properties = new + { + child = new + { + properties = new { }, + type = "object" + } + } + } + } +}; + +Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +---- + +Now lets specify a maxRecursion of 3 + +[source,csharp] +---- +var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(3)) + ); +---- + +`.AutoMap()` has now mapped three levels of our Child property + +[source,csharp] +---- +var expectedWithMaxRecursion = new +{ + mappings = new + { + a = new + { + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new { } + } + } + } + } + } + } + } + } + } + } +}; + +Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); +---- + +[[applying-conventions-through-the-visitor-pattern]] +[float] +== Applying conventions through the Visitor pattern + +It is also possible to apply a transformation on all or specific properties. + +AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, +does nothing and acts as a blank canvas for you to implement your own visiting methods. + +For instance, lets create a custom visitor that disables doc values for numeric and boolean types +(Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) + +[source,csharp] +---- +public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor +{ + public override void Visit( + INumberProperty type, + PropertyInfo propertyInfo, + ElasticsearchPropertyAttributeBase attribute) <1> + { + type.DocValues = false; + } + + public override void Visit( + IBooleanProperty type, + PropertyInfo propertyInfo, + ElasticsearchPropertyAttributeBase attribute) <2> + { + type.DocValues = false; + } +} +---- +<1> Override the `Visit` method on `INumberProperty` and set `DocValues = false` + +<2> Similarily, override the `Visit` method on `IBooleanProperty` and set `DocValues = false` + +Now we can pass an instance of our custom visitor to `.AutoMap()` + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) + ); +---- + +and anytime the client maps a property of the POCO (``Employee`` in this example) as a number (``INumberProperty``) or boolean (``IBooleanProperty``), +it will apply the transformation defined in each `Visit()` call respectively, which in this example +disables {ref_current}/doc-values.html[doc_values]. + +[source,csharp] +---- +var expected = new +{ + mappings = new + { + employee = new + { + properties = new + { + birthday = new + { + type = "date" + }, + employees = new + { + properties = new { }, + type = "object" + }, + firstName = new + { + type = "string" + }, + isManager = new + { + doc_values = false, + type = "boolean" + }, + lastName = new + { + type = "string" + }, + salary = new + { + doc_values = false, + type = "integer" + } + } + } + } +}; +---- + +=== Visiting on ``PropertyInfo`` + +You can even take the visitor approach a step further, and instead of visiting on `IProperty` types, visit +directly on your POCO properties (``PropertyInfo``). As an example, let's create a visitor that maps all CLR types +to an Elasticsearch string (``IStringProperty``). + +[source,csharp] +---- +public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor +{ + public override IProperty Visit( + PropertyInfo propertyInfo, + ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); +} +---- + +[source,csharp] +---- +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(new EverythingIsAStringPropertyVisitor())) + ); + +var expected = new +{ + mappings = new + { + employee = new + { + properties = new + { + birthday = new + { + type = "string" + }, + employees = new + { + type = "string" + }, + firstName = new + { + type = "string" + }, + isManager = new + { + type = "string" + }, + lastName = new + { + type = "string" + }, + salary = new + { + type = "string" + } + } + } + } +}; +---- + diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 2359f9e57d7..3615da648ff 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -62,21 +62,21 @@ var node = new Uri("http://mynode.example.com:8082/apiKey"); var connectionPool = new SniffingConnectionPool(new[] { node }); var config = new ConnectionConfiguration(connectionPool) - .DisableDirectStreaming() - .BasicAuthentication("user", "pass") - .RequestTimeout(TimeSpan.FromSeconds(5)); + .DisableDirectStreaming() + .BasicAuthentication("user", "pass") + .RequestTimeout(TimeSpan.FromSeconds(5)); ---- The following is a list of available connection configuration options: [source,csharp] ---- -var client = new ElasticLowLevelClient(); - var config = new ConnectionConfiguration() - .DisableAutomaticProxyDetection() //<1> - .EnableHttpCompression() //<2> - .DisableDirectStreaming(); //<3> + .DisableAutomaticProxyDetection() <1> + .EnableHttpCompression() <2> + .DisableDirectStreaming(); <3> + +var client = new ElasticLowLevelClient(config); var result = client.Search>(new { size = 12 }); ---- @@ -106,12 +106,12 @@ other configuration options [source,csharp] ---- config = config - .GlobalQueryStringParameters(new NameValueCollection()) //<1> - .Proxy(new Uri("http://myproxy"), "username", "pass") //<2> - .RequestTimeout(TimeSpan.FromSeconds(4)) //<3> - .ThrowExceptions() //<4> - .PrettyJson() //<5> - .BasicAuthentication("username", "password"); + .GlobalQueryStringParameters(new NameValueCollection()) <1> + .Proxy(new Uri("http://myproxy"), "username", "pass") <2> + .RequestTimeout(TimeSpan.FromSeconds(4)) <3> + .ThrowExceptions() <4> + .PrettyJson() <5> + .BasicAuthentication("username", "password"); ---- <1> Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. @@ -188,7 +188,7 @@ var list = new List(); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) //<1> +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) <1> .DisableDirectStreaming() .OnRequestCompleted(response => { @@ -281,17 +281,17 @@ This can be much faster then registering them on JsonSerializerSettings.Converte ---- public class MyJsonNetSerializer : JsonNetSerializer { - public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } + public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } public int CallToModify { get; set; } = 0; - protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; + protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; public int CallToContractConverter { get; set; } = 0; - protected override IList> ContractConverters => new List> - { - t => { - CallToContractConverter++; - return null; - } - }; + protected override IList> ContractConverters => new List> + { + t => { + CallToContractConverter++; + return null; + } + }; } ---- diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 62a8c64b777..8c2a4a71a4d 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -28,37 +28,37 @@ Let's demonstrate which components are disposed by creating our own derived `Con ---- class AConnectionSettings : ConnectionSettings { - public AConnectionSettings(IConnectionPool pool, IConnection connection) - : base(pool, connection) - { } - public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() - { - this.IsDisposed = true; - base.DisposeManagedResources(); - } + public AConnectionSettings(IConnectionPool pool, IConnection connection) + : base(pool, connection) + { } + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } } class AConnectionPool : SingleNodeConnectionPool { - public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } - - public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() - { - this.IsDisposed = true; - base.DisposeManagedResources(); - } + public AConnectionPool(Uri uri, IDateTimeProvider dateTimeProvider = null) : base(uri, dateTimeProvider) { } + + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } } class AConnection : InMemoryConnection { - public bool IsDisposed { get; private set; } - protected override void DisposeManagedResources() - { - this.IsDisposed = true; - base.DisposeManagedResources(); - } + public bool IsDisposed { get; private set; } + protected override void DisposeManagedResources() + { + this.IsDisposed = true; + base.DisposeManagedResources(); + } } ---- diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index aea574b4d1e..299d025ef0e 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -8,10 +8,10 @@ == Post data The low level client allows you to post a `string` or `byte[]` array directly. On top of this, -if you pass a collection of `string`s or `object`s they will be serialized +if you pass a collection of ``string``s or ``object``s they will be serialized using Elasticsearch's special bulk/multi format. -Even though the argument for `PostData` on the low level client takes a `PostData`, +Even 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 completely. You can implicitly convert from the following types @@ -40,6 +40,19 @@ PostData bytes will always be set if it originated from `byte[]` [source,csharp] ---- fromByteArray.WrittenBytes.Should().BeSameAs(bytes); + +fromString.Type.Should().Be(PostType.LiteralString); +fromByteArray.Type.Should().Be(PostType.ByteArray); +fromListOfString.Type.Should().Be(PostType.EnumerableOfString); +fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); +fromObject.Type.Should().Be(PostType.Serializable); +---- + +and passing a `PostData` object to a method taking `PostData` should not wrap + +[source,csharp] +---- +fromString = ImplicitlyConvertsFrom(fromString); ---- [source,csharp] @@ -51,12 +64,6 @@ await this.AssertOn(new ConnectionConfiguration()); [source,csharp] ---- -fromString.Type.Should().Be(PostType.LiteralString); -fromByteArray.Type.Should().Be(PostType.ByteArray); -fromListOfString.Type.Should().Be(PostType.EnumerableOfString); -fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); -fromObject.Type.Should().Be(PostType.Serializable); -fromString = ImplicitlyConvertsFrom(fromString); fromByteArray = ImplicitlyConvertsFrom(fromByteArray); fromListOfString = ImplicitlyConvertsFrom(fromListOfString); fromListOfObject = ImplicitlyConvertsFrom(fromListOfObject); @@ -100,14 +107,14 @@ In all other cases postdata is serialized as is. await Post(() => @object, writes: objectJson, storesBytes: false, settings: settings); ---- -If you want to maintain a copy of the request that went out use the following settings +If you want to maintain a copy of the request that went out, use `DisableDirectStreaming` [source,csharp] ---- settings = new ConnectionSettings().DisableDirectStreaming(); ---- -by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream +by forcing `DisableDirectStreaming` on connection settings, serialization happens first in a private `MemoryStream` so we can get hold of the serialized bytes [source,csharp] diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 5b65a1d8c65..efe65c27fab 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -13,11 +13,11 @@ Every descriptor should inherit from `DescriptorBase`, this hides object members ---- var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() - where t.IsClass() - && t.Name.Contains("Descriptor") - && !notDescriptors.Contains(t.Name) - && !t.GetInterfaces().Any(i => i == typeof(IDescriptor)) - select t.FullName; + where t.IsClass() + && t.Name.Contains("Descriptor") + && !notDescriptors.Contains(t.Name) + && !t.GetInterfaces().Any(i => i == typeof(IDescriptor)) + select t.FullName; descriptors.Should().BeEmpty(); ---- @@ -26,35 +26,35 @@ Methods taking a func should have that func return an interface [source,csharp] ---- var descriptors = - from t in typeof(DescriptorBase<,>).Assembly().Types() - where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) - select t; + from t in typeof(DescriptorBase<,>).Assembly().Types() + where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t) + select t; var selectorMethods = - from d in descriptors - from m in d.GetMethods() - let parameters = m.GetParameters() - from p in parameters - let type = p.ParameterType - let isGeneric = type.IsGeneric() - where isGeneric - let isFunc = type.GetGenericTypeDefinition() == typeof(Func<,>) - where isFunc - let firstFuncArg = type.GetGenericArguments().First() - let secondFuncArg = type.GetGenericArguments().Last() - let isQueryFunc = firstFuncArg.IsGeneric() && - firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) && - typeof(QueryContainer).IsAssignableFrom(secondFuncArg) - where !isQueryFunc - let isFluentDictionaryFunc = - firstFuncArg.IsGeneric() && - firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) && - secondFuncArg.IsGeneric() && - secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) - where !isFluentDictionaryFunc - let lastArgIsNotInterface = !secondFuncArg.IsInterface() - where lastArgIsNotInterface - select $"{m.Name} on {m.DeclaringType.Name}"; + from d in descriptors + from m in d.GetMethods() + let parameters = m.GetParameters() + from p in parameters + let type = p.ParameterType + let isGeneric = type.IsGeneric() + where isGeneric + let isFunc = type.GetGenericTypeDefinition() == typeof(Func<,>) + where isFunc + let firstFuncArg = type.GetGenericArguments().First() + let secondFuncArg = type.GetGenericArguments().Last() + let isQueryFunc = firstFuncArg.IsGeneric() && + firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) && + typeof(QueryContainer).IsAssignableFrom(secondFuncArg) + where !isQueryFunc + let isFluentDictionaryFunc = + firstFuncArg.IsGeneric() && + firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) && + secondFuncArg.IsGeneric() && + secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) + where !isFluentDictionaryFunc + let lastArgIsNotInterface = !secondFuncArg.IsInterface() + where lastArgIsNotInterface + select $"{m.Name} on {m.DeclaringType.Name}"; selectorMethods.Should().BeEmpty(); ---- diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index aa434df2fef..cb4fded5230 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -10,11 +10,11 @@ [source,csharp] ---- var requestParametersNotNamedRequest = - from m in typeof(IElasticClient).GetMethods() - from p in m.GetParameters() - where typeof(IRequest).IsAssignableFrom(p.ParameterType) - where !p.Name.Equals("request") - select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'request' but has a name of '{p.Name}'"; + from m in typeof(IElasticClient).GetMethods() + from p in m.GetParameters() + where typeof(IRequest).IsAssignableFrom(p.ParameterType) + where !p.Name.Equals("request") + select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'request' but has a name of '{p.Name}'"; requestParametersNotNamedRequest.Should().BeEmpty(); ---- @@ -22,10 +22,10 @@ requestParametersNotNamedRequest.Should().BeEmpty(); [source,csharp] ---- var requestParameters = - (from m in typeof(IElasticClient).GetMethods() - from p in m.GetParameters() - where typeof(IRequest).IsAssignableFrom(p.ParameterType) - select p).ToList(); + (from m in typeof(IElasticClient).GetMethods() + from p in m.GetParameters() + where typeof(IRequest).IsAssignableFrom(p.ParameterType) + select p).ToList(); requestParameter.HasDefaultValue.Should().BeFalse(); ---- @@ -85,54 +85,54 @@ asyncMethod.Parameter.HasDefaultValue.Should().Be(syncMethod.Parameter.HasDefaul [source,csharp] ---- var fluentParametersNotNamedSelector = - from m in typeof (IElasticClient).GetMethods() - from p in m.GetParameters() - where p.ParameterType.BaseType() == typeof (MulticastDelegate) - where !p.Name.Equals("selector") - select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'selector' but has a name of '{p.Name}'"; + from m in typeof (IElasticClient).GetMethods() + from p in m.GetParameters() + where p.ParameterType.BaseType() == typeof (MulticastDelegate) + where !p.Name.Equals("selector") + select $"method '{nameof(IElasticClient)}.{m.Name}' should have parameter name of 'selector' but has a name of '{p.Name}'"; fluentParametersNotNamedSelector.Should().BeEmpty(); ---- [source,csharp] ---- private class MethodWithRequestParameter - { - public string Name { get; } + { + public string Name { get; } - public MethodInfo MethodInfo { get; } + public MethodInfo MethodInfo { get; } - public bool IsAsync { get; } + public bool IsAsync { get; } - public ClientMethodType MethodType { get; } + public ClientMethodType MethodType { get; } - public ParameterInfo Parameter { get; } + public ParameterInfo Parameter { get; } - public MethodWithRequestParameter(MethodInfo methodInfo) - { - Name = methodInfo.Name.EndsWith("Async") - ? methodInfo.Name.Substring(0, methodInfo.Name.Length - "Async".Length) - : methodInfo.Name; + public MethodWithRequestParameter(MethodInfo methodInfo) + { + Name = methodInfo.Name.EndsWith("Async") + ? methodInfo.Name.Substring(0, methodInfo.Name.Length - "Async".Length) + : methodInfo.Name; - IsAsync = methodInfo.ReturnType.IsGeneric() && - methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); + IsAsync = methodInfo.ReturnType.IsGeneric() && + methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); - MethodInfo = methodInfo; + MethodInfo = methodInfo; - var parameterInfo = methodInfo.GetParameters() - .FirstOrDefault(p => typeof(IRequest).IsAssignableFrom(p.ParameterType)); + var parameterInfo = methodInfo.GetParameters() + .FirstOrDefault(p => typeof(IRequest).IsAssignableFrom(p.ParameterType)); - if (parameterInfo != null) - { - Parameter = parameterInfo; - MethodType = ClientMethodType.Initializer; - } - else - { - Parameter = methodInfo.GetParameters() - .First(p => p.ParameterType.BaseType() == typeof(MulticastDelegate)); - MethodType = ClientMethodType.Fluent; - } - } - } + if (parameterInfo != null) + { + Parameter = parameterInfo; + MethodType = ClientMethodType.Initializer; + } + else + { + Parameter = methodInfo.GetParameters() + .First(p => p.ParameterType.BaseType() == typeof(MulticastDelegate)); + MethodType = ClientMethodType.Fluent; + } + } + } ---- diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 928aae50d02..6abf43be885 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -17,13 +17,13 @@ Abstract class names should end with a `Base` suffix ---- var exceptions = new[] { - typeof(DateMath) + typeof(DateMath) }; var abstractClasses = typeof(IRequest).Assembly().GetTypes() - .Where(t => t.IsClass() && t.IsAbstract() && !t.IsSealed() && !exceptions.Contains(t)) - .Where(t => !t.Name.Split('`')[0].EndsWith("Base")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); + .Where(t => t.IsClass() && t.IsAbstract() && !t.IsSealed() && !exceptions.Contains(t)) + .Where(t => !t.Name.Split('`')[0].EndsWith("Base")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); abstractClasses.Should().BeEmpty(); ---- @@ -34,11 +34,11 @@ Class names that end with `Base` suffix are abstract var exceptions = new[] { typeof(DateMath) }; var baseClassesNotAbstract = typeof(IRequest).Assembly().GetTypes() - .Where(t => t.IsClass() && !exceptions.Contains(t)) - .Where(t => t.Name.Split('`')[0].EndsWith("Base")) - .Where(t => !t.IsAbstractClass()) - .Select(t => t.Name.Split('`')[0]) - .ToList(); + .Where(t => t.IsClass() && !exceptions.Contains(t)) + .Where(t => t.Name.Split('`')[0].EndsWith("Base")) + .Where(t => !t.IsAbstractClass()) + .Select(t => t.Name.Split('`')[0]) + .ToList(); baseClassesNotAbstract.Should().BeEmpty(); ---- @@ -52,11 +52,11 @@ Request class names should end with `Request` var types = typeof(IRequest).Assembly().GetTypes(); var requests = types - .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) - .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) - .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); + .Where(t => typeof(IRequest).IsAssignableFrom(t) && !t.IsAbstract()) + .Where(t => !typeof(IDescriptor).IsAssignableFrom(t)) + .Where(t => !t.Name.Split('`')[0].EndsWith("Request")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); requests.Should().BeEmpty(); ---- @@ -68,10 +68,10 @@ Response class names should end with `Response` var types = typeof(IRequest).Assembly().GetTypes(); var responses = types - .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) - .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) - .Select(t => t.Name.Split('`')[0]) - .ToList(); + .Where(t => typeof(IResponse).IsAssignableFrom(t) && !t.IsAbstract()) + .Where(t => !t.Name.Split('`')[0].EndsWith("Response")) + .Select(t => t.Name.Split('`')[0]) + .ToList(); responses.Should().BeEmpty(); ---- @@ -83,58 +83,58 @@ the `Exists` requests. [source,csharp] ---- -var exceptions = new[] //<1> +var exceptions = new[] <1> { - typeof(CatAliasesRequest), - typeof(CatAllocationRequest), - typeof(CatCountRequest), - typeof(CatFielddataRequest), - typeof(CatHealthRequest), - typeof(CatHelpRequest), - typeof(CatIndicesRequest), - typeof(CatMasterRequest), - typeof(CatNodesRequest), - typeof(CatPendingTasksRequest), - typeof(CatPluginsRequest), - typeof(CatRecoveryRequest), - typeof(CatSegmentsRequest), - typeof(CatShardsRequest), - typeof(CatThreadPoolRequest), - typeof(DocumentExistsRequest), - typeof(DocumentExistsRequest<>), - typeof(AliasExistsRequest), - typeof(IndexExistsRequest), - typeof(TypeExistsRequest), - typeof(IndexTemplateExistsRequest), - typeof(SearchExistsRequest), - typeof(SearchExistsRequest<>), - typeof(SearchTemplateRequest), - typeof(SearchTemplateRequest<>), - typeof(ScrollRequest), - typeof(SourceRequest), - typeof(SourceRequest<>), - typeof(ValidateQueryRequest<>), - typeof(GetAliasRequest), - typeof(CatNodeattrsRequest), - typeof(IndicesShardStoresRequest), - typeof(RenderSearchTemplateRequest) + typeof(CatAliasesRequest), + typeof(CatAllocationRequest), + typeof(CatCountRequest), + typeof(CatFielddataRequest), + typeof(CatHealthRequest), + typeof(CatHelpRequest), + typeof(CatIndicesRequest), + typeof(CatMasterRequest), + typeof(CatNodesRequest), + typeof(CatPendingTasksRequest), + typeof(CatPluginsRequest), + typeof(CatRecoveryRequest), + typeof(CatSegmentsRequest), + typeof(CatShardsRequest), + typeof(CatThreadPoolRequest), + typeof(DocumentExistsRequest), + typeof(DocumentExistsRequest<>), + typeof(AliasExistsRequest), + typeof(IndexExistsRequest), + typeof(TypeExistsRequest), + typeof(IndexTemplateExistsRequest), + typeof(SearchExistsRequest), + typeof(SearchExistsRequest<>), + typeof(SearchTemplateRequest), + typeof(SearchTemplateRequest<>), + typeof(ScrollRequest), + typeof(SourceRequest), + typeof(SourceRequest<>), + typeof(ValidateQueryRequest<>), + typeof(GetAliasRequest), + typeof(CatNodeattrsRequest), + typeof(IndicesShardStoresRequest), + typeof(RenderSearchTemplateRequest) }; var types = typeof(IRequest).Assembly().GetTypes(); var requests = new HashSet(types - .Where(t => - t.IsClass() && - !t.IsAbstract() && - typeof(IRequest).IsAssignableFrom(t) && - !typeof(IDescriptor).IsAssignableFrom(t) - && !exceptions.Contains(t)) - .Select(t => t.Name.Split('`')[0].Replace("Request", "")) + .Where(t => + t.IsClass() && + !t.IsAbstract() && + typeof(IRequest).IsAssignableFrom(t) && + !typeof(IDescriptor).IsAssignableFrom(t) + && !exceptions.Contains(t)) + .Select(t => t.Name.Split('`')[0].Replace("Request", "")) ); var responses = types - .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) - .Select(t => t.Name.Split('`')[0].Replace("Response", "")); + .Where(t => t.IsClass() && !t.IsAbstract() && typeof(IResponse).IsAssignableFrom(t)) + .Select(t => t.Name.Split('`')[0].Replace("Response", "")); requests.Except(responses).Should().BeEmpty(); ---- diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index 91136723dd9..b91485f4145 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -10,8 +10,8 @@ [source,csharp] ---- var staticProperties = from p in typeof(Query<>).GetMethods() - let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name - select name; + let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name + select name; var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name); @@ -21,8 +21,8 @@ staticProperties.Distinct().Should().Contain(placeHolders.Distinct()); [source,csharp] ---- var fluentMethods = from p in typeof(QueryContainerDescriptor<>).GetMethods() - let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name - select name; + let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name + select name; var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name); @@ -34,9 +34,9 @@ fluentMethods.Distinct().Should().Contain(placeHolders.Distinct()); var skipQueryImplementations = new[] { typeof(IFieldNameQuery), typeof(IFuzzyQuery<,>), typeof(IConditionlessQuery) }; var queries = typeof(IQuery).Assembly().ExportedTypes - .Where(t => t.IsInterface() && typeof(IQuery).IsAssignableFrom(t)) - .Where(t => !skipQueryImplementations.Contains(t)) - .ToList(); + .Where(t => t.IsInterface() && typeof(IQuery).IsAssignableFrom(t)) + .Where(t => !skipQueryImplementations.Contains(t)) + .ToList(); queries.Should().NotBeEmpty(); @@ -45,9 +45,9 @@ var visitMethods = typeof(IQueryVisitor).GetMethods().Where(m => m.Name == "Visi visitMethods.Should().NotBeEmpty(); var missingTypes = from q in queries - let visitMethod = visitMethods.FirstOrDefault(m => m.GetParameters().First().ParameterType == q) - where visitMethod == null - select q; + let visitMethod = visitMethods.FirstOrDefault(m => m.GetParameters().First().ParameterType == q) + where visitMethod == null + select q; missingTypes.Should().BeEmpty(); ---- @@ -55,9 +55,9 @@ missingTypes.Should().BeEmpty(); [source,csharp] ---- var properties = from p in QueryProperties - let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) - where a.Count() != 1 - select p; + let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) + where a.Count() != 1 + select p; properties.Should().BeEmpty(); ---- diff --git a/docs/asciidoc/common-options.asciidoc b/docs/asciidoc/common-options.asciidoc index 5e99213dd2a..de10d6b64a8 100644 --- a/docs/asciidoc/common-options.asciidoc +++ b/docs/asciidoc/common-options.asciidoc @@ -1,4 +1,4 @@ -:output-dir: common-options +:output-dir: common-options [[common-options]] = Common Options @@ -6,6 +6,7 @@ [partintro] -- Something about the convenience types for working with time and distance units and date math expressions + -- include::{output-dir}/time-unit/time-units.asciidoc[] @@ -14,6 +15,3 @@ include::{output-dir}/distance-unit/distance-units.asciidoc[] include::{output-dir}/date-math/date-math-expressions.asciidoc[] - - - diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index 8903602eda1..5852e072014 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -65,11 +65,11 @@ the resulting date math will assume the whole string is the anchor ---- Expect(nonsense).WhenSerializing(nonsense) .Result(dateMath => ((IDateMath)dateMath) - .Anchor.Match( - d => d.Should().NotBe(default(DateTime)), - s => s.Should().Be(nonsense) - ) - ); + .Anchor.Match( + d => d.Should().NotBe(default(DateTime)), + s => s.Should().Be(nonsense) + ) + ); ---- `DateTime` also implicitly convert to simple date math expressions @@ -85,11 +85,11 @@ the anchor will be an actual `DateTime`, even after a serialization/deserializat ---- Expect("2015-05-05T00:00:00").WhenSerializing(date) .Result(dateMath => ((IDateMath)dateMath) - . Anchor.Match( - d => d.Should().Be(date), - s => s.Should().BeNull() - ) - ); + . Anchor.Match( + d => d.Should().Be(date), + s => s.Should().BeNull() + ) + ); ---- === Complex Expressions diff --git a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc index 83c1a043cad..b51a727aa21 100644 --- a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc +++ b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc @@ -31,8 +31,8 @@ The factor is a double so always has at least one decimal place when serialized [source,csharp] ---- Expect("25.0m") - .WhenSerializing(unitComposed) - .WhenSerializing(unitComposedWithUnits); + .WhenSerializing(unitComposed) + .WhenSerializing(unitComposedWithUnits); ---- ==== Implicit conversion @@ -47,8 +47,8 @@ Nest.Distance distanceString = "25"; Nest.Distance distanceStringWithUnits = "25m"; Expect(new Nest.Distance(25)) - .WhenSerializing(distanceString) - .WhenSerializing(distanceStringWithUnits); + .WhenSerializing(distanceString) + .WhenSerializing(distanceStringWithUnits); ---- ==== Supported units diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index ffe465ab7cc..b03fd54f3b0 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -41,10 +41,10 @@ the expression will be serialized to a time unit string composed of the factor a [source,csharp] ---- Expect("2d") - .WhenSerializing(unitString) - .WhenSerializing(unitComposed) - .WhenSerializing(unitTimeSpan) - .WhenSerializing(unitMilliseconds); + .WhenSerializing(unitString) + .WhenSerializing(unitComposed) + .WhenSerializing(unitTimeSpan) + .WhenSerializing(unitMilliseconds); ---- The `Milliseconds` property on `Time` is calculated even when not using the constructor that takes a double diff --git a/docs/asciidoc/connection-pooling.asciidoc b/docs/asciidoc/connection-pooling.asciidoc index 759505a124d..a62280ab5cc 100644 --- a/docs/asciidoc/connection-pooling.asciidoc +++ b/docs/asciidoc/connection-pooling.asciidoc @@ -1,11 +1,19 @@ -:output-dir: client-concepts/connection-pooling +:output-dir: client-concepts/connection-pooling + :building-blocks: {output-dir}/building-blocks + :sniffing: {output-dir}/sniffing + :pinging: {output-dir}/pinging + :round-robin: {output-dir}/round-robin + :failover: {output-dir}/failover + :max-retries: {output-dir}/max-retries + :request-overrides: {output-dir}/request-overrides + :exceptions: {output-dir}/exceptions include::{building-blocks}/connection-pooling.asciidoc[] @@ -54,8 +62,3 @@ include::{exceptions}/unexpected-exceptions.asciidoc[] include::{exceptions}/unrecoverable-exceptions.asciidoc[] - - - - - diff --git a/docs/asciidoc/high-level.asciidoc b/docs/asciidoc/high-level.asciidoc index 6cab2b234d9..9a4401707dd 100644 --- a/docs/asciidoc/high-level.asciidoc +++ b/docs/asciidoc/high-level.asciidoc @@ -1,20 +1,48 @@ -:output-dir: client-concepts/high-level +:output-dir: client-concepts/high-level -[[high-level]] -== High Level +[[nest]] += Client Concepts - High Level -A high level client that provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL -and takes advantage of specific .NET features such as covariant results. +[partintro] +-- +The high level client, `ElasticClient`, provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL. -NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> +It can be installed from the Package Manager Console inside Visual Studio using + + +[source,shell] +---- +Install-Package NEST +---- + + +Or by searching for https://www.nuget.org/packages/NEST[NEST] in the Package Manager GUI. + +NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> via +the `.LowLevel` property on `ElasticClient`. There are a number of conventions that NEST uses for inference of -- Field and Property names -- Document ids -- Building a URI path to a document -- Building a URI path to one or more indices -- Inferring + +* <> and <> + +* <> + +* <> + +* <> + +* <> + + +In addition to features such as + + +* <> + +* <> + +-- include::{output-dir}/inference/field-inference.asciidoc[] @@ -32,8 +60,5 @@ include::{output-dir}/mapping/auto-map.asciidoc[] include::{output-dir}/covariant-hits/covariant-search-results.asciidoc[] - - - - +include::connection-pooling.asciidoc[] diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 212cd2f5d73..57662ec8c3d 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -1,5 +1,5 @@ -[[elasticsearch-net-reference]] -= Elasticsearch.Net and NEST: the .NET Elasticsearch clients +[[elasticsearch-net-reference]] += Elasticsearch.Net and NEST: the .NET clients include::intro.asciidoc[] @@ -11,4 +11,3 @@ include::query-dsl.asciidoc[] include::aggregations.asciidoc[] - diff --git a/docs/asciidoc/intro.asciidoc b/docs/asciidoc/intro.asciidoc index 0b41b0b3bd4..ddc314e19bd 100644 --- a/docs/asciidoc/intro.asciidoc +++ b/docs/asciidoc/intro.asciidoc @@ -1,4 +1,5 @@ -:github: https://github.com/elastic/elasticsearch-net +:github: https://github.com/elastic/elasticsearch-net + :stackoverflow: http://stackoverflow.com [[introduction]] @@ -14,10 +15,14 @@ enough so that **all** the Elasticsearch API endpoints are represented as method Please read the getting started guide for both. === Who's using Nest -- {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). -- http://www.7digital.com[7digital.com] (run NEST on mono). -- https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). -- http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. + +* {stackoverflow}[stackoverflow.com] (and the rest of the stackexchange family). + +* http://www.7digital.com[7digital.com] (run NEST on mono). + +* https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). + +* http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] === Other resources @@ -55,4 +60,3 @@ This software is licensed under the Apache 2 license, quoted below. limitations under the License. .... - diff --git a/docs/asciidoc/low-level.asciidoc b/docs/asciidoc/low-level.asciidoc index 78b02a70ded..e6d50c0a974 100644 --- a/docs/asciidoc/low-level.asciidoc +++ b/docs/asciidoc/low-level.asciidoc @@ -1,19 +1,25 @@ -:output-dir: client-concepts/low-level +:output-dir: client-concepts/low-level -[[low-level]] -== Low Level +[[elasticsearch-net]] += Client Concepts - Low Level +[partintro] +-- The low level client, `ElasticLowLevelClient`, is a low level, dependency free client that has no opinions about how you build and represent your requests and responses. It can be installed from the Package Manager Console inside Visual Studio using -[source, shell] + +[source,shell] ---- Install-Package Elasticsearch.Net ---- -Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[`Elasticsearch.Net`] in the Package Manager GUI. + +Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. + +-- include::{output-dir}/connecting.asciidoc[] @@ -21,5 +27,3 @@ include::{output-dir}/lifetimes.asciidoc[] include::{output-dir}/post-data.asciidoc[] - - diff --git a/docs/asciidoc/query-dsl-usage.asciidoc b/docs/asciidoc/query-dsl-usage.asciidoc index 117510d6dfe..5d3586ad3ec 100644 --- a/docs/asciidoc/query-dsl-usage.asciidoc +++ b/docs/asciidoc/query-dsl-usage.asciidoc @@ -1,2 +1,132 @@ -:includes-from-dirs: +:includes-from-dirs: query-dsl/compound,query-dsl/full-text,query-dsl/geo,query-dsl/joining,query-dsl/nest-specific,query-dsl/span,query-dsl/specialized,query-dsl/term-level + +include::../../docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc[] + +include::../../docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc[] diff --git a/docs/asciidoc/query-dsl.asciidoc b/docs/asciidoc/query-dsl.asciidoc index 76eedce8e11..f861089183a 100644 --- a/docs/asciidoc/query-dsl.asciidoc +++ b/docs/asciidoc/query-dsl.asciidoc @@ -1,17 +1,145 @@ -:output-dir: query-dsl +:output-dir: query-dsl [[query-dsl]] = Query DSL [partintro] -- -Something about the query DSL --- +NEST exposes all of the query DSL endpoints available in Elasticsearch -include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] +* <> -include::query-dsl-usage.asciidoc[] +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> +* <> +* <> +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +* <> + +-- + +include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] + +include::query-dsl-usage.asciidoc[] diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index 4cee5be53f4..ca408b6cf38 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -1,177 +1,324 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../images/ - -[[bool-queries]] -== Bool Queries - -Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, -take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses - -[source,csharp] ----- -var searchResults = this.Client.Search(s => s - .Query(q => q - .Bool(b => b - .Should( - bs => bs.Term(p => p.Name, "x"), - bs => bs.Term(p => p.Name, "y") - ) - ) - ) -); ----- - -Now, imagine multiple nested bools; you'll realise that this quickly becomes an exercise in _hadouken indenting_ - -[[indent]] -.hadouken indenting example -image::{imagesdir}hadouken-indentation.jpg[dead indent] - -=== Operator Overloading - -For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. -The previous example now becomes the following with the fluent API - -[source,csharp] ----- -var searchResults = this.Client.Search(s => s - .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) -); ----- - -or, using the object initializer syntax - -[source,csharp] ----- -searchResults = this.Client.Search(new SearchRequest -{ - Query = new TermQuery { Field = "name", Value= "x" } - || new TermQuery { Field = Field(p=>p.Name), Value = "y" } -}); ----- - -A naive implementation of operator overloading would rewrite - -`term && term && term` to - -.... -bool -|___must - |___term - |___bool - |___must - |___term - |___term -.... - -As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and -join them together to become a single bool query - -.... -bool -|___must - |___term - |___term - |___term -.... - -The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator - -And to mark a query as a `filter` using the `+` operator - -Both of these can be combined with `&&` to form a single bool query - -=== Combining/Merging bool queries - -When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query - -.... -bool -|___must -| |___term -| |___term -| |___term -| -|___must_not - |___term -.... - -[source,csharp] ----- -Assert( - q => q.Query() && q.Query() && q.Query() && !q.Query(), - Query && Query && Query && !Query, - c=> - { - c.Bool.Must.Should().HaveCount(3); - c.Bool.MustNot.Should().HaveCount(1); - }); - -c.Bool.Must.Should().HaveCount(3); - -c.Bool.MustNot.Should().HaveCount(1); ----- - -Even more involved `term && term && term && !term && +term && +term` still only results in a single `bool` query: - -.... -bool -|___must -| |___term -| |___term -| |___term -| -|___must_not -| |___term -| -|___filter - |___term - |___term -.... - -You can still mix and match actual bool queries with the bool DSL e.g -`bool(must=term, term, term) && !term` would still merge into a single `bool` query. - -TIP: You can add parentheses to force evaluation order - -Also note that using shoulds as boosting factors can be really powerful so if you need this -always remember that you can mix and match an actual bool query with the bool dsl. - -There is another subtle situation where NEST will not blindly merge 2 bool queries with only should clauses. Imagine the following: - -`bool(should=term1, term2, term3, term4, minimum_should_match=2) || term5 || term6` - -if NEST identified both sides of the OR operation as only containing `should` clauses and it would -join them together it would give a different meaning to the `minimum_should_match` parameter of the first boolean query. -Rewriting this to a single bool with 5 `should` clauses would break because only matching on `term5` or `term6` should still be a hit. - -=== Locked bool queries - -NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, -NEST will treat these as locked - -Here we demonstrate that two locked `bool` queries are not combined - -neither are two `bool` queries where either the left or the right query is locked - -[source,csharp] ----- -c.Bool.Should.Should().HaveCount(2); - -var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); - -nestedBool.Bool.Should.Should().HaveCount(1); - -nestedBool.Bool.Name.Should().Be(firstName); ----- - -[source,csharp] ----- -assert(fluent.InvokeQuery(new QueryContainerDescriptor())); - -assert((QueryContainer)ois); ----- - +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +[[bool-queries]] +== Bool Queries + +Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, +take a single {ref_current}/query-dsl-bool-query.html[``bool`` query] with only two clauses + +[source,csharp] +---- +var searchResults = this.Client.Search(s => s + .Query(q => q + .Bool(b => b + .Should( + bs => bs.Term(p => p.Name, "x"), + bs => bs.Term(p => p.Name, "y") + ) + ) + ) +); +---- + +Now, imagine multiple nested bools; you'll realise that this quickly becomes an exercise in _hadouken indenting_ + +[[indent]] +.hadouken indenting example +image::{imagesdir}hadouken-indentation.jpg[dead indent] + +=== Operator Overloading + +For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. +The previous example now becomes the following with the fluent API + +[source,csharp] +---- +var searchResults = this.Client.Search(s => s + .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) +); +---- + +or, using the object initializer syntax + +[source,csharp] +---- +searchResults = this.Client.Search(new SearchRequest +{ + Query = new TermQuery { Field = "name", Value= "x" } + || new TermQuery { Field = Field(p=>p.Name), Value = "y" } +}); +---- + +A naive implementation of operator overloading would rewrite + +`term && term && term` to + +.... +bool +|___must + |___term + |___bool + |___must + |___term + |___term +.... + +As you can image this becomes unwieldy quite fast the more complex a query becomes NEST can spot these and +join them together to become a single bool query + +.... +bool +|___must + |___term + |___term + |___term +.... + +[source,csharp] +---- +Assert( + q => q.Query() && q.Query() && q.Query(), + Query && Query && Query, + c => c.Bool.Must.Should().HaveCount(3) + ); +---- + +The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator + +[source,csharp] +---- +Assert(q => !q.Query(), !Query, c => c.Bool.MustNot.Should().HaveCount(1)); +---- + +And to mark a query as a `filter` using the `+` operator + +[source,csharp] +---- +Assert(q => +q.Query(), +Query, c => c.Bool.Filter.Should().HaveCount(1)); +---- + +Both of these can be combined with `&&` to form a single bool query + +[source,csharp] +---- +Assert(q => !q.Query() && !q.Query(), !Query && !Query, c => c.Bool.MustNot.Should().HaveCount(2)); +---- + +[source,csharp] +---- +Assert(q => +q.Query() && +q.Query(), +Query && +Query, c => c.Bool.Filter.Should().HaveCount(2)); +---- + +=== Combining/Merging bool queries + +When combining multiple queries some or all possibly marked as `must_not` or `filter`, NEST still combines to a single bool query + +.... +bool +|___must +| |___term +| |___term +| |___term +| +|___must_not + |___term +.... + +[source,csharp] +---- +Assert( + q => q.Query() && q.Query() && q.Query() && !q.Query(), + Query && Query && Query && !Query, + c=> + { + c.Bool.Must.Should().HaveCount(3); + c.Bool.MustNot.Should().HaveCount(1); + }); + +c.Bool.Must.Should().HaveCount(3); + +c.Bool.MustNot.Should().HaveCount(1); +---- + +Even more involved `term && term && term && !term && +term && +term` still only results in a single `bool` query: + +.... +bool +|___must +| |___term +| |___term +| |___term +| +|___must_not +| |___term +| +|___filter + |___term + |___term +.... + +[source,csharp] +---- +Assert( + q => q.Query() && q.Query() && q.Query() && !q.Query() && +q.Query() && +q.Query(), + Query && Query && Query && !Query && +Query && +Query, + c => + { + c.Bool.Must.Should().HaveCount(3); + c.Bool.MustNot.Should().HaveCount(1); + c.Bool.Filter.Should().HaveCount(2); + }); + +c.Bool.Must.Should().HaveCount(3); + +c.Bool.MustNot.Should().HaveCount(1); + +c.Bool.Filter.Should().HaveCount(2); +---- + +You can still mix and match actual bool queries with the bool DSL e.g `bool(must=term, term, term) && !term` would still merge into a single `bool` query. + +[source,csharp] +---- +Assert( + q => q.Bool(b => b.Must(mq => mq.Query(), mq => mq.Query(), mq => mq.Query())) && !q.Query(), + new BoolQuery { Must = new QueryContainer[] { Query, Query, Query } } && !Query, + c => + { + c.Bool.Must.Should().HaveCount(3); + c.Bool.MustNot.Should().HaveCount(1); + }); + +c.Bool.Must.Should().HaveCount(3); + +c.Bool.MustNot.Should().HaveCount(1); +---- + +[source,csharp] +---- +Assert( + q => q.Query() && (q.Query() || q.Query() || q.Query()), + Query && (Query || Query || Query), + c => + { + c.Bool.Must.Should().HaveCount(2); + var lastClause = c.Bool.Must.Last() as IQueryContainer; + lastClause.Should().NotBeNull(); + lastClause.Bool.Should().NotBeNull(); + lastClause.Bool.Should.Should().HaveCount(3); + }); + +c.Bool.Must.Should().HaveCount(2); + +var lastClause = c.Bool.Must.Last() as IQueryContainer; + +lastClause.Should().NotBeNull(); + +lastClause.Bool.Should().NotBeNull(); + +lastClause.Bool.Should.Should().HaveCount(3); +---- + +TIP: You can add parentheses to force evaluation order + +Also note that using shoulds as boosting factors can be really powerful so if you need this +always remember that you can mix and match an actual bool query with the bool dsl. + +There is another subtle situation where NEST will not blindly merge 2 bool queries with only should clauses. Imagine the following: + +`bool(should=term1, term2, term3, term4, minimum_should_match=2) || term5 || term6` + +if NEST identified both sides of the OR operation as only containing `should` clauses and it would +join them together it would give a different meaning to the `minimum_should_match` parameter of the first boolean query. +Rewriting this to a single bool with 5 `should` clauses would break because only matching on `term5` or `term6` should still be a hit. + +[source,csharp] +---- +Assert( + q => q.Bool(b => b + .Should(mq => mq.Query(), mq => mq.Query(), mq => mq.Query(), mq => mq.Query()) + .MinimumShouldMatch(2) + ) + || !q.Query() || q.Query(), + new BoolQuery + { + Should = new QueryContainer[] { Query, Query, Query, Query }, + MinimumShouldMatch = 2 + } || !Query || Query, + c => + { + c.Bool.Should.Should().HaveCount(3); + var nestedBool = c.Bool.Should.First() as IQueryContainer; + nestedBool.Bool.Should.Should().HaveCount(4); + }); + +c.Bool.Should.Should().HaveCount(3); + +var nestedBool = c.Bool.Should.First() as IQueryContainer; + +nestedBool.Bool.Should.Should().HaveCount(4); +---- + +=== Locked bool queries + +NEST will not combine `bool` queries if any of the query metadata is set e.g if metadata such as `boost` or `name` are set, +NEST will treat these as locked + +Here we demonstrate that two locked `bool` queries are not combined + +[source,csharp] +---- +Assert( + q => q.Bool(b => b.Name("leftBool").Should(mq => mq.Query())) + || q.Bool(b => b.Name("rightBool").Should(mq => mq.Query())), + new BoolQuery { Name = "leftBool", Should = new QueryContainer[] { Query } } + || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, + c => AssertDoesNotJoinOntoLockedBool(c, "leftBool")); +---- + +neither are two `bool` queries where either right query is locked + +[source,csharp] +---- +Assert( + q => q.Bool(b => b.Should(mq => mq.Query())) + || q.Bool(b => b.Name("rightBool").Should(mq => mq.Query())), + new BoolQuery { Should = new QueryContainer[] { Query } } + || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, + c => AssertDoesNotJoinOntoLockedBool(c, "rightBool")); +---- + +or the left query is locked + +[source,csharp] +---- +Assert( + q => q.Bool(b => b.Name("leftBool").Should(mq => mq.Query())) + || q.Bool(b => b.Should(mq => mq.Query())), + new BoolQuery { Name = "leftBool", Should = new QueryContainer[] { Query } } + || new BoolQuery { Should = new QueryContainer[] { Query } }, + c => AssertDoesNotJoinOntoLockedBool(c, "leftBool")); +---- + +[source,csharp] +---- +c.Bool.Should.Should().HaveCount(2); + +var nestedBool = c.Bool.Should.Cast().First(b=>!string.IsNullOrEmpty(b.Bool?.Name)); + +nestedBool.Bool.Should.Should().HaveCount(1); + +nestedBool.Bool.Name.Should().Be(firstName); +---- + +[source,csharp] +---- +assert(fluent.InvokeQuery(new QueryContainerDescriptor())); + +assert((QueryContainer)ois); +---- + diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc index d0741bb2dc2..57c6af17071 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -45,10 +45,10 @@ lotsOfAnds.Bool.Must.Should().NotBeEmpty().And.HaveCount(100); ---- ReturnsBool(Query && Query, q => q.Query() && q.Query(), b => { - b.Must.Should().NotBeEmpty().And.HaveCount(2); - b.Should.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.Filter.Should().BeNull(); + b.Must.Should().NotBeEmpty().And.HaveCount(2); + b.Should.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); }); b.Must.Should().NotBeEmpty().And.HaveCount(2); b.Should.Should().BeNull(); @@ -56,41 +56,41 @@ b.MustNot.Should().BeNull(); b.Filter.Should().BeNull(); ReturnsBool(Query && Query && ConditionlessQuery, q => q.Query() && q.Query() && q.ConditionlessQuery(), b => { - b.Must.Should().NotBeEmpty().And.HaveCount(2); - b.Should.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.Filter.Should().BeNull(); + b.Must.Should().NotBeEmpty().And.HaveCount(2); + b.Should.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); }); b.Must.Should().NotBeEmpty().And.HaveCount(2); b.Should.Should().BeNull(); b.MustNot.Should().BeNull(); b.Filter.Should().BeNull(); ReturnsSingleQuery(Query && ConditionlessQuery, q => q.Query() && q.ConditionlessQuery(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(ConditionlessQuery && Query, q => q.ConditionlessQuery() && q.Query(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(Query && NullQuery, q => q.Query() && q.NullQuery(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(NullQuery && Query, q=> q.NullQuery() && q.Query(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(ConditionlessQuery && ConditionlessQuery && ConditionlessQuery && Query, - q => q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.Query(), - c => c.Term.Value.Should().NotBeNull()); + q => q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.Query(), + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery( - NullQuery && NullQuery && ConditionlessQuery && Query, - q=>q.NullQuery() && q.NullQuery() && q.ConditionlessQuery() && q.Query(), - c => c.Term.Value.Should().NotBeNull()); + NullQuery && NullQuery && ConditionlessQuery && Query, + q=>q.NullQuery() && q.NullQuery() && q.ConditionlessQuery() && q.Query(), + c => c.Term.Value.Should().NotBeNull()); ReturnsNull(NullQuery && ConditionlessQuery, q=> q.NullQuery() && q.ConditionlessQuery()); ReturnsNull(ConditionlessQuery && NullQuery, q=>q.ConditionlessQuery() && q.NullQuery()); ReturnsNull(ConditionlessQuery && ConditionlessQuery, q=>q.ConditionlessQuery() && q.ConditionlessQuery()); ReturnsNull( - ConditionlessQuery && ConditionlessQuery && ConditionlessQuery && ConditionlessQuery, - q=>q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() + ConditionlessQuery && ConditionlessQuery && ConditionlessQuery && ConditionlessQuery, + q=>q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() ); ReturnsNull( - NullQuery && ConditionlessQuery && ConditionlessQuery && ConditionlessQuery, - q=>q.NullQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() + NullQuery && ConditionlessQuery && ConditionlessQuery && ConditionlessQuery, + q=>q.NullQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() ); ---- diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc index b4a163a38e4..021d856ae2a 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -45,10 +45,10 @@ lotsOfNots.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); ---- ReturnsBool(!Query && !Query, q => !q.Query() && !q.Query(), b => { - b.MustNot.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.Should.Should().BeNull(); - b.Filter.Should().BeNull(); + b.MustNot.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.Should.Should().BeNull(); + b.Filter.Should().BeNull(); }); b.MustNot.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); @@ -56,15 +56,15 @@ b.Should.Should().BeNull(); b.Filter.Should().BeNull(); ReturnsBool(!Query || !Query || !ConditionlessQuery, q => !q.Query() || !q.Query() || !q.ConditionlessQuery(), b => { - b.Should.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.Filter.Should().BeNull(); - foreach (IQueryContainer q in b.Should) - { - q.Bool.Should().NotBeNull(); - q.Bool.MustNot.Should().NotBeEmpty().And.HaveCount(1); - } + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); + foreach (IQueryContainer q in b.Should) + { + q.Bool.Should().NotBeNull(); + q.Bool.MustNot.Should().NotBeEmpty().And.HaveCount(1); + } }); b.Should.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); @@ -73,31 +73,31 @@ b.Filter.Should().BeNull(); q.Bool.Should().NotBeNull(); q.Bool.MustNot.Should().NotBeEmpty().And.HaveCount(1); ReturnsSingleQuery(!Query || !ConditionlessQuery, q => !q.Query() || !q.ConditionlessQuery(), - c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(!ConditionlessQuery || !Query, q => !q.ConditionlessQuery() || !q.Query(), - c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(!Query || !NullQuery, q => !q.Query() || !q.NullQuery(), - c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(!NullQuery && !Query, q => !q.NullQuery() && !q.Query(), - c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(!ConditionlessQuery || !ConditionlessQuery && !ConditionlessQuery || !Query, - q => !q.ConditionlessQuery() || !q.ConditionlessQuery() && !q.ConditionlessQuery() || !q.Query(), - c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); + q => !q.ConditionlessQuery() || !q.ConditionlessQuery() && !q.ConditionlessQuery() || !q.Query(), + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery( - !NullQuery || !NullQuery || !ConditionlessQuery || !Query, - q => !q.NullQuery() || !q.NullQuery() || !q.ConditionlessQuery() || !q.Query(), - c => c.Bool.MustNot.Should().NotBeNull()); + !NullQuery || !NullQuery || !ConditionlessQuery || !Query, + q => !q.NullQuery() || !q.NullQuery() || !q.ConditionlessQuery() || !q.Query(), + c => c.Bool.MustNot.Should().NotBeNull()); ReturnsNull(!NullQuery || !ConditionlessQuery, q => !q.NullQuery() || !q.ConditionlessQuery()); ReturnsNull(!ConditionlessQuery && !NullQuery, q => !q.ConditionlessQuery() && !q.NullQuery()); ReturnsNull(!ConditionlessQuery || !ConditionlessQuery, q => !q.ConditionlessQuery() || !q.ConditionlessQuery()); ReturnsNull( - !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery, - q => !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() + !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery, + q => !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() ); ReturnsNull( - !NullQuery || !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery, - q => !q.NullQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() + !NullQuery || !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery, + q => !q.NullQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() ); ---- diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc index 80f474ad975..b072709a6d3 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -45,10 +45,10 @@ lotsOfOrs.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); ---- ReturnsBool(Query || Query, q => q.Query() || q.Query(), b => { - b.Should.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.Filter.Should().BeNull(); + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); }); b.Should.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); @@ -56,10 +56,10 @@ b.MustNot.Should().BeNull(); b.Filter.Should().BeNull(); ReturnsBool(Query || Query || ConditionlessQuery, q => q.Query() || q.Query() || q.ConditionlessQuery(), b => { - b.Should.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.Filter.Should().BeNull(); + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); }); b.Should.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); @@ -67,41 +67,41 @@ b.MustNot.Should().BeNull(); b.Filter.Should().BeNull(); ReturnsBool(Query || Query || ConditionlessQuery, q => q.Query() || q.Query() || q.ConditionlessQuery(), b => { - b.Should.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.Filter.Should().BeNull(); + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); }); b.Should.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); b.MustNot.Should().BeNull(); b.Filter.Should().BeNull(); ReturnsSingleQuery(Query || ConditionlessQuery, q => q.Query() || q.ConditionlessQuery(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(ConditionlessQuery || Query, q => q.ConditionlessQuery() || q.Query(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(Query || NullQuery, q => q.Query() || q.NullQuery(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(NullQuery || Query, q=> q.NullQuery() || q.Query(), - c => c.Term.Value.Should().NotBeNull()); + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery(ConditionlessQuery || ConditionlessQuery || ConditionlessQuery || Query, - q => q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.Query(), - c => c.Term.Value.Should().NotBeNull()); + q => q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.Query(), + c => c.Term.Value.Should().NotBeNull()); ReturnsSingleQuery( - NullQuery || NullQuery || ConditionlessQuery || Query, - q=>q.NullQuery() || q.NullQuery() || q.ConditionlessQuery() || q.Query(), - c => c.Term.Value.Should().NotBeNull()); + NullQuery || NullQuery || ConditionlessQuery || Query, + q=>q.NullQuery() || q.NullQuery() || q.ConditionlessQuery() || q.Query(), + c => c.Term.Value.Should().NotBeNull()); ReturnsNull(NullQuery || ConditionlessQuery, q=> q.NullQuery() || q.ConditionlessQuery()); ReturnsNull(ConditionlessQuery || NullQuery, q=>q.ConditionlessQuery() || q.NullQuery()); ReturnsNull(ConditionlessQuery || ConditionlessQuery, q=>q.ConditionlessQuery() || q.ConditionlessQuery()); ReturnsNull( - ConditionlessQuery || ConditionlessQuery || ConditionlessQuery || ConditionlessQuery, - q=>q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() + ConditionlessQuery || ConditionlessQuery || ConditionlessQuery || ConditionlessQuery, + q=>q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() ); ReturnsNull( - NullQuery || ConditionlessQuery || ConditionlessQuery || ConditionlessQuery, - q=>q.NullQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() + NullQuery || ConditionlessQuery || ConditionlessQuery || ConditionlessQuery, + q=>q.NullQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() ); ---- diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc index 1363e9c70ed..9246aac2caf 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -56,10 +56,10 @@ c.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); ---- ReturnsBool(+Query && +Query, q => +q.Query() && +q.Query(), b => { - b.Filter.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.Should.Should().BeNull(); - b.MustNot.Should().BeNull(); + b.Filter.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.Should.Should().BeNull(); + b.MustNot.Should().BeNull(); }); b.Filter.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); @@ -67,15 +67,15 @@ b.Should.Should().BeNull(); b.MustNot.Should().BeNull(); ReturnsBool(+Query || +Query || +ConditionlessQuery, q => +q.Query() || +q.Query() || +q.ConditionlessQuery(), b => { - b.Should.Should().NotBeEmpty().And.HaveCount(2); - b.Must.Should().BeNull(); - b.MustNot.Should().BeNull(); - b.MustNot.Should().BeNull(); - foreach (IQueryContainer q in b.Should) - { - q.Bool.Should().NotBeNull(); - q.Bool.Filter.Should().NotBeEmpty().And.HaveCount(1); - } + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.MustNot.Should().BeNull(); + foreach (IQueryContainer q in b.Should) + { + q.Bool.Should().NotBeNull(); + q.Bool.Filter.Should().NotBeEmpty().And.HaveCount(1); + } }); b.Should.Should().NotBeEmpty().And.HaveCount(2); b.Must.Should().BeNull(); @@ -84,31 +84,31 @@ b.MustNot.Should().BeNull(); q.Bool.Should().NotBeNull(); q.Bool.Filter.Should().NotBeEmpty().And.HaveCount(1); ReturnsSingleQuery(+Query || +ConditionlessQuery, q => +q.Query() || +q.ConditionlessQuery(), - c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(+ConditionlessQuery || +Query, q => +q.ConditionlessQuery() || +q.Query(), - c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(+Query || +NullQuery, q => +q.Query() || +q.NullQuery(), - c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(+NullQuery && +Query, q => +q.NullQuery() && +q.Query(), - c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery(+ConditionlessQuery || +ConditionlessQuery && +ConditionlessQuery || +Query, - q => +q.ConditionlessQuery() || +q.ConditionlessQuery() && +q.ConditionlessQuery() || +q.Query(), - c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); + q => +q.ConditionlessQuery() || +q.ConditionlessQuery() && +q.ConditionlessQuery() || +q.Query(), + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); ReturnsSingleQuery( - +NullQuery || +NullQuery || +ConditionlessQuery || +Query, - q => +q.NullQuery() || +q.NullQuery() || +q.ConditionlessQuery() || +q.Query(), - c => c.Bool.Filter.Should().NotBeNull()); + +NullQuery || +NullQuery || +ConditionlessQuery || +Query, + q => +q.NullQuery() || +q.NullQuery() || +q.ConditionlessQuery() || +q.Query(), + c => c.Bool.Filter.Should().NotBeNull()); ReturnsNull(+NullQuery || +ConditionlessQuery, q => +q.NullQuery() || +q.ConditionlessQuery()); ReturnsNull(+ConditionlessQuery && +NullQuery, q => +q.ConditionlessQuery() && +q.NullQuery()); ReturnsNull(+ConditionlessQuery || +ConditionlessQuery, q => +q.ConditionlessQuery() || +q.ConditionlessQuery()); ReturnsNull( - +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery, - q => +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() + +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery, + q => +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() ); ReturnsNull( - +NullQuery || +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery, - q => +q.NullQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() + +NullQuery || +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery, + q => +q.NullQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() ); ---- diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index adc56e8cd2e..3f1f067a7c5 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -7,6 +7,36 @@ [[and-query-usage]] == And Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.And(c => c + .Name("named_query") + .Boost(1.1) + .Filters( + qq => qq.MatchAll(m => m.Name("query1")), + qq => qq.MatchAll(m => m.Name("query2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new AndQuery() +{ + Name = "named_query", + Boost = 1.1, + Filters = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, + } +} +---- + [source,javascript] .Example json output ---- @@ -30,18 +60,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new AndQuery() - { -Name = "named_query", -Boost = 1.1, -Filters = new QueryContainer[] { - new MatchAllQuery() { Name = "query1" }, - new MatchAllQuery() { Name = "query2" }, -} - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc index ebd62d17f5e..eed5831eaf7 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -7,62 +7,21 @@ [[bool-dsl-complex-query-usage]] == Bool Dsl Complex Query Usage +=== Fluent DSL Example + [source,csharp] ---- -new - { -@bool = new -{ - should = new object[] { - new { - @bool = new { - must = new [] { - new { term = new { x = new { value = "y" } } }, - new { term = new { x = new { value = "y" } } } - } - } - }, - new { - @bool = new { - must = new object[] { - new { - @bool = new { - should = new object [] { - new { - @bool = new { - filter = new [] { - new { term = new { x = new { value = "y" } } } - } - } - }, - new { - @bool = new { - filter = new [] { - new { term = new { x = new { value = "y" } } } - } - } - }, - new { - @bool = new { - must_not = new [] { - new { term = new { x = new { value = "y" } } }, - new { term = new { x = new { value = "y" } } } - } - } - }, - new { term = new { x = new { value = "y" } } }, - new { term = new { x = new { value = "y" } } }, - new { term = new { x = new { value = "y" } } } - } - } - }, - base.QueryJson, - } - } - } - } -} - } +q.Query() && q.Query() +//second bool +|| ( + //complex nested bool + (+q.Query() || +q.Query() || !q.Query() && (!q.Query() && !q.ConditionlessQuery())) + // simple nested or + && (q.Query() || q.Query() || q.Query()) + //all conditionless bool + && (q.NullQuery() || +q.ConditionlessQuery() || !q.ConditionlessQuery()) + // actual bool query + && (base.QueryFluent(q))) ---- === Object Initializer Syntax Example @@ -72,14 +31,150 @@ new Query && Query //second bool || ( - //complex nested bool - (+Query || +Query || !Query && (!Query && !ConditionlessQuery)) - // simple nested or - && (Query || Query || Query) - //all conditionless bool - && (NullQuery || +ConditionlessQuery || !ConditionlessQuery) - // actual bool query - && (base.QueryInitializer)) + //complex nested bool + (+Query || +Query || !Query && (!Query && !ConditionlessQuery)) + // simple nested or + && (Query || Query || Query) + //all conditionless bool + && (NullQuery || +ConditionlessQuery || !ConditionlessQuery) + // actual bool query + && (base.QueryInitializer)) +---- + +[source,javascript] +.Example json output +---- +{ + "bool": { + "should": [ + { + "bool": { + "must": [ + { + "term": { + "x": { + "value": "y" + } + } + }, + { + "term": { + "x": { + "value": "y" + } + } + } + ] + } + }, + { + "bool": { + "must": [ + { + "bool": { + "should": [ + { + "bool": { + "filter": [ + { + "term": { + "x": { + "value": "y" + } + } + } + ] + } + }, + { + "bool": { + "filter": [ + { + "term": { + "x": { + "value": "y" + } + } + } + ] + } + }, + { + "bool": { + "must_not": [ + { + "term": { + "x": { + "value": "y" + } + } + }, + { + "term": { + "x": { + "value": "y" + } + } + } + ] + } + }, + { + "term": { + "x": { + "value": "y" + } + } + }, + { + "term": { + "x": { + "value": "y" + } + } + }, + { + "term": { + "x": { + "value": "y" + } + } + } + ] + } + }, + { + "bool": { + "must": [ + { + "match_all": {} + } + ], + "must_not": [ + { + "match_all": {} + } + ], + "should": [ + { + "match_all": {} + } + ], + "filter": [ + { + "match_all": {} + } + ], + "minimum_should_match": 1, + "boost": 2.0 + } + } + ] + } + } + ] + } +} ---- [source,csharp] diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc index fe7c1a4bfd5..d2b1cc27c36 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -7,6 +7,35 @@ [[bool-query-usage]] == Bool Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Bool(b => b + .MustNot(m => m.MatchAll()) + .Should(m => m.MatchAll()) + .Must(m => m.MatchAll()) + .Filter(f => f.MatchAll()) + .MinimumShouldMatch(1) + .Boost(2)) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new BoolQuery() +{ + MustNot = new QueryContainer[] { new MatchAllQuery() }, + Should = new QueryContainer[] { new MatchAllQuery() }, + Must = new QueryContainer[] { new MatchAllQuery() }, + Filter = new QueryContainer[] { new MatchAllQuery() }, + MinimumShouldMatch = 1, + Boost = 2 +} +---- + [source,javascript] .Example json output ---- @@ -38,18 +67,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new BoolQuery() -{ - MustNot = new QueryContainer[] { new MatchAllQuery() }, - Should = new QueryContainer[] { new MatchAllQuery() }, - Must = new QueryContainer[] { new MatchAllQuery() }, - Filter = new QueryContainer[] { new MatchAllQuery() }, - MinimumShouldMatch = 1, - Boost = 2 -} ----- - diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc index 8f20d2b14db..0129cd6434d 100644 --- a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -7,6 +7,34 @@ [[boosting-query-usage]] == Boosting Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Boosting(c => c + .Name("named_query") + .Boost(1.1) + .Positive(qq => qq.MatchAll(m => m.Name("filter"))) + .Negative(qq => qq.MatchAll(m => m.Name("query"))) + .NegativeBoost(1.12) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new BoostingQuery() +{ + Name = "named_query", + Boost = 1.1, + PositiveQuery = new MatchAllQuery { Name ="filter" }, + NegativeQuery= new MatchAllQuery() { Name = "query" }, + NegativeBoost = 1.12 +} +---- + [source,javascript] .Example json output ---- @@ -29,17 +57,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new BoostingQuery() - { -Name = "named_query", -Boost = 1.1, -PositiveQuery = new MatchAllQuery { Name ="filter" }, -NegativeQuery= new MatchAllQuery() { Name = "query" }, -NegativeBoost = 1.12 - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc index 50768ae2ced..64ef531eb41 100644 --- a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -7,6 +7,30 @@ [[constant-score-query-usage]] == Constant Score Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.ConstantScore(c => c + .Name("named_query") + .Boost(1.1) + .Filter(qq => qq.MatchAll(m => m.Name("filter"))) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new ConstantScoreQuery() +{ + Name = "named_query", + Boost = 1.1, + Filter = new MatchAllQuery { Name = "filter" }, +} +---- + [source,javascript] .Example json output ---- @@ -23,15 +47,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new ConstantScoreQuery() - { -Name = "named_query", -Boost = 1.1, -Filter = new MatchAllQuery { Name = "filter" }, - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc index 957510ac438..1fd63790b5c 100644 --- a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -7,6 +7,38 @@ [[dismax-query-usage]] == Dismax Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.DisMax(c => c + .Name("named_query") + .Boost(1.1) + .TieBreaker(1.11) + .Queries( + qq => qq.MatchAll(m => m.Name("query1")), + qq => qq.MatchAll(m => m.Name("query2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new DisMaxQuery() +{ + Name = "named_query", + Boost = 1.1, + TieBreaker = 1.11, + Queries = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, + } +} +---- + [source,javascript] .Example json output ---- @@ -31,19 +63,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new DisMaxQuery() - { -Name = "named_query", -Boost = 1.1, -TieBreaker = 1.11, -Queries = new QueryContainer[] { - new MatchAllQuery() { Name = "query1" }, - new MatchAllQuery() { Name = "query2" }, -} - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc index f0a67232d96..ed35edf83a5 100644 --- a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -7,6 +7,32 @@ [[filtered-query-usage]] == Filtered Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Filtered(c => c + .Name("named_query") + .Boost(1.1) + .Filter(qq => qq.MatchAll(m => m.Name("filter"))) + .Query(qq => qq.MatchAll(m => m.Name("query"))) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new FilteredQuery() +{ + Name = "named_query", + Boost = 1.1, + Filter = new MatchAllQuery { Name ="filter" }, + Query = new MatchAllQuery() { Name = "query" }, +} +---- + [source,javascript] .Example json output ---- @@ -28,16 +54,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new FilteredQuery() - { -Name = "named_query", -Boost = 1.1, -Filter = new MatchAllQuery { Name ="filter" }, -Query = new MatchAllQuery() { Name = "query" }, - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc index 01dfbfc45e7..095e1eb11af 100644 --- a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -7,6 +7,62 @@ [[function-score-query-usage]] == Function Score Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.FunctionScore(c => c + .Name("named_query") + .Boost(1.1) + .Query(qq => qq.MatchAll()) + .BoostMode(FunctionBoostMode.Multiply) + .ScoreMode(FunctionScoreMode.Sum) + .MaxBoost(20.0) + .MinScore(1.0) + .Functions(f => f + .Exponential(b => b.Field(p => p.NumberOfCommits).Decay(0.5).Origin(1.0).Scale(0.1).Weight(2.1)) + .GaussDate(b => b.Field(p => p.LastActivity).Origin(DateMath.Now).Decay(0.5).Scale("1d")) + .LinearGeoLocation(b => b.Field(p => p.Location).Origin(new GeoLocation(70, -70)).Scale(Distance.Miles(1)).MultiValueMode(MultiValueMode.Average)) + .FieldValueFactor(b => b.Field("x").Factor(1.1).Missing(0.1).Modifier(FieldValueFactorModifier.Ln)) + .RandomScore(1337) + .RandomScore("randomstring") + .Weight(1.0) + .ScriptScore(ss => ss.Script(s => s.File("x"))) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new FunctionScoreQuery() +{ + Name = "named_query", + Boost = 1.1, + Query = new MatchAllQuery { }, + BoostMode = FunctionBoostMode.Multiply, + ScoreMode = FunctionScoreMode.Sum, + MaxBoost = 20.0, + MinScore = 1.0, + Functions = new List + { + new ExponentialDecayFunction { Origin = 1.0, Decay = 0.5, Field = Field(p=>p.NumberOfCommits), Scale = 0.1, Weight = 2.1 }, + new GaussDateDecayFunction { Origin = DateMath.Now, Field = Field(p=>p.LastActivity), Decay = 0.5, Scale = TimeSpan.FromDays(1) }, + new LinearGeoDecayFunction { Origin = new GeoLocation(70, -70), Field = Field(p=>p.Location), Scale = Distance.Miles(1), MultiValueMode = MultiValueMode.Average }, + new FieldValueFactorFunction + { + Field = "x", Factor = 1.1, Missing = 0.1, Modifier = FieldValueFactorModifier.Ln + }, + new RandomScoreFunction { Seed = 1337 }, + new RandomScoreFunction { Seed = "randomstring" }, + new WeightFunction { Weight = 1.0}, + new ScriptScoreFunction { Script = new ScriptQuery { File = "x" } } + } +} +---- + [source,javascript] .Example json output ---- @@ -86,33 +142,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new FunctionScoreQuery() - { -Name = "named_query", -Boost = 1.1, -Query = new MatchAllQuery { }, -BoostMode = FunctionBoostMode.Multiply, -ScoreMode = FunctionScoreMode.Sum, -MaxBoost = 20.0, -MinScore = 1.0, -Functions = new List -{ - new ExponentialDecayFunction { Origin = 1.0, Decay = 0.5, Field = Field(p=>p.NumberOfCommits), Scale = 0.1, Weight = 2.1 }, - new GaussDateDecayFunction { Origin = DateMath.Now, Field = Field(p=>p.LastActivity), Decay = 0.5, Scale = TimeSpan.FromDays(1) }, - new LinearGeoDecayFunction { Origin = new GeoLocation(70, -70), Field = Field(p=>p.Location), Scale = Distance.Miles(1), MultiValueMode = MultiValueMode.Average }, - new FieldValueFactorFunction - { - Field = "x", Factor = 1.1, Missing = 0.1, Modifier = FieldValueFactorModifier.Ln - }, - new RandomScoreFunction { Seed = 1337 }, - new RandomScoreFunction { Seed = "randomstring" }, - new WeightFunction { Weight = 1.0}, - new ScriptScoreFunction { Script = new ScriptQuery { File = "x" } } -} - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc index 0bf71824bda..350006fefa9 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -7,6 +7,34 @@ [[indices-no-match-query-usage]] == Indices No Match Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Indices(c => c + .Name("named_query") + .Boost(1.1) + .Indices(Nest.Indices.All) + .Query(qq => qq.MatchAll()) + .NoMatchQuery(NoMatchShortcut.All) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new IndicesQuery() +{ + Name = "named_query", + Boost = 1.1, + Indices = Nest.Indices.All, + Query = new MatchAllQuery(), + NoMatchQuery = new NoMatchQueryContainer { Shortcut = NoMatchShortcut.All } +} +---- + [source,javascript] .Example json output ---- @@ -25,17 +53,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new IndicesQuery() - { -Name = "named_query", -Boost = 1.1, -Indices = Nest.Indices.All, -Query = new MatchAllQuery(), -NoMatchQuery = new NoMatchQueryContainer { Shortcut = NoMatchShortcut.All } - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc index 9c88e4351af..33f957a3d9f 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -7,6 +7,35 @@ [[indices-query-usage]] == Indices Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Indices(c => c + .Name("named_query") + .Boost(1.1) + .Indices(Index()) + .Query(qq => qq.MatchAll()) + .NoMatchQuery(qq => qq.MatchAll(m => m.Name("no_match"))) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new IndicesQuery() +{ + Name = "named_query", + Boost = 1.1, + Indices = Index(), + Query = new MatchAllQuery(), + NoMatchQuery = new MatchAllQuery { Name ="no_match" } + +} +---- + [source,javascript] .Example json output ---- @@ -29,18 +58,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new IndicesQuery() - { -Name = "named_query", -Boost = 1.1, -Indices = Index(), -Query = new MatchAllQuery(), -NoMatchQuery = new MatchAllQuery { Name ="no_match" } - - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc index 2ba54bd24c0..a8c2bc166fb 100644 --- a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -7,6 +7,30 @@ [[limit-query-usage]] == Limit Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Limit(c => c + .Name("named_query") + .Boost(1.1) + .Limit(100) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new LimitQuery +{ + Name = "named_query", + Boost = 1.1, + Limit = 100 +} +---- + [source,javascript] .Example json output ---- @@ -19,15 +43,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new LimitQuery - { -Name = "named_query", -Boost = 1.1, -Limit = 100 - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc index 30a63f28247..5adf9ff6b3f 100644 --- a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -7,6 +7,36 @@ [[not-query-usage]] == Not Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Not(c => c + .Name("named_query") + .Boost(1.1) + .Filters( + qq => qq.MatchAll(m => m.Name("query1")), + qq => qq.MatchAll(m => m.Name("query2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new NotQuery() +{ + Name = "named_query", + Boost = 1.1, + Filters = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, + } +} +---- + [source,javascript] .Example json output ---- @@ -30,18 +60,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new NotQuery() - { -Name = "named_query", -Boost = 1.1, -Filters = new QueryContainer[] { - new MatchAllQuery() { Name = "query1" }, - new MatchAllQuery() { Name = "query2" }, -} - } ----- - diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc index 97cb2f0f14e..445009593b4 100644 --- a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -7,6 +7,36 @@ [[or-query-usage]] == Or Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Or(c => c + .Name("named_query") + .Boost(1.1) + .Filters( + qq => qq.MatchAll(m => m.Name("query1")), + qq => qq.MatchAll(m => m.Name("query2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new OrQuery() +{ + Name = "named_query", + Boost = 1.1, + Filters = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, + } +} +---- + [source,javascript] .Example json output ---- @@ -30,18 +60,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new OrQuery() - { -Name = "named_query", -Boost = 1.1, -Filters = new QueryContainer[] { - new MatchAllQuery() { Name = "query1" }, - new MatchAllQuery() { Name = "query2" }, -} - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc index fdb556cfc8c..838a1270d4f 100644 --- a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -7,6 +7,44 @@ [[common-terms-usage]] == Common Terms Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.CommonTerms(c => c + .Field(p => p.Description) + .Analyzer("standard") + .Boost(1.1) + .CutoffFrequency(0.001) + .DisableCoord() + .HighFrequencyOperator(Operator.And) + .LowFrequencyOperator(Operator.Or) + .MinimumShouldMatch(1) + .Name("named_query") + .Query("nelly the elephant not as a") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new CommonTermsQuery() +{ + Field = Field(p => p.Description), + Analyzer = "standard", + Boost = 1.1, + CutoffFrequency = 0.001, + DisableCoord = true, + HighFrequencyOperator = Operator.And, + LowFrequencyOperator = Operator.Or, + MinimumShouldMatch = 1, + Name = "named_query", + Query = "nelly the elephant not as a" +} +---- + [source,javascript] .Example json output ---- @@ -27,22 +65,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new CommonTermsQuery() - { -Field = Field(p => p.Description), -Analyzer = "standard", -Boost = 1.1, -CutoffFrequency = 0.001, -DisableCoord = true, -HighFrequencyOperator = Operator.And, -LowFrequencyOperator = Operator.Or, -MinimumShouldMatch = 1, -Name = "named_query", -Query = "nelly the elephant not as a" - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc index 9fcef97e292..f0e19a71af7 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -7,6 +7,54 @@ [[match-phrase-prefix-usage]] == Match Phrase Prefix Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.MatchPhrasePrefix(c => c + .Field(p => p.Description) + .Analyzer("standard") + .Boost(1.1) + .CutoffFrequency(0.001) + .Query("hello worl") + .Fuzziness(Fuzziness.Auto) + .Lenient() + .FuzzyTranspositions() + .MaxExpansions(2) + .MinimumShouldMatch(2) + .PrefixLength(2) + .Operator(Operator.Or) + .FuzzyRewrite(RewriteMultiTerm.ConstantScoreBoolean) + .Slop(2) + .Name("named_query") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MatchPhrasePrefixQuery +{ + Field = Field(p => p.Description), + Analyzer = "standard", + Boost = 1.1, + Name = "named_query", + CutoffFrequency = 0.001, + Query = "hello worl", + Fuzziness = Fuzziness.Auto, + FuzzyTranspositions = true, + MinimumShouldMatch = 2, + FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, + MaxExpansions = 2, + Slop = 2, + Lenient = true, + Operator = Operator.Or, + PrefixLength = 2 +} +---- + [source,javascript] .Example json output ---- @@ -33,27 +81,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new MatchPhrasePrefixQuery - { -Field = Field(p => p.Description), -Analyzer = "standard", -Boost = 1.1, -Name = "named_query", -CutoffFrequency = 0.001, -Query = "hello worl", -Fuzziness = Fuzziness.Auto, -FuzzyTranspositions = true, -MinimumShouldMatch = 2, -FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, -MaxExpansions = 2, -Slop = 2, -Lenient = true, -Operator = Operator.Or, -PrefixLength = 2 - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc index 9763dc9f736..2610ac4ada4 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -7,6 +7,54 @@ [[match-phrase-usage]] == Match Phrase Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.MatchPhrase(c => c + .Field(p => p.Description) + .Analyzer("standard") + .Boost(1.1) + .CutoffFrequency(0.001) + .Query("hello world") + .Fuzziness(Fuzziness.Auto) + .Lenient() + .FuzzyTranspositions() + .MaxExpansions(2) + .MinimumShouldMatch(2) + .PrefixLength(2) + .Operator(Operator.Or) + .FuzzyRewrite(RewriteMultiTerm.ConstantScoreBoolean) + .Slop(2) + .Name("named_query") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MatchPhraseQuery +{ + Field = Field(p=>p.Description), + Analyzer = "standard", + Boost = 1.1, + Name = "named_query", + CutoffFrequency = 0.001, + Query = "hello world", + Fuzziness = Fuzziness.Auto, + FuzzyTranspositions = true, + MinimumShouldMatch = 2, + FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, + MaxExpansions = 2, + Slop = 2, + Lenient = true, + Operator = Operator.Or, + PrefixLength = 2 +} +---- + [source,javascript] .Example json output ---- @@ -33,27 +81,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new MatchPhraseQuery - { -Field = Field(p=>p.Description), -Analyzer = "standard", -Boost = 1.1, -Name = "named_query", -CutoffFrequency = 0.001, -Query = "hello world", -Fuzziness = Fuzziness.Auto, -FuzzyTranspositions = true, -MinimumShouldMatch = 2, -FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, -MaxExpansions = 2, -Slop = 2, -Lenient = true, -Operator = Operator.Or, -PrefixLength = 2 - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc index 86ea6d8013d..ecc310194eb 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -7,6 +7,54 @@ [[match-usage]] == Match Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Match(c => c + .Field(p => p.Description) + .Analyzer("standard") + .Boost(1.1) + .CutoffFrequency(0.001) + .Query("hello world") + .Fuzziness(Fuzziness.Auto) + .Lenient() + .FuzzyTranspositions() + .MaxExpansions(2) + .MinimumShouldMatch(2) + .PrefixLength(2) + .Operator(Operator.Or) + .FuzzyRewrite(RewriteMultiTerm.ConstantScoreBoolean) + .Slop(2) + .Name("named_query") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MatchQuery +{ + Field = Field(p=>p.Description), + Analyzer = "standard", + Boost = 1.1, + Name = "named_query", + CutoffFrequency = 0.001, + Query = "hello world", + Fuzziness = Fuzziness.Auto, + FuzzyTranspositions = true, + MinimumShouldMatch = 2, + FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, + MaxExpansions = 2, + Slop = 2, + Lenient = true, + Operator = Operator.Or, + PrefixLength = 2 +} +---- + [source,javascript] .Example json output ---- @@ -32,27 +80,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new MatchQuery - { -Field = Field(p=>p.Description), -Analyzer = "standard", -Boost = 1.1, -Name = "named_query", -CutoffFrequency = 0.001, -Query = "hello world", -Fuzziness = Fuzziness.Auto, -FuzzyTranspositions = true, -MinimumShouldMatch = 2, -FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, -MaxExpansions = 2, -Slop = 2, -Lenient = true, -Operator = Operator.Or, -PrefixLength = 2 - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index 16aee90125f..12e44e1907e 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -7,6 +7,56 @@ [[multi-match-usage]] == Multi Match Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.MultiMatch(c => c + .Fields(f => f.Field(p=>p.Description).Field("myOtherField")) + .Query("hello world") + .Analyzer("standard") + .Boost(1.1) + .Slop(2) + .Fuzziness(Fuzziness.Auto) + .PrefixLength(2) + .MaxExpansions(2) + .Operator(Operator.Or) + .MinimumShouldMatch(2) + .FuzzyRewrite(RewriteMultiTerm.ConstantScoreBoolean) + .TieBreaker(1.1) + .CutoffFrequency(0.001) + .Lenient() + .ZeroTermsQuery(ZeroTermsQuery.All) + .Name("named_query") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MultiMatchQuery +{ + Fields = Field(p=>p.Description).And("myOtherField"), + Query = "hello world", + Analyzer = "standard", + Boost = 1.1, + Slop = 2, + Fuzziness = Fuzziness.Auto, + PrefixLength = 2, + MaxExpansions = 2, + Operator = Operator.Or, + MinimumShouldMatch = 2, + FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, + TieBreaker = 1.1, + CutoffFrequency = 0.001, + Lenient = true, + ZeroTermsQuery = ZeroTermsQuery.All, + Name = "named_query", +} +---- + [source,javascript] .Example json output ---- @@ -35,28 +85,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new MultiMatchQuery - { -Fields = Field(p=>p.Description).And("myOtherField"), -Query = "hello world", -Analyzer = "standard", -Boost = 1.1, -Slop = 2, -Fuzziness = Fuzziness.Auto, -PrefixLength = 2, -MaxExpansions = 2, -Operator = Operator.Or, -MinimumShouldMatch = 2, -FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, -TieBreaker = 1.1, -CutoffFrequency = 0.001, -Lenient = true, -ZeroTermsQuery = ZeroTermsQuery.All, -Name = "named_query", - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc index 732cb3a707e..da703d9af6f 100644 --- a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -7,6 +7,78 @@ [[query-string-usage]] == Query String Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.QueryString(c => c + .Name("named_query") + .Boost(1.1) + .Fields(f => f.Field(p=>p.Description).Field("myOtherField")) + .Query("hello world") + .DefaultField(p=>p.Description) + .DefaultOperator(Operator.Or) + .Analyzer("standard") + .QuoteAnalyzer("quote-an") + .AllowLeadingWildcard() + .AutoGeneratePhraseQueries() + .MaximumDeterminizedStates(2) + .LowercaseExpendedTerms() + .EnablePositionIncrements() + .Escape() + .UseDisMax() + .FuzzyPrefixLength(2) + .FuzzyMaxExpansions(3) + .FuzzyRewrite(RewriteMultiTerm.ConstantScore) + .Rewrite(RewriteMultiTerm.ConstantScore) + .Fuziness(Fuzziness.Auto) + .TieBreaker(1.2) + .AnalyzeWildcard() + .MinimumShouldMatch(2) + .QuoteFieldSuffix("'") + .Lenient() + .Locale("en_US") + .Timezone("root") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new QueryStringQuery +{ + Fields = Field(p=>p.Description).And("myOtherField"), + Boost = 1.1, + Name = "named_query", + Query = "hello world", + DefaultField = Field(p=>p.Description), + DefaultOperator = Operator.Or, + Analyzer = "standard", + QuoteAnalyzer = "quote-an", + AllowLeadingWildcard = true, + AutoGeneratePhraseQueries = true, + MaximumDeterminizedStates = 2, + LowercaseExpendedTerms = true, + EnablePositionIncrements = true, + Escape = true, + UseDisMax = true, + FuzzyPrefixLength = 2, + FuzzyMaxExpansions = 3, + FuzzyRewrite = RewriteMultiTerm.ConstantScore, + Rewrite = RewriteMultiTerm.ConstantScore, + Fuzziness = Fuzziness.Auto, + TieBreaker = 1.2, + AnalyzeWildcard = true, + MinimumShouldMatch = 2, + QuoteFieldSuffix = "'", + Lenient = true, + Locale = "en_US", + Timezone = "root" +} +---- + [source,javascript] .Example json output ---- @@ -46,39 +118,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new QueryStringQuery - { -Fields = Field(p=>p.Description).And("myOtherField"), -Boost = 1.1, -Name = "named_query", -Query = "hello world", -DefaultField = Field(p=>p.Description), -DefaultOperator = Operator.Or, -Analyzer = "standard", -QuoteAnalyzer = "quote-an", -AllowLeadingWildcard = true, -AutoGeneratePhraseQueries = true, -MaximumDeterminizedStates = 2, -LowercaseExpendedTerms = true, -EnablePositionIncrements = true, -Escape = true, -UseDisMax = true, -FuzzyPrefixLength = 2, -FuzzyMaxExpansions = 3, -FuzzyRewrite = RewriteMultiTerm.ConstantScore, -Rewrite = RewriteMultiTerm.ConstantScore, -Fuzziness = Fuzziness.Auto, -TieBreaker = 1.2, -AnalyzeWildcard = true, -MinimumShouldMatch = 2, -QuoteFieldSuffix = "'", -Lenient = true, -Locale = "en_US", -Timezone = "root" - } ----- - diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc index dd12595eef9..1bd88f2691e 100644 --- a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -7,6 +7,48 @@ [[simple-query-string-usage]] == Simple Query String Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SimpleQueryString(c => c + .Name("named_query") + .Boost(1.1) + .Fields(f => f.Field(p=>p.Description).Field("myOtherField")) + .Query("hello world") + .Analyzer("standard") + .DefaultOperator(Operator.Or) + .Flags(SimpleQueryStringFlags.And|SimpleQueryStringFlags.Near) + .Locale("en_US") + .LowercaseExpendedTerms() + .Lenient() + .AnalyzeWildcard() + .MinimumShouldMatch("30%") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SimpleQueryStringQuery +{ + Name = "named_query", + Boost = 1.1, + Fields = Field(p=>p.Description).And("myOtherField"), + Query = "hello world", + Analyzer = "standard", + DefaultOperator = Operator.Or, + Flags = SimpleQueryStringFlags.And|SimpleQueryStringFlags.Near, + Locale = "en_US", + LowercaseExpendedTerms = true, + Lenient = true, + AnalyzeWildcard = true, + MinimumShouldMatch = "30%" +} +---- + [source,javascript] .Example json output ---- @@ -31,24 +73,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SimpleQueryStringQuery - { -Name = "named_query", -Boost = 1.1, -Fields = Field(p=>p.Description).And("myOtherField"), -Query = "hello world", -Analyzer = "standard", -DefaultOperator = Operator.Or, -Flags = SimpleQueryStringFlags.And|SimpleQueryStringFlags.Near, -Locale = "en_US", -LowercaseExpendedTerms = true, -Lenient = true, -AnalyzeWildcard = true, -MinimumShouldMatch = "30%" - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc index 895f3c6d797..9479a4edb7c 100644 --- a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -7,6 +7,47 @@ [[geo-bounding-box-query-usage]] == Geo Bounding Box Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoBoundingBox(g=>g + .Boost(1.1) + .Name("named_query") + .Field(p=>p.Location) + .BoundingBox(b=>b + .TopLeft(34, -34) + .BottomRight(-34, 34) + ) + .Coerce() + .IgnoreMalformed() + .ValidationMethod(GeoValidationMethod.Strict) + .Type(GeoExecution.Indexed) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new GeoBoundingBoxQuery +{ + Boost = 1.1, + Name = "named_query", + Field = Infer.Field(p => p.Location), + BoundingBox = new Nest.BoundingBox + { + TopLeft = new GeoLocation(34,-34), + BottomRight = new GeoLocation(-34,34), + }, + Type = GeoExecution.Indexed, + Coerce = true, + IgnoreMalformed = true, + ValidationMethod = GeoValidationMethod.Strict +} +---- + [source,javascript] .Example json output ---- @@ -32,24 +73,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new GeoBoundingBoxQuery - { -Boost = 1.1, -Name = "named_query", -Field = Infer.Field(p => p.Location), -BoundingBox = new Nest.BoundingBox -{ - TopLeft = new GeoLocation(34,-34), - BottomRight = new GeoLocation(-34,34), -}, -Type = GeoExecution.Indexed, -Coerce = true, -IgnoreMalformed = true, -ValidationMethod = GeoValidationMethod.Strict - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc index 5fe0431730c..5a955ae340a 100644 --- a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -7,6 +7,50 @@ [[geo-distance-range-query-usage]] == Geo Distance Range Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoDistanceRange(g=>g + .Boost(1.1) + .Name("named_query") + .Field(p=>p.Location) + .DistanceType(GeoDistanceType.Arc) + .Coerce() + .GreaterThanOrEqualTo(200, DistanceUnit.Kilometers) + .GreaterThan(200, DistanceUnit.Kilometers) + .IgnoreMalformed() + .Location(new GeoLocation(40, -70)) + .Optimize(GeoOptimizeBBox.Indexed) + .LessThanOrEqualTo(Nest.Distance.Miles(400)) + .LessThan(Nest.Distance.Miles(400)) + .ValidationMethod(GeoValidationMethod.Strict) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new GeoDistanceRangeQuery +{ + Boost = 1.1, + Name = "named_query", + Field = Infer.Field(p=>p.Location), + DistanceType = GeoDistanceType.Arc, + Coerce = true, + GreaterThanOrEqualTo = Nest.Distance.Kilometers(200), + IgnoreMalformed = true, + GreaterThan = Nest.Distance.Kilometers(200), + LessThan = Nest.Distance.Miles(400), + Location = new GeoLocation(40, -70), + OptimizeBoundingBox = GeoOptimizeBBox.Indexed, + LessThanOrEqualTo = Nest.Distance.Miles(400), + ValidationMethod = GeoValidationMethod.Strict +} +---- + [source,javascript] .Example json output ---- @@ -31,25 +75,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new GeoDistanceRangeQuery - { -Boost = 1.1, -Name = "named_query", -Field = Infer.Field(p=>p.Location), -DistanceType = GeoDistanceType.Arc, -Coerce = true, -GreaterThanOrEqualTo = Nest.Distance.Kilometers(200), -IgnoreMalformed = true, -GreaterThan = Nest.Distance.Kilometers(200), -LessThan = Nest.Distance.Miles(400), -Location = new GeoLocation(40, -70), -OptimizeBoundingBox = GeoOptimizeBBox.Indexed, -LessThanOrEqualTo = Nest.Distance.Miles(400), -ValidationMethod = GeoValidationMethod.Strict - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc index 7974b3c5a30..98bb57d3060 100644 --- a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -7,6 +7,44 @@ [[geo-distance-query-usage]] == Geo Distance Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoDistance(g=>g + .Boost(1.1) + .Name("named_query") + .Field(p=>p.Location) + .DistanceType(GeoDistanceType.Arc) + .Coerce() + .Location(34, -34) + .Distance("200.0m") + .IgnoreMalformed() + .Optimize(GeoOptimizeBBox.Memory) + .ValidationMethod(GeoValidationMethod.Strict) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new GeoDistanceQuery +{ + Boost = 1.1, + Name = "named_query", + Field = Infer.Field(p => p.Location), + DistanceType = GeoDistanceType.Arc, + Coerce = true, + Location = new GeoLocation(34,-34), + Distance = "200.0m", + IgnoreMalformed = true, + OptimizeBoundingBox = GeoOptimizeBBox.Memory, + ValidationMethod = GeoValidationMethod.Strict +} +---- + [source,javascript] .Example json output ---- @@ -28,22 +66,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new GeoDistanceQuery - { -Boost = 1.1, -Name = "named_query", -Field = Infer.Field(p => p.Location), -DistanceType = GeoDistanceType.Arc, -Coerce = true, -Location = new GeoLocation(34,-34), -Distance = "200.0m", -IgnoreMalformed = true, -OptimizeBoundingBox = GeoOptimizeBBox.Memory, -ValidationMethod = GeoValidationMethod.Strict - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc index d671631c800..cad7398f97e 100644 --- a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -7,6 +7,36 @@ [[geo-hash-cell-query-usage]] == Geo Hash Cell Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoHashCell(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Location(new GeoLocation(13.4080, 52.5186)) + .Neighbors() + .Precision(Nest.Distance.Meters(3)) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new GeoHashCellQuery +{ + Boost = 1.1, + Name = "named_query", + Field = Infer.Field(p=>p.Location), + Location = new GeoLocation(13.4080, 52.5186), + Neighbors = true, + Precision = Nest.Distance.Meters(3) +} +---- + [source,javascript] .Example json output ---- @@ -24,18 +54,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new GeoHashCellQuery - { -Boost = 1.1, -Name = "named_query", -Field = Infer.Field(p=>p.Location), -Location = new GeoLocation(13.4080, 52.5186), -Neighbors = true, -Precision = Nest.Distance.Meters(3) - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc index d2910881c62..ed0ea98258d 100644 --- a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -7,6 +7,38 @@ [[geo-polygon-query-usage]] == Geo Polygon Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoPolygon(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .IgnoreMalformed() + .Coerce() + .ValidationMethod(GeoValidationMethod.Strict) + .Points( new GeoLocation(45,-45), new GeoLocation(-34,34)) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new GeoPolygonQuery +{ + Boost = 1.1, + Name = "named_query", + ValidationMethod = GeoValidationMethod.Strict, + Coerce = true, + IgnoreMalformed = true, + Points = new [] { new GeoLocation(45,-45), new GeoLocation(-34,34), }, + Field = Field(p=>p.Location) +} +---- + [source,javascript] .Example json output ---- @@ -33,19 +65,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new GeoPolygonQuery - { -Boost = 1.1, -Name = "named_query", -ValidationMethod = GeoValidationMethod.Strict, -Coerce = true, -IgnoreMalformed = true, -Points = new [] { new GeoLocation(45,-45), new GeoLocation(-34,34), }, -Field = Field(p=>p.Location) - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc index 9cb5f00e15c..58be9d7a7fd 100644 --- a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -7,16 +7,30 @@ [[geo-shape-circle-usage]] == Geo Shape Circle Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapeCircle(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Coordinates(this._coordinates) + .Radius("100m") +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapeCircleQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -Shape = new CircleGeoShape(this._coordinates) { Radius = "100m" } - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + Shape = new CircleGeoShape(this._coordinates) { Radius = "100m" } +} ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc index ca574bb9ce4..82d2f37d48f 100644 --- a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -7,16 +7,29 @@ [[geo-envelope-usage]] == Geo Envelope Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapeEnvelope(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Coordinates(this._coordinates) +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapeEnvelopeQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -Shape = new EnvelopeGeoShape(this._coordinates) - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + Shape = new EnvelopeGeoShape(this._coordinates) +} ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc index 2b26bf706aa..4ec907dcaa7 100644 --- a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -7,6 +7,41 @@ [[geo-indexed-shape-usage]] == Geo Indexed Shape Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoIndexedShape(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .IndexedShape(p=>p + .Id(2) + .Path(pp=>pp.Location) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new GeoIndexedShapeQuery +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + IndexedShape = new FieldLookup + { + Id = 2, + Index = Index(), + Type = Type(), + Path = Field(p=>p.Location) + } +} +---- + [source,javascript] .Example json output ---- @@ -26,22 +61,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new GeoIndexedShapeQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -IndexedShape = new FieldLookup -{ - Id = 2, - Index = Index(), - Type = Type(), - Path = Field(p=>p.Location) -} - } ----- - diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc index 0403fbb3ca6..9e2ef3cc9c7 100644 --- a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -7,16 +7,29 @@ [[geo-line-string-usage]] == Geo Line String Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapeLineString(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Coordinates(this._coordinates) +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapeLineStringQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -Shape = new LineStringGeoShape(this._coordinates) - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + Shape = new LineStringGeoShape(this._coordinates) +} ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc index e1ac11a6673..a451a70869b 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -7,16 +7,29 @@ [[geo-multi-line-string-usage]] == Geo Multi Line String Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapeMultiLineString(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Coordinates(this._coordinates) +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapeMultiLineStringQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -Shape = new MultiLineStringGeoShape(this._coordinates) - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + Shape = new MultiLineStringGeoShape(this._coordinates) +} ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc index e43fcebde8a..3b46211d663 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -7,16 +7,29 @@ [[geo-multi-point-usage]] == Geo Multi Point Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapeMultiPoint(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Coordinates(this._coordinates) +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapeMultiPointQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -Shape = new MultiPointGeoShape(this._coordinates) - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + Shape = new MultiPointGeoShape(this._coordinates) +} ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc index 7968b28cc65..93a173ac826 100644 --- a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -7,16 +7,29 @@ [[geo-point-usage]] == Geo Point Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapePoint(c => c + .Name("named_query") + .Boost(1.1) + .Field(p=>p.Location) + .Coordinates(this._coordinates) +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapePointQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p=>p.Location), -Shape = new PointGeoShape(this._coordinates) - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p=>p.Location), + Shape = new PointGeoShape(this._coordinates) +} ---- diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc index 72d3f9da21e..e7043835380 100644 --- a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -7,16 +7,29 @@ [[geo-polygon-usage]] == Geo Polygon Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.GeoShapePolygon(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Location) + .Coordinates(this._coordinates) +) +---- + === Object Initializer Syntax Example [source,csharp] ---- new GeoShapePolygonQuery - { -Name = "named_query", -Boost = 1.1, -Field = Field(p => p.Location), -Shape = new PolygonGeoShape(this._coordinates) { } - } +{ + Name = "named_query", + Boost = 1.1, + Field = Field(p => p.Location), + Shape = new PolygonGeoShape(this._coordinates) { } +} ---- diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc index e9f6713e8b7..0a2be5e8663 100644 --- a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -7,6 +7,39 @@ [[has-child-query-usage]] == Has Child Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.HasChild(c => c + .Name("named_query") + .Boost(1.1) + .InnerHits(i=>i.Explain()) + .MaxChildren(5) + .MinChildren(1) + .ScoreMode(ChildScoreMode.Average) + .Query(qq=>qq.MatchAll()) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new HasChildQuery +{ + Name = "named_query", + Boost = 1.1, + Type = Infer.Type(), + InnerHits = new InnerHits { Explain = true }, + MaxChildren = 5, + MinChildren = 1, + Query = new MatchAllQuery(), + ScoreMode = ChildScoreMode.Average +} +---- + [source,javascript] .Example json output ---- @@ -28,20 +61,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new HasChildQuery - { -Name = "named_query", -Boost = 1.1, -Type = Infer.Type(), -InnerHits = new InnerHits { Explain = true }, -MaxChildren = 5, -MinChildren = 1, -Query = new MatchAllQuery(), -ScoreMode = ChildScoreMode.Average - } ----- - diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc index efd64321540..ecb7cfbc839 100644 --- a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -7,6 +7,36 @@ [[has-parent-query-usage]] == Has Parent Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.HasParent(c => c + .Name("named_query") + .Boost(1.1) + .InnerHits(i=>i.Explain()) + .ScoreMode(ParentScoreMode.Score) + .Query(qq=>qq.MatchAll()) + +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new HasParentQuery +{ + Name = "named_query", + Boost = 1.1, + Type = Infer.Type(), + InnerHits = new InnerHits { Explain = true }, + Query = new MatchAllQuery(), + ScoreMode = ParentScoreMode.Score +} +---- + [source,javascript] .Example json output ---- @@ -26,18 +56,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new HasParentQuery - { -Name = "named_query", -Boost = 1.1, -Type = Infer.Type(), -InnerHits = new InnerHits { Explain = true }, -Query = new MatchAllQuery(), -ScoreMode = ParentScoreMode.Score - } ----- - diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc index 5b2ca56ef6d..2fc19d0286c 100644 --- a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -7,6 +7,34 @@ [[nested-query-usage]] == Nested Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Nested(c => c + .Name("named_query") + .Boost(1.1) + .InnerHits(i=>i.Explain()) + .Query(qq=>qq.MatchAll()) + .Path(p=>p.CuratedTags) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new NestedQuery +{ + Name = "named_query", + Boost = 1.1, + InnerHits = new InnerHits { Explain = true }, + Query = new MatchAllQuery(), + Path = Field(p=>p.CuratedTags) +} +---- + [source,javascript] .Example json output ---- @@ -25,17 +53,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new NestedQuery - { -Name = "named_query", -Boost = 1.1, -InnerHits = new InnerHits { Explain = true }, -Query = new MatchAllQuery(), -Path = Field(p=>p.CuratedTags) - } ----- - diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc index 69b596a1def..7e757b84cbe 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -7,6 +7,21 @@ [[raw-combine-usage]] == Raw Combine Usage +=== Fluent DSL Example + +[source,csharp] +---- +q.Raw(RawTermQuery) && q.Term("x", "y") +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new RawQuery(RawTermQuery) +&& new TermQuery { Field = "x", Value = "y" } +---- + [source,javascript] .Example json output ---- @@ -30,11 +45,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new RawQuery(RawTermQuery) -&& new TermQuery { Field = "x", Value = "y" } ----- - diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc index 0dcb9694cae..bb86243202f 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -7,14 +7,12 @@ [[raw-query-usage]] == Raw Query Usage -[source,javascript] -.Example json output +=== Fluent DSL Example + +[source,csharp] ---- -{ - "term": { - "fieldname": "value" - } -} +q +.Raw(RawTermQuery) ---- === Object Initializer Syntax Example @@ -24,3 +22,13 @@ new RawQuery(RawTermQuery) ---- +[source,javascript] +.Example json output +---- +{ + "term": { + "fieldname": "value" + } +} +---- + diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc index b5ce94293a0..1ac458d4646 100644 --- a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -7,6 +7,36 @@ [[span-containing-query-usage]] == Span Containing Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanContaining(sn => sn + .Name("named_query") + .Boost(1.1) + .Little(i=>i + .SpanTerm(st=>st.Field("field1").Value("hoya")) + ) + .Big(e=>e + .SpanTerm(st=>st.Field("field1").Value("hoya2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanContainingQuery +{ + Name = "named_query", + Boost = 1.1, + Little = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya"} }, + Big = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2"} }, +} +---- + [source,javascript] .Example json output ---- @@ -32,16 +62,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanContainingQuery - { -Name = "named_query", -Boost = 1.1, -Little = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya"} }, -Big = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2"} }, - } ----- - diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc index 23f987c8c6d..af3b148cdbb 100644 --- a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -7,6 +7,37 @@ [[span-first-query-usage]] == Span First Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanFirst(c => c + .Name("named_query") + .Boost(1.1) + .Match(sq=>sq + .SpanTerm(st=>st.Field(p=>p.Name).Value("value")) + ) + .End(3) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanFirstQuery +{ + Name = "named_query", + Boost = 1.1, + End = 3, + Match = new SpanQuery + { + SpanTerm = new SpanTermQuery { Field = "name", Value = "value" } + } +} +---- + [source,javascript] .Example json output ---- @@ -26,19 +57,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanFirstQuery - { -Name = "named_query", -Boost = 1.1, -End = 3, -Match = new SpanQuery -{ - SpanTerm = new SpanTermQuery { Field = "name", Value = "value" } -} - } ----- - diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc index 7a596d350c8..6e298543839 100644 --- a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -7,6 +7,32 @@ [[span-multi-term-query-usage]] == Span Multi Term Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanMultiTerm(c => c + .Name("named_query") + .Boost(1.1) + .Match(sq=>sq + .Prefix(pr=>pr.Field(p=>p.Name).Value("pre-*")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanMultiTermQuery +{ + Name = "named_query", + Boost = 1.1, + Match = new PrefixQuery { Field = "name", Value = "pre-*" } +} +---- + [source,javascript] .Example json output ---- @@ -25,15 +51,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanMultiTermQuery - { -Name = "named_query", -Boost = 1.1, -Match = new PrefixQuery { Field = "name", Value = "pre-*" } - } ----- - diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc index a05440813f0..9a7ede543ac 100644 --- a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -7,6 +7,45 @@ [[span-near-query-usage]] == Span Near Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanNear(sn => sn + .Name("named_query") + .Boost(1.1) + .Clauses( + c=>c.SpanTerm(st=>st.Field("field").Value("value1")), + c=>c.SpanTerm(st=>st.Field("field").Value("value2")), + c=>c.SpanTerm(st=>st.Field("field").Value("value3")) + ) + .Slop(12) + .InOrder(false) + .CollectPayloads(false) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanNearQuery +{ + Name = "named_query", + Boost = 1.1, + Clauses = new List + { + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value1" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value2" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value3" } } + }, + Slop = 12, + InOrder = false, + CollectPayloads = false +} +---- + [source,javascript] .Example json output ---- @@ -44,23 +83,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanNearQuery - { -Name = "named_query", -Boost = 1.1, -Clauses = new List -{ - new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value1" } }, - new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value2" } }, - new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value3" } } -}, -Slop = 12, -InOrder = false, -CollectPayloads = false - } ----- - diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc index c9b81fbc772..6aa8f74b640 100644 --- a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -7,6 +7,54 @@ [[span-not-query-usage]] == Span Not Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanNot(sn => sn + .Name("named_query") + .Boost(1.1) + .Dist(12) + .Post(13) + .Pre(14) + .Include(i => i + .SpanTerm(st => st.Field("field1").Value("hoya")) + ) + .Exclude(e => e + .SpanTerm(st => st.Field("field1").Value("hoya2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanNotQuery +{ + Name = "named_query", + Boost = 1.1, + Dist = 12, + Post = 13, + Pre = 14, + Include = new SpanQuery + { + SpanTerm = new SpanTermQuery + { + Field = "field1", Value = "hoya" + } + }, + Exclude = new SpanQuery + { + SpanTerm = new SpanTermQuery + { + Field = "field1", Value = "hoya2" + } + }, +} +---- + [source,javascript] .Example json output ---- @@ -35,19 +83,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanNotQuery - { -Name = "named_query", -Boost = 1.1, -Dist = 12, -Post = 13, -Pre = 14, -Include = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya" } }, -Exclude = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2" } }, - } ----- - diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc index 4090145c317..968742e3af2 100644 --- a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -7,6 +7,39 @@ [[span-or-query-usage]] == Span Or Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanOr(sn => sn + .Name("named_query") + .Boost(1.1) + .Clauses( + c => c.SpanTerm(st => st.Field("field").Value("value1")), + c => c.SpanTerm(st => st.Field("field").Value("value2")), + c => c.SpanTerm(st => st.Field("field").Value("value3")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanOrQuery +{ + Name = "named_query", + Boost = 1.1, + Clauses = new List + { + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value1" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value2" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value3" } } + }, +} +---- + [source,javascript] .Example json output ---- @@ -41,20 +74,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanOrQuery - { -Name = "named_query", -Boost = 1.1, -Clauses = new List -{ - new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value1" } }, - new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value2" } }, - new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value3" } } -}, - } ----- - diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc index d8ec50a627b..feaadab2811 100644 --- a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -7,6 +7,32 @@ [[span-term-query-usage]] == Span Term Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanTerm(c => c + .Name("named_query") + .Boost(1.1) + .Field("user") + .Value("kimchy") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanTermQuery +{ + Name = "named_query", + Boost = 1.1, + Value = "kimchy", + Field = "user" +} +---- + [source,javascript] .Example json output ---- @@ -21,16 +47,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanTermQuery - { -Name = "named_query", -Boost = 1.1, -Value = "kimchy", -Field = "user" - } ----- - diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc index d25aa2c8574..4a0b1acf65b 100644 --- a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -7,6 +7,36 @@ [[span-within-query-usage]] == Span Within Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.SpanWithin(sn => sn + .Name("named_query") + .Boost(1.1) + .Little(i=>i + .SpanTerm(st=>st.Field("field1").Value("hoya")) + ) + .Big(e=>e + .SpanTerm(st=>st.Field("field1").Value("hoya2")) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SpanWithinQuery +{ + Name = "named_query", + Boost = 1.1, + Little = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya"} }, + Big = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2"} }, +} +---- + [source,javascript] .Example json output ---- @@ -32,16 +62,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new SpanWithinQuery - { -Name = "named_query", -Boost = 1.1, -Little = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya"} }, -Big = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2"} }, - } ----- - diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc index 54c421f4681..d897f2aff76 100644 --- a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -7,6 +7,68 @@ [[more-like-this-query-usage]] == More Like This Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.MoreLikeThis(sn => sn + .Name("named_query") + .Boost(1.1) + .Like(l=>l + .Document(d=>d .Id(Project.Instance.Name)) + .Text("some long text") + ) + .Analyzer("some_analyzer") + .BoostTerms(1.1) + .Include() + .MaxDocumentFrequency(12) + .MaxQueryTerms(12) + .MaxWordLength(300) + .MinDocumentFrequency(1) + .MinTermFrequency(1) + .MinWordLength(10) + .StopWords("and", "the") + .MinimumShouldMatch(1) + .Fields(f=>f.Field(p=>p.Name)) + .Unlike(l=>l + .Text("not like this text") + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MoreLikeThisQuery +{ + Name = "named_query", + Boost = 1.1, + Fields = Fields(p=>p.Name), + Like = new List + { + new LikeDocument(Project.Instance.Name), + "some long text" + }, + Analyzer = "some_analyzer", + BoostTerms = 1.1, + Include = true, + MaxDocumentFrequency = 12, + MaxQueryTerms = 12, + MaxWordLength = 300, + MinDocumentFrequency = 1, + MinTermFrequency = 1, + MinWordLength = 10, + MinimumShouldMatch = 1, + StopWords = new [] { "and", "the"}, + Unlike = new List + { + "not like this text" + } +} +---- + [source,javascript] .Example json output ---- @@ -46,35 +108,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new MoreLikeThisQuery - { -Name = "named_query", -Boost = 1.1, -Fields = Fields(p=>p.Name), -Like = new List -{ - new LikeDocument(Project.Instance.Name), - "some long text" -}, -Analyzer = "some_analyzer", -BoostTerms = 1.1, -Include = true, -MaxDocumentFrequency = 12, -MaxQueryTerms = 12, -MaxWordLength = 300, -MinDocumentFrequency = 1, -MinTermFrequency = 1, -MinWordLength = 10, -MinimumShouldMatch = 1, -StopWords = new [] { "and", "the"}, -Unlike = new List -{ - "not like this text" -} - } ----- - diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc index 00b86eadd36..6eb03580099 100644 --- a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -7,6 +7,35 @@ [[script-query-usage]] == Script Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Script(sn => sn + .Name("named_query") + .Boost(1.1) + .Inline(_templateString) + .Params(p=>p.Add("param1", 1)) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new ScriptQuery +{ + Name = "named_query", + Boost = 1.1, + Inline = _templateString, + Params = new Dictionary + { + { "param1", 1 } + } +} +---- + [source,javascript] .Example json output ---- @@ -22,19 +51,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new ScriptQuery - { -Name = "named_query", -Boost = 1.1, -Inline = _templateString, -Params = new Dictionary -{ - { "param1", 1 } -} - } ----- - diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc index 969e2088fe7..41639a3ef99 100644 --- a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -7,23 +7,17 @@ [[template-query-usage]] == Template Query Usage +=== Fluent DSL Example + [source,csharp] ---- -new - { -template = new -{ - _name = "named_query", - boost = 1.1, - inline = _templateString, - @params = new - { - query_string = "all about search" - } -} - - - } +q +.Template(sn => sn + .Name("named_query") + .Boost(1.1) + .Inline(_templateString) + .Params(p=>p.Add("query_string", "all about search")) +) ---- === Object Initializer Syntax Example @@ -31,14 +25,29 @@ template = new [source,csharp] ---- new TemplateQuery - { -Name = "named_query", -Boost = 1.1, -Inline = _templateString, -Params = new Dictionary { - { "query_string", "all about search" } + Name = "named_query", + Boost = 1.1, + Inline = _templateString, + Params = new Dictionary + { + { "query_string", "all about search" } + } +} +---- + +[source,javascript] +.Example json output +---- +{ + "template": { + "_name": "named_query", + "boost": 1.1, + "inline": "{ \"match\": { \"text\": \"{{query_string}}\" } }", + "params": { + "query_string": "all about search" + } + } } - } ---- diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc index cde6ed1672c..ecd457d6b69 100644 --- a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -7,6 +7,30 @@ [[exists-query-usage]] == Exists Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Exists(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new ExistsQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", +} +---- + [source,javascript] .Example json output ---- @@ -19,15 +43,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new ExistsQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc index c225db88b59..8ae64f6b8fc 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -7,6 +7,42 @@ [[fuzzy-date-query-usage]] == Fuzzy Date Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.FuzzyDate(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Fuzziness(TimeSpan.FromDays(2)) + .Value(Project.Instance.StartedOn) + .MaxExpansions(100) + .PrefixLength(3) + .Rewrite(RewriteMultiTerm.ConstantScore) + .Transpositions() +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new FuzzyDateQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Fuzziness = TimeSpan.FromDays(2), + Value = Project.Instance.StartedOn, + MaxExpansions = 100, + PrefixLength = 3, + Rewrite = RewriteMultiTerm.ConstantScore, + Transpositions = true +} +---- + [source,javascript] .Example json output ---- @@ -26,21 +62,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new FuzzyDateQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Fuzziness = TimeSpan.FromDays(2), -Value = Project.Instance.StartedOn, -MaxExpansions = 100, -PrefixLength = 3, -Rewrite = RewriteMultiTerm.ConstantScore, -Transpositions = true - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc index 569bf80365a..6b5be0877c7 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -7,6 +7,42 @@ [[fuzzy-numeric-query-usage]] == Fuzzy Numeric Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.FuzzyNumeric(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Fuzziness(2) + .Value(12) + .MaxExpansions(100) + .PrefixLength(3) + .Rewrite(RewriteMultiTerm.ConstantScore) + .Transpositions() +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new FuzzyNumericQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Fuzziness = 2, + Value = 12, + MaxExpansions = 100, + PrefixLength = 3, + Rewrite = RewriteMultiTerm.ConstantScore, + Transpositions = true +} +---- + [source,javascript] .Example json output ---- @@ -26,21 +62,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new FuzzyNumericQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Fuzziness = 2, -Value = 12, -MaxExpansions = 100, -PrefixLength = 3, -Rewrite = RewriteMultiTerm.ConstantScore, -Transpositions = true - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc index 886533cf892..7072ac95b46 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -7,6 +7,42 @@ [[fuzzy-query-usage]] == Fuzzy Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Fuzzy(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Fuzziness(Fuzziness.Auto) + .Value("ki") + .MaxExpansions(100) + .PrefixLength(3) + .Rewrite(RewriteMultiTerm.ConstantScore) + .Transpositions() +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new FuzzyQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Fuzziness = Fuzziness.Auto, + Value = "ki", + MaxExpansions = 100, + PrefixLength = 3, + Rewrite = RewriteMultiTerm.ConstantScore, + Transpositions = true +} +---- + [source,javascript] .Example json output ---- @@ -26,21 +62,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new FuzzyQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Fuzziness = Fuzziness.Auto, -Value = "ki", -MaxExpansions = 100, -PrefixLength = 3, -Rewrite = RewriteMultiTerm.ConstantScore, -Transpositions = true - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc index aa8cde22133..4d38095c146 100644 --- a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -7,6 +7,32 @@ [[ids-query-usage]] == Ids Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Ids(c => c + .Name("named_query") + .Boost(1.1) + .Values(1, 2, 3, 4) + .Types(typeof(Project), typeof(Developer)) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new IdsQuery +{ + Name = "named_query", + Boost = 1.1, + Values = new List { 1, 2,3,4 }, + Types = Type().And() +} +---- + [source,javascript] .Example json output ---- @@ -28,16 +54,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new IdsQuery - { -Name = "named_query", -Boost = 1.1, -Values = new List { 1, 2,3,4 }, -Types = Type().And() - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc index 8c5ad8edbaa..00744f32413 100644 --- a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -7,6 +7,34 @@ [[missing-query-usage]] == Missing Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Missing(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .NullValue() + .Existence() +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MissingQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + NullValue = true, + Existence = true +} +---- + [source,javascript] .Example json output ---- @@ -21,17 +49,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new MissingQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -NullValue = true, -Existence = true - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc index 6c5d867cd0a..12385a142d5 100644 --- a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -7,6 +7,34 @@ [[prefix-query-usage]] == Prefix Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Prefix(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Value("proj") + .Rewrite(RewriteMultiTerm.TopTermsBoostN) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new PrefixQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Value = "proj", + Rewrite = RewriteMultiTerm.TopTermsBoostN +} +---- + [source,javascript] .Example json output ---- @@ -22,17 +50,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new PrefixQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Value = "proj", -Rewrite = RewriteMultiTerm.TopTermsBoostN - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc index 8b5b377e7e9..1d7be7e1702 100644 --- a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -7,6 +7,42 @@ [[date-range-query-usage]] == Date Range Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.DateRange(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .GreaterThan(FixedDate) + .GreaterThanOrEquals(DateMath.Anchored(FixedDate).RoundTo(TimeUnit.Month)) + .LessThan("01/01/2012") + .LessThanOrEquals(DateMath.Now) + .Format("dd/MM/yyyy||yyyy") + .TimeZone("+01:00") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new DateRangeQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + GreaterThan = FixedDate, + GreaterThanOrEqualTo = DateMath.Anchored(FixedDate).RoundTo(TimeUnit.Month), + LessThan = "01/01/2012", + LessThanOrEqualTo = DateMath.Now, + TimeZone = "+01:00", + Format = "dd/MM/yyyy||yyyy" +} +---- + [source,javascript] .Example json output ---- @@ -26,21 +62,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new DateRangeQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -GreaterThan = FixedDate, -GreaterThanOrEqualTo = DateMath.Anchored(FixedDate).RoundTo(TimeUnit.Month), -LessThan = "01/01/2012", -LessThanOrEqualTo = DateMath.Now, -TimeZone = "+01:00", -Format = "dd/MM/yyyy||yyyy" - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc index 23757ad419c..b205a8df690 100644 --- a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -7,6 +7,38 @@ [[numeric-range-query-usage]] == Numeric Range Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Range(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .GreaterThan(1.0) + .GreaterThanOrEquals(1.1) + .LessThan(2.1) + .LessThanOrEquals(2.0) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new NumericRangeQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + GreaterThan = 1.0, + GreaterThanOrEqualTo = 1.1, + LessThan = 2.1, + LessThanOrEqualTo = 2.0 +} +---- + [source,javascript] .Example json output ---- @@ -24,19 +56,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new NumericRangeQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -GreaterThan = 1.0, -GreaterThanOrEqualTo = 1.1, -LessThan = 2.1, -LessThanOrEqualTo = 2.0 - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc index b695949a8b1..76ee62d518b 100644 --- a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -7,6 +7,38 @@ [[term-range-query-usage]] == Term Range Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.TermRange(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .GreaterThan("foo") + .GreaterThanOrEquals("foof") + .LessThan("bar") + .LessThanOrEquals("barb") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermRangeQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + GreaterThan = "foo", + GreaterThanOrEqualTo = "foof", + LessThan = "bar", + LessThanOrEqualTo = "barb" +} +---- + [source,javascript] .Example json output ---- @@ -24,19 +56,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new TermRangeQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -GreaterThan = "foo", -GreaterThanOrEqualTo = "foof", -LessThan = "bar", -LessThanOrEqualTo = "barb" - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc index 27dabc3f5df..55ea47a337b 100644 --- a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -7,6 +7,36 @@ [[regexp-query-usage]] == Regexp Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Regexp(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Value("s.*y") + .Flags("INTERSECTION|COMPLEMENT|EMPTY") + .MaximumDeterminizedStates(20000) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new RegexpQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Value = "s.*y", + Flags = "INTERSECTION|COMPLEMENT|EMPTY", + MaximumDeterminizedStates = 20000 +} +---- + [source,javascript] .Example json output ---- @@ -23,18 +53,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new RegexpQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Value = "s.*y", -Flags = "INTERSECTION|COMPLEMENT|EMPTY", -MaximumDeterminizedStates = 20000 - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc index 08a80933ec9..95814a28b9a 100644 --- a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -7,6 +7,32 @@ [[term-query-usage]] == Term Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Term(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Value("project description") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Value = "project description" +} +---- + [source,javascript] .Example json output ---- @@ -21,16 +47,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new TermQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Value = "project description" - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc index 4593044ad15..d1872500ccc 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -7,6 +7,38 @@ [[terms-lookup-query-usage]] == Terms Lookup Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Terms(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .TermsLookup(e=>e.Path(p=>p.LastName).Id(12)) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermsQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + TermsLookup = new FieldLookup + { + Id = 12, + Index = Index(), + Type = Type(), + Path = Field(p=>p.LastName) + } +} +---- + [source,javascript] .Example json output ---- @@ -24,22 +56,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new TermsQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -TermsLookup = new FieldLookup -{ - Id = 12, - Index = Index(), - Type = Type(), - Path = Field(p=>p.LastName) -} - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc index 8aa8b0c441e..4fb23152c66 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -7,6 +7,36 @@ [[terms-query-usage]] == Terms Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Terms(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .DisableCoord() + .MinimumShouldMatch(MinimumShouldMatch.Fixed(2)) + .Terms("term1", "term2") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermsQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Terms = new [] { "term1", "term2" }, + DisableCoord = true, + MinimumShouldMatch = 2 +} +---- + [source,javascript] .Example json output ---- @@ -24,18 +54,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new TermsQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Terms = new [] { "term1", "term2" }, -DisableCoord = true, -MinimumShouldMatch = 2 - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc index cce3aa33b5a..6cfb8816a66 100644 --- a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -7,6 +7,30 @@ [[type-query-usage]] == Type Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Type(c => c + .Name("named_query") + .Boost(1.1) + .Value() +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TypeQuery +{ + Name = "named_query", + Boost = 1.1, + Value = Type() +} +---- + [source,javascript] .Example json output ---- @@ -19,15 +43,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new TypeQuery - { -Name = "named_query", -Boost = 1.1, -Value = Type() - } ----- - diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc index b4ded36e094..b2bfa6ed973 100644 --- a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -7,6 +7,34 @@ [[wildcard-query-usage]] == Wildcard Query Usage +=== Fluent DSL Example + +[source,csharp] +---- +q +.Wildcard(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .Value("p*oj") + .Rewrite(RewriteMultiTerm.TopTermsBoostN) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new WildcardQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Value = "p*oj", + Rewrite = RewriteMultiTerm.TopTermsBoostN +} +---- + [source,javascript] .Example json output ---- @@ -22,17 +50,3 @@ } ---- -=== Object Initializer Syntax Example - -[source,csharp] ----- -new WildcardQuery - { -Name = "named_query", -Boost = 1.1, -Field = "description", -Value = "p*oj", -Rewrite = RewriteMultiTerm.TopTermsBoostN - } ----- - diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index b0bf3b57ce0..8ec77e8b766 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -13,9 +13,9 @@ ---- s => s .FielddataFields(fs => fs - .Field(p => p.Name) - .Field(p => p.LeadDeveloper) - .Field(p => p.StartedOn) + .Field(p => p.Name) + .Field(p => p.LeadDeveloper) + .Field(p => p.StartedOn) ) ---- @@ -25,7 +25,7 @@ s => s ---- new SearchRequest { - FielddataFields = new string [] { "name", "leadDeveloper", "startedOn" } + FielddataFields = new string [] { "name", "leadDeveloper", "startedOn" } } ---- diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index 41a2c2f7d70..44cd2a1a51f 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -13,8 +13,8 @@ ---- s => s .Fields(fs => fs - .Field(p => p.Name) - .Field(p => p.StartedOn) + .Field(p => p.Name) + .Field(p => p.StartedOn) ) ---- @@ -24,7 +24,7 @@ s => s ---- new SearchRequest { - Fields = Fields(p => p.Name, p => p.StartedOn) + Fields = Fields(p => p.Name, p => p.StartedOn) } ---- diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index 2016ec3db1a..ddeef4f585c 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -13,8 +13,8 @@ ---- new SearchRequest() { - From = 10, - Size = 12 + From = 10, + Size = 12 } ---- @@ -32,7 +32,7 @@ new SearchRequest() [source,csharp] ---- s => s - .From(10) - .Size(12) + .From(10) + .Size(12) ---- diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index 8ff7e4c54ed..9220f1b1c97 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -13,48 +13,48 @@ ---- s => s .Query(q => q - .Match(m => m - .Field(f => f.Name.Suffix("standard")) - .Query("Upton Sons Shield Rice Rowe Roberts") - ) + .Match(m => m + .Field(f => f.Name.Suffix("standard")) + .Query("Upton Sons Shield Rice Rowe Roberts") + ) ) .Highlight(h => h - .PreTags("") - .PostTags("") - .Fields( - fs => fs - .Field(p => p.Name.Suffix("standard")) - .Type(HighlighterType.Plain) - .ForceSource() - .FragmentSize(150) - .NumberOfFragments(3) - .NoMatchSize(150), - fs => fs - .Field(p => p.LeadDeveloper.FirstName) - .Type(HighlighterType.Fvh) - .PreTags("") - .PostTags("") - .HighlightQuery(q => q - .Match(m => m - .Field(p => p.LeadDeveloper.FirstName) - .Query("Kurt Edgardo Naomi Dariana Justice Felton") - ) - ), - fs => fs - .Field(p => p.State.Suffix("offsets")) - .Type(HighlighterType.Postings) - .PreTags("") - .PostTags("") - .HighlightQuery(q => q - .Terms(t => t - .Field(f => f.State.Suffix("offsets")) - .Terms( - StateOfBeing.Stable.ToString().ToLowerInvariant(), - StateOfBeing.BellyUp.ToString().ToLowerInvariant() - ) - ) - ) - ) + .PreTags("") + .PostTags("") + .Fields( + fs => fs + .Field(p => p.Name.Suffix("standard")) + .Type(HighlighterType.Plain) + .ForceSource() + .FragmentSize(150) + .NumberOfFragments(3) + .NoMatchSize(150), + fs => fs + .Field(p => p.LeadDeveloper.FirstName) + .Type(HighlighterType.Fvh) + .PreTags("") + .PostTags("") + .HighlightQuery(q => q + .Match(m => m + .Field(p => p.LeadDeveloper.FirstName) + .Query("Kurt Edgardo Naomi Dariana Justice Felton") + ) + ), + fs => fs + .Field(p => p.State.Suffix("offsets")) + .Type(HighlighterType.Postings) + .PreTags("") + .PostTags("") + .HighlightQuery(q => q + .Terms(t => t + .Field(f => f.State.Suffix("offsets")) + .Terms( + StateOfBeing.Stable.ToString().ToLowerInvariant(), + StateOfBeing.BellyUp.ToString().ToLowerInvariant() + ) + ) + ) + ) ) ---- @@ -64,52 +64,52 @@ s => s ---- new SearchRequest { - Query = new MatchQuery - { - Query = "Upton Sons Shield Rice Rowe Roberts", - Field = "name.standard" - }, - Highlight = new Highlight - { - PreTags = new[] { "" }, - PostTags = new[] { "" }, - Fields = new Dictionary - { - { "name.standard", new HighlightField - { - Type = HighlighterType.Plain, - ForceSource = true, - FragmentSize = 150, - NumberOfFragments = 3, - NoMatchSize = 150 - } - }, - { "leadDeveloper.firstName", new HighlightField - { - Type = HighlighterType.Fvh, - PreTags = new[] { ""}, - PostTags = new[] { ""}, - HighlightQuery = new MatchQuery - { - Field = "leadDeveloper.firstName", - Query = "Kurt Edgardo Naomi Dariana Justice Felton" - } - } - }, - { "state.offsets", new HighlightField - { - Type = HighlighterType.Postings, - PreTags = new[] { ""}, - PostTags = new[] { ""}, - HighlightQuery = new TermsQuery - { - Field = "state.offsets", - Terms = new [] { "stable", "bellyup" } - } - } - } - } - } + Query = new MatchQuery + { + Query = "Upton Sons Shield Rice Rowe Roberts", + Field = "name.standard" + }, + Highlight = new Highlight + { + PreTags = new[] { "" }, + PostTags = new[] { "" }, + Fields = new Dictionary + { + { "name.standard", new HighlightField + { + Type = HighlighterType.Plain, + ForceSource = true, + FragmentSize = 150, + NumberOfFragments = 3, + NoMatchSize = 150 + } + }, + { "leadDeveloper.firstName", new HighlightField + { + Type = HighlighterType.Fvh, + PreTags = new[] { ""}, + PostTags = new[] { ""}, + HighlightQuery = new MatchQuery + { + Field = "leadDeveloper.firstName", + Query = "Kurt Edgardo Naomi Dariana Justice Felton" + } + } + }, + { "state.offsets", new HighlightField + { + Type = HighlighterType.Postings, + PreTags = new[] { ""}, + PostTags = new[] { ""}, + HighlightQuery = new TermsQuery + { + Field = "state.offsets", + Terms = new [] { "stable", "bellyup" } + } + } + } + } + } } ---- diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index 44c22ec9af4..1f84cbfb1c0 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -13,8 +13,8 @@ ---- s => s .IndicesBoost(b => b - .Add("index1", 1.4) - .Add("index2", 1.3) + .Add("index1", 1.4) + .Add("index2", 1.3) ) ---- @@ -24,11 +24,11 @@ s => s ---- new SearchRequest { - IndicesBoost = new Dictionary - { - { "index1", 1.4 }, - { "index2", 1.3 } - } + IndicesBoost = new Dictionary + { + { "index1", 1.4 }, + { "index2", 1.3 } + } } ---- diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc index bec91811afa..b6e3210f360 100644 --- a/docs/asciidoc/search/request/inner-hits-usage.asciidoc +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -10,9 +10,9 @@ [source,csharp] ---- public interface IRoyal - { -string Name { get; set; } - } +{ + string Name { get; set; } +} ---- [source,csharp] @@ -31,38 +31,38 @@ indexChildren(royal); [source,csharp] ---- var create = this._client.CreateIndex(this._index, c => c - .Settings(s => s - .NumberOfReplicas(0) - .NumberOfShards(1) - ) - .Mappings(map => map - .Map(m => m.AutoMap() - .Properties(props => - RoyalProps(props) - .Nested(n => n.Name(p => p.Foes).AutoMap()) - ) - ) - .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) - .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) - .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) - .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) - ) + .Settings(s => s + .NumberOfReplicas(0) + .NumberOfShards(1) + ) + .Mappings(map => map + .Map(m => m.AutoMap() + .Properties(props => + RoyalProps(props) + .Nested(n => n.Name(p => p.Foes).AutoMap()) + ) + ) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + ) ); var kings = King.Generator.Generate(2) - .Select(k => - { - k.Foes = King.Generator.Generate(2).ToList(); - return k; - }); + .Select(k => + { + k.Foes = King.Generator.Generate(2).ToList(); + return k; + }); var bulk = new BulkDescriptor(); IndexAll(bulk, () => kings, indexChildren: king => - IndexAll(bulk, () => Prince.Generator.Generate(2), king.Name, prince => - IndexAll(bulk, () => Duke.Generator.Generate(3), prince.Name, duke => - IndexAll(bulk, () => Earl.Generator.Generate(5), duke.Name, earl => - IndexAll(bulk, () => Baron.Generator.Generate(1), earl.Name) - ) - ) - ) + IndexAll(bulk, () => Prince.Generator.Generate(2), king.Name, prince => + IndexAll(bulk, () => Duke.Generator.Generate(3), prince.Name, duke => + IndexAll(bulk, () => Earl.Generator.Generate(5), duke.Name, earl => + IndexAll(bulk, () => Baron.Generator.Generate(1), earl.Name) + ) + ) + ) ); this._client.Bulk(bulk); this._client.Refresh(this._index); @@ -75,13 +75,13 @@ this._client.Refresh(this._index); s => s .Index(Index) .InnerHits(ih => ih - .Type("earls", g => g - .Size(5) - .InnerHits(iih => iih - .Type("barons") - ) - .FielddataFields(p => p.Name) - ) + .Type("earls", g => g + .Size(5) + .InnerHits(iih => iih + .Type("barons") + ) + .FielddataFields(p => p.Name) + ) ) ---- @@ -90,26 +90,26 @@ s => s [source,csharp] ---- new SearchRequest(Index, typeof(Duke)) - { -InnerHits = new NamedInnerHits { - { "earls", new InnerHitsContainer - { - Type = new TypeInnerHit - { - InnerHit = new GlobalInnerHit - { - Size = 5, - FielddataFields = new Field[]{ "name" }, - InnerHits = new NamedInnerHits - { - { "barons", new TypeInnerHit() } - } - } - } - } } + InnerHits = new NamedInnerHits + { + { "earls", new InnerHitsContainer + { + Type = new TypeInnerHit + { + InnerHit = new GlobalInnerHit + { + Size = 5, + FielddataFields = new Field[]{ "name" }, + InnerHits = new NamedInnerHits + { + { "barons", new TypeInnerHit() } + } + } + } + } } + } } - } ---- [source,javascript] @@ -145,14 +145,14 @@ InnerHits = new NamedInnerHits s => s .Index(Index) .Query(q => - q.HasChild(hc => hc - .Query(hcq => hcq.MatchAll()) - .InnerHits(ih => ih.Name("princes")) - ) || q.Nested(n => n - .Path(p => p.Foes) - .Query(nq => nq.MatchAll()) - .InnerHits() - ) + q.HasChild(hc => hc + .Query(hcq => hcq.MatchAll()) + .InnerHits(ih => ih.Name("princes")) + ) || q.Nested(n => n + .Path(p => p.Foes) + .Query(nq => nq.MatchAll()) + .InnerHits() + ) ) ---- @@ -161,19 +161,19 @@ s => s [source,csharp] ---- new SearchRequest(Index, typeof(King)) - { -Query = new HasChildQuery -{ - Type = typeof(Prince), - Query = new MatchAllQuery(), - InnerHits = new InnerHits { Name = "princes" } -} || new NestedQuery { - Path = Field(p => p.Foes), - Query = new MatchAllQuery(), - InnerHits = new InnerHits() + Query = new HasChildQuery + { + Type = typeof(Prince), + Query = new MatchAllQuery(), + InnerHits = new InnerHits { Name = "princes" } + } || new NestedQuery + { + Path = Field(p => p.Foes), + Query = new MatchAllQuery(), + InnerHits = new InnerHits() + } } - } ---- [source,javascript] diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index cab10f64c30..e0ef7c85657 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -14,7 +14,7 @@ s => s .MinScore(0.5) .Query(q => q - .Term(p => p.Name, "elasticsearch") + .Term(p => p.Name, "elasticsearch") ) ---- @@ -24,12 +24,12 @@ s => s ---- new SearchRequest { - MinScore = 0.5, - Query = new TermQuery - { - Field = "name", - Value = "elasticsearch" - } + MinScore = 0.5, + Query = new TermQuery + { + Field = "name", + Value = "elasticsearch" + } } ---- diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index 84c2025102f..2a7d48dd579 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -13,7 +13,7 @@ ---- new SearchRequest() { - PostFilter = new QueryContainer(new MatchAllQuery()) + PostFilter = new QueryContainer(new MatchAllQuery()) } ---- diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index 3e3c456c6b8..8e614cb9645 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -15,7 +15,7 @@ The query element within the search request body allows to define a query using ---- s => s .Query(q => q - .Term(p => p.Name, "elasticsearch") + .Term(p => p.Name, "elasticsearch") ) ---- @@ -25,11 +25,11 @@ s => s ---- new SearchRequest { - Query = new TermQuery - { - Field = "name", - Value = "elasticsearch" - } + Query = new TermQuery + { + Field = "name", + Value = "elasticsearch" + } } ---- diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index eec71bbc0d4..8fed749f668 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -13,15 +13,15 @@ ---- s => s .ScriptFields(sf=>sf - .ScriptField("test1", sc=>sc - .Inline("doc['my_field_name'].value * 2") - ) - .ScriptField("test2", sc=>sc - .Inline("doc['my_field_name'].value * factor") - .Params(p=>p - .Add("factor", 2.0) - ) - ) + .ScriptField("test1", sc=>sc + .Inline("doc['my_field_name'].value * 2") + ) + .ScriptField("test2", sc=>sc + .Inline("doc['my_field_name'].value * factor") + .Params(p=>p + .Add("factor", 2.0) + ) + ) ) ---- @@ -31,20 +31,20 @@ s => s ---- new SearchRequest { - ScriptFields = new ScriptFields - { - { "test1", new ScriptField - { - Script = new InlineScript("doc['my_field_name'].value * 2") - } }, - { "test2", new InlineScript("doc['my_field_name'].value * factor") - { - Params = new FluentDictionary - { - { "factor", 2.0 } - } - } } - } + ScriptFields = new ScriptFields + { + { "test1", new ScriptField + { + Script = new InlineScript("doc['my_field_name'].value * 2") + } }, + { "test2", new InlineScript("doc['my_field_name'].value * factor") + { + Params = new FluentDictionary + { + { "factor", 2.0 } + } + } } + } } ---- diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 60c5e89eda6..0d7af40826a 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -8,7 +8,7 @@ == Sort Usage Allows to add one or more sort on specific fields. Each sort can be reversed as well. -The sort is defined on a per field level, with special field name for score to sort by score. +The sort is defined on a per field level, with special field name for _score to sort by score. === Fluent DSL Example @@ -16,35 +16,35 @@ The sort is defined on a per field level, with special field name for score to s ---- s => s .Sort(ss => ss - .Ascending(p => p.StartedOn) - .Descending(p => p.Name) - .Descending(SortSpecialField.Score) - .Ascending(SortSpecialField.DocumentIndexOrder) - .Field(f => f - .Field(p => p.LastActivity) - .Order(SortOrder.Descending) - .MissingLast() - .UnmappedType(FieldType.Date) - .Mode(SortMode.Average) - .NestedPath(p => p.Tags) - .NestedFilter(q => q.MatchAll()) - ) - .GeoDistance(g => g - .Field(p => p.Location) - .DistanceType(GeoDistanceType.SloppyArc) - .Order(SortOrder.Ascending) - .Unit(DistanceUnit.Centimeters) - .Mode(SortMode.Min) - .PinTo(new GeoLocation(70, -70), new GeoLocation(-12, 12)) - ) - .Script(sc => sc - .Type("number") - .Ascending() - .Script(script => script - .Inline("doc['numberOfCommits'].value * factor") - .Params(p => p.Add("factor", 1.1)) - ) - ) + .Ascending(p => p.StartedOn) + .Descending(p => p.Name) + .Descending(SortSpecialField.Score) + .Ascending(SortSpecialField.DocumentIndexOrder) + .Field(f => f + .Field(p => p.LastActivity) + .Order(SortOrder.Descending) + .MissingLast() + .UnmappedType(FieldType.Date) + .Mode(SortMode.Average) + .NestedPath(p => p.Tags) + .NestedFilter(q => q.MatchAll()) + ) + .GeoDistance(g => g + .Field(p => p.Location) + .DistanceType(GeoDistanceType.SloppyArc) + .Order(SortOrder.Ascending) + .Unit(DistanceUnit.Centimeters) + .Mode(SortMode.Min) + .PinTo(new GeoLocation(70, -70), new GeoLocation(-12, 12)) + ) + .Script(sc => sc + .Type("number") + .Ascending() + .Script(script => script + .Inline("doc['numberOfCommits'].value * factor") + .Params(p => p.Add("factor", 1.1)) + ) + ) ) ---- @@ -54,43 +54,43 @@ s => s ---- new SearchRequest { - Sort = new List - { - new SortField { Field = "startedOn", Order = SortOrder.Ascending }, - new SortField { Field = "name", Order = SortOrder.Descending }, - new SortField { Field = "_score", Order = SortOrder.Descending }, - new SortField { Field = "_doc", Order = SortOrder.Ascending }, - new SortField { - Field = Field(p=>p.LastActivity), - Order = SortOrder.Descending, - Missing = "_last", - UnmappedType = FieldType.Date, - Mode = SortMode.Average, - NestedPath = Field(p=>p.Tags), - NestedFilter = new MatchAllQuery(), - }, - new GeoDistanceSort - { - Field = "location", - Order = SortOrder.Ascending, - DistanceType = GeoDistanceType.Arc, - GeoUnit = DistanceUnit.Centimeters, - Mode = SortMode.Min, - Points = new [] {new GeoLocation(70, -70), new GeoLocation(-12, 12) } - }, - new ScriptSort - { - Type = "number", - Order = SortOrder.Ascending, - Script = new InlineScript("doc['numberOfCommits'].value * factor") - { - Params = new Dictionary - { - { "factor", 1.1 } - } - } - } - } + Sort = new List + { + new SortField { Field = "startedOn", Order = SortOrder.Ascending }, + new SortField { Field = "name", Order = SortOrder.Descending }, + new SortField { Field = "_score", Order = SortOrder.Descending }, + new SortField { Field = "_doc", Order = SortOrder.Ascending }, + new SortField { + Field = Field(p=>p.LastActivity), + Order = SortOrder.Descending, + Missing = "_last", + UnmappedType = FieldType.Date, + Mode = SortMode.Average, + NestedPath = Field(p=>p.Tags), + NestedFilter = new MatchAllQuery(), + }, + new GeoDistanceSort + { + Field = "location", + Order = SortOrder.Ascending, + DistanceType = GeoDistanceType.Arc, + GeoUnit = DistanceUnit.Centimeters, + Mode = SortMode.Min, + Points = new [] {new GeoLocation(70, -70), new GeoLocation(-12, 12) } + }, + new ScriptSort + { + Type = "number", + Order = SortOrder.Ascending, + Script = new InlineScript("doc['numberOfCommits'].value * factor") + { + Params = new Dictionary + { + { "factor", 1.1 } + } + } + } + } } ---- diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index 7a49f8d119f..8adcebf9841 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -9,7 +9,7 @@ Allows to control how the _source field is returned with every hit. By default operations return the contents of the _source field unless - you have used the fields parameter or if the source field is disabled. + you have used the fields parameter or if the _source field is disabled. === Fluent DSL Example @@ -17,12 +17,12 @@ By default operations return the contents of the _source field unless ---- s => s .Source(so => so - .Include(f => f - .Fields( - p => p.Name, - p => p.StartedOn - ) - ) + .Include(f => f + .Fields( + p => p.Name, + p => p.StartedOn + ) + ) ) ---- @@ -32,10 +32,10 @@ s => s ---- new SearchRequest { - Source = new SourceFilter - { - Include = Fields(p => p.Name, prop => prop.StartedOn) - } + Source = new SourceFilter + { + Include = Fields(p => p.Name, prop => prop.StartedOn) + } } ---- @@ -66,8 +66,8 @@ document.Description.Should().BeNull(); ---- internal class WithSourceFilterProperty { - [JsonProperty("_source")] - public ISourceFilter SourceFilter { get; set; } + [JsonProperty("_source")] + public ISourceFilter SourceFilter { get; set; } } ---- diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index 7e994f8d40b..51ed1b0831a 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -8,7 +8,7 @@ == Suggest Usage Allows to add one or more sort on specific fields. Each sort can be reversed as well. -The sort is defined on a per field level, with special field name for score to sort by score. +The sort is defined on a per field level, with special field name for _score to sort by score. === Handling Responses @@ -34,54 +34,54 @@ payload.State.Should().NotBeNull(); ---- s => s .Suggest(ss => ss - .Term("my-term-suggest", t => t - .MaxEdits(1) - .MaxInspections(2) - .MaxTermFrequency(3) - .MinDocFrequency(4) - .MinWordLength(5) - .PrefixLength(6) - .SuggestMode(SuggestMode.Always) - .Analyzer("standard") - .Field(p => p.Name) - .ShardSize(7) - .Size(8) - .Text("hello world") - ) - .Completion("my-completion-suggest", c => c - .Context(ctx => ctx - .Add("color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()) - ) - .Fuzzy(f => f - .Fuzziness(Fuzziness.Auto) - .MinLength(1) - .PrefixLength(2) - .Transpositions() - .UnicodeAware(false) - ) - .Analyzer("simple") - .Field(p => p.Suggest) - .ShardSize(7) - .Size(8) - .Text(Project.Instance.Name) - ) - .Phrase("my-phrase-suggest", ph => ph - .Collate(c => c - .Query(q => q - .Inline("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") - .Params(p => p.Add("field_name", "title")) - ) - .Prune() - ) - .Confidence(10.1) - .DirectGenerator(d => d - .Field(p => p.Description) - ) - .GramSize(1) - .Field(p => p.Name) - .Text("hello world") - .RealWordErrorLikelihood(0.5) - ) + .Term("my-term-suggest", t => t + .MaxEdits(1) + .MaxInspections(2) + .MaxTermFrequency(3) + .MinDocFrequency(4) + .MinWordLength(5) + .PrefixLength(6) + .SuggestMode(SuggestMode.Always) + .Analyzer("standard") + .Field(p => p.Name) + .ShardSize(7) + .Size(8) + .Text("hello world") + ) + .Completion("my-completion-suggest", c => c + .Context(ctx => ctx + .Add("color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()) + ) + .Fuzzy(f => f + .Fuzziness(Fuzziness.Auto) + .MinLength(1) + .PrefixLength(2) + .Transpositions() + .UnicodeAware(false) + ) + .Analyzer("simple") + .Field(p => p.Suggest) + .ShardSize(7) + .Size(8) + .Text(Project.Instance.Name) + ) + .Phrase("my-phrase-suggest", ph => ph + .Collate(c => c + .Query(q => q + .Inline("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + .Params(p => p.Add("field_name", "title")) + ) + .Prune() + ) + .Confidence(10.1) + .DirectGenerator(d => d + .Field(p => p.Description) + ) + .GramSize(1) + .Field(p => p.Name) + .Text("hello world") + .RealWordErrorLikelihood(0.5) + ) ) ---- @@ -91,73 +91,73 @@ s => s ---- new SearchRequest { - Suggest = new SuggestContainer - { - { "my-term-suggest", new SuggestBucket - { - Text = "hello world", - Term = new TermSuggester - { - MaxEdits = 1, - MaxInspections = 2, - MaxTermFrequency = 3, - MinDocFrequency = 4, - MinWordLen = 5, - PrefixLen = 6, - SuggestMode = SuggestMode.Always, - Analyzer = "standard", - Field = Field(p=>p.Name), - ShardSize = 7, - Size = 8 - } - } }, - { "my-completion-suggest", new SuggestBucket - { - Text = Project.Instance.Name, - Completion = new CompletionSuggester - { - Context = new Dictionary { { "color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First() } }, - Fuzzy = new FuzzySuggester - { - Fuzziness = Fuzziness.Auto, - MinLength = 1, - PrefixLength = 2, - Transpositions = true, - UnicodeAware = false - }, - Analyzer = "simple", - Field = Field(p=>p.Suggest), - ShardSize = 7, - Size = 8 - } - } }, - { "my-phrase-suggest", new SuggestBucket - { - Text = "hello world", - Phrase = new PhraseSuggester - { - Collate = new PhraseSuggestCollate - { - Query = new InlineScript("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") - { - Params = new Dictionary - { - { "field_name", "title" } - } - }, - Prune = true - }, - Confidence = 10.1, - DirectGenerator = new List - { - new DirectGenerator { Field = "description" } - }, - GramSize = 1, - Field = "name", - RealWordErrorLikelihood = 0.5 - } - } }, - } + Suggest = new SuggestContainer + { + { "my-term-suggest", new SuggestBucket + { + Text = "hello world", + Term = new TermSuggester + { + MaxEdits = 1, + MaxInspections = 2, + MaxTermFrequency = 3, + MinDocFrequency = 4, + MinWordLen = 5, + PrefixLen = 6, + SuggestMode = SuggestMode.Always, + Analyzer = "standard", + Field = Field(p=>p.Name), + ShardSize = 7, + Size = 8 + } + } }, + { "my-completion-suggest", new SuggestBucket + { + Text = Project.Instance.Name, + Completion = new CompletionSuggester + { + Context = new Dictionary { { "color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First() } }, + Fuzzy = new FuzzySuggester + { + Fuzziness = Fuzziness.Auto, + MinLength = 1, + PrefixLength = 2, + Transpositions = true, + UnicodeAware = false + }, + Analyzer = "simple", + Field = Field(p=>p.Suggest), + ShardSize = 7, + Size = 8 + } + } }, + { "my-phrase-suggest", new SuggestBucket + { + Text = "hello world", + Phrase = new PhraseSuggester + { + Collate = new PhraseSuggestCollate + { + Query = new InlineScript("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + { + Params = new Dictionary + { + { "field_name", "title" } + } + }, + Prune = true + }, + Confidence = 10.1, + DirectGenerator = new List + { + new DirectGenerator { Field = "description" } + }, + GramSize = 1, + Field = "name", + RealWordErrorLikelihood = 0.5 + } + } }, + } } ---- diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index f4b6d42d13a..4c911d5696c 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -14,54 +14,54 @@ [source,csharp] ---- s => s - .Term("my-term-suggest", t => t - .MaxEdits(1) - .MaxInspections(2) - .MaxTermFrequency(3) - .MinDocFrequency(4) - .MinWordLength(5) - .PrefixLength(6) - .SuggestMode(SuggestMode.Always) - .Analyzer("standard") - .Field(p => p.Name) - .ShardSize(7) - .Size(8) - .Text("hello world") - ) - .Completion("my-completion-suggest", c => c - .Context(ctx => ctx - .Add("color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()) - ) - .Fuzzy(f => f - .Fuzziness(Fuzziness.Auto) - .MinLength(1) - .PrefixLength(2) - .Transpositions() - .UnicodeAware(false) - ) - .Analyzer("simple") - .Field(p => p.Suggest) - .ShardSize(7) - .Size(8) - .Text(Project.Instance.Name) - ) - .Phrase("my-phrase-suggest", ph => ph - .Collate(c => c - .Query(q => q - .Inline("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") - .Params(p => p.Add("field_name", "title")) - ) - .Prune() - ) - .Confidence(10.1) - .DirectGenerator(d => d - .Field(p => p.Description) - ) - .GramSize(1) - .Field(p => p.Name) - .Text("hello world") - .RealWordErrorLikelihood(0.5) - ) + .Term("my-term-suggest", t => t + .MaxEdits(1) + .MaxInspections(2) + .MaxTermFrequency(3) + .MinDocFrequency(4) + .MinWordLength(5) + .PrefixLength(6) + .SuggestMode(SuggestMode.Always) + .Analyzer("standard") + .Field(p => p.Name) + .ShardSize(7) + .Size(8) + .Text("hello world") + ) + .Completion("my-completion-suggest", c => c + .Context(ctx => ctx + .Add("color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()) + ) + .Fuzzy(f => f + .Fuzziness(Fuzziness.Auto) + .MinLength(1) + .PrefixLength(2) + .Transpositions() + .UnicodeAware(false) + ) + .Analyzer("simple") + .Field(p => p.Suggest) + .ShardSize(7) + .Size(8) + .Text(Project.Instance.Name) + ) + .Phrase("my-phrase-suggest", ph => ph + .Collate(c => c + .Query(q => q + .Inline("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + .Params(p => p.Add("field_name", "title")) + ) + .Prune() + ) + .Confidence(10.1) + .DirectGenerator(d => d + .Field(p => p.Description) + ) + .GramSize(1) + .Field(p => p.Name) + .Text("hello world") + .RealWordErrorLikelihood(0.5) + ) ---- === Object Initializer Syntax Example @@ -70,73 +70,73 @@ s => s ---- new SuggestRequest { - Suggest = new SuggestContainer - { - { "my-term-suggest", new SuggestBucket - { - Text = "hello world", - Term = new TermSuggester - { - MaxEdits = 1, - MaxInspections = 2, - MaxTermFrequency = 3, - MinDocFrequency = 4, - MinWordLen = 5, - PrefixLen = 6, - SuggestMode = SuggestMode.Always, - Analyzer = "standard", - Field = Field(p=>p.Name), - ShardSize = 7, - Size = 8 - } - } }, - { "my-completion-suggest", new SuggestBucket - { - Text = Project.Instance.Name, - Completion = new CompletionSuggester - { - Context = new Dictionary { { "color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First() } }, - Fuzzy = new FuzzySuggester - { - Fuzziness = Fuzziness.Auto, - MinLength = 1, - PrefixLength = 2, - Transpositions = true, - UnicodeAware = false - }, - Analyzer = "simple", - Field = Field(p=>p.Suggest), - ShardSize = 7, - Size = 8 - } - } }, - { "my-phrase-suggest", new SuggestBucket - { - Text = "hello world", - Phrase = new PhraseSuggester - { - Collate = new PhraseSuggestCollate - { - Query = new InlineScript("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") - { - Params = new Dictionary - { - { "field_name", "title" } - } - }, - Prune = true - }, - Confidence = 10.1, - DirectGenerator = new List - { - new DirectGenerator { Field = "description" } - }, - GramSize = 1, - Field = "name", - RealWordErrorLikelihood = 0.5 - } - } }, - } + Suggest = new SuggestContainer + { + { "my-term-suggest", new SuggestBucket + { + Text = "hello world", + Term = new TermSuggester + { + MaxEdits = 1, + MaxInspections = 2, + MaxTermFrequency = 3, + MinDocFrequency = 4, + MinWordLen = 5, + PrefixLen = 6, + SuggestMode = SuggestMode.Always, + Analyzer = "standard", + Field = Field(p=>p.Name), + ShardSize = 7, + Size = 8 + } + } }, + { "my-completion-suggest", new SuggestBucket + { + Text = Project.Instance.Name, + Completion = new CompletionSuggester + { + Context = new Dictionary { { "color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First() } }, + Fuzzy = new FuzzySuggester + { + Fuzziness = Fuzziness.Auto, + MinLength = 1, + PrefixLength = 2, + Transpositions = true, + UnicodeAware = false + }, + Analyzer = "simple", + Field = Field(p=>p.Suggest), + ShardSize = 7, + Size = 8 + } + } }, + { "my-phrase-suggest", new SuggestBucket + { + Text = "hello world", + Phrase = new PhraseSuggester + { + Collate = new PhraseSuggestCollate + { + Query = new InlineScript("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + { + Params = new Dictionary + { + { "field_name", "title" } + } + }, + Prune = true + }, + Confidence = 10.1, + DirectGenerator = new List + { + new DirectGenerator { Field = "description" } + }, + GramSize = 1, + Field = "name", + RealWordErrorLikelihood = 0.5 + } + } }, + } } ---- diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs similarity index 76% rename from src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs rename to src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs index 6c6fdbbb3c1..ee1a054defd 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using AsciiDoc; @@ -13,7 +14,7 @@ namespace Nest.Litterateur.AsciiDoc /// Visits the "raw" asciidoc generated using Roslyn and adds attribute entries, /// section titles, rearranges sections, etc. /// - public class AddAttributeEntriesVisitor : NoopVisitor + public class GeneratedAsciidocVisitor : NoopVisitor { private static readonly Dictionary Ids = new Dictionary(); @@ -21,7 +22,7 @@ public class AddAttributeEntriesVisitor : NoopVisitor private Document _newDocument; private bool _topLevel = true; - public AddAttributeEntriesVisitor(FileInfo destination) + public GeneratedAsciidocVisitor(FileInfo destination) { _destination = destination; } @@ -72,16 +73,19 @@ public override void Visit(Document document) } // see if the document has some kind of top level title and add one with an anchor if not. - if (document.Title == null && - document.Elements.Count > 0 && - !document.Elements.OfType().Any(s => s.Level == 2)) + if (document.Title == null && document.Elements.Count > 0) { - var id = Path.GetFileNameWithoutExtension(_destination.Name); - var title = id.LowercaseHyphenToPascal(); - var sectionTitle = new SectionTitle(title, 2); - sectionTitle.Attributes.Add(new Anchor(id)); + var sectionTitle = document.Elements[0] as SectionTitle; - _newDocument.Elements.Add(sectionTitle); + if (sectionTitle == null || sectionTitle.Level != 2) + { + var id = Path.GetFileNameWithoutExtension(_destination.Name); + var title = id.LowercaseHyphenToPascal(); + sectionTitle = new SectionTitle(title, 2); + sectionTitle.Attributes.Add(new Anchor(id)); + + _newDocument.Elements.Add(sectionTitle); + } } base.Visit(document); @@ -93,6 +97,7 @@ public override void Visit(IList elements) { _topLevel = false; Source exampleJson = null; + Source objectInitializerExample = null; for (int index = 0; index < elements.Count; index++) { @@ -114,7 +119,7 @@ public override void Visit(IList elements) continue; } - if (method.Value == "expectjson" && + if ((method.Value == "expectjson" || method.Value == "queryjson") && source.Attributes.Count > 1 && source.Attributes[1].Name == "javascript") { @@ -142,9 +147,21 @@ public override void Visit(IList elements) case "queryfluent": _newDocument.Elements.Add(new SectionTitle("Fluent DSL Example", 3)); _newDocument.Elements.Add(element); + + if (objectInitializerExample != null) + { + _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); + _newDocument.Elements.Add(objectInitializerExample); + objectInitializerExample = null; + + if (exampleJson != null) + { + _newDocument.Elements.Add(exampleJson); + exampleJson = null; + } + } break; case "initializer": - case "queryinitializer": _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); _newDocument.Elements.Add(element); // Move the example json to after the initializer example @@ -154,6 +171,24 @@ public override void Visit(IList elements) exampleJson = null; } break; + case "queryinitializer": + if (objectInitializerExample != null) + { + _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); + _newDocument.Elements.Add(objectInitializerExample); + + // Move the example json to after the initializer example + if (exampleJson != null) + { + _newDocument.Elements.Add(exampleJson); + exampleJson = null; + } + } + else + { + objectInitializerExample = source; + } + break; case "expectresponse": _newDocument.Elements.Add(new SectionTitle("Handling Responses", 3)); _newDocument.Elements.Add(element); @@ -190,6 +225,10 @@ public override void Visit(Source source) source.Attributes.Remove(methodAttribute); } + // Replace tabs with spaces and remove comment escaping from output + // (elastic docs generation does not like this callout format) + source.Text = Regex.Replace(source.Text.Replace("\t", " "), @"//[ \t]*\<(\d+)\>.*", "<$1>"); + base.Visit(source); } diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/RawAsciidocVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/RawAsciidocVisitor.cs new file mode 100644 index 00000000000..59df54a14f1 --- /dev/null +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/RawAsciidocVisitor.cs @@ -0,0 +1,95 @@ +#if !DOTNETCORE +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AsciiDoc; + +namespace Nest.Litterateur.AsciiDoc +{ + /// + /// Visits raw asciidoc files (i.e. not generated) to make modifications + /// + public class RawAsciidocVisitor : NoopVisitor + { + private readonly FileInfo _destination; + + private static readonly Dictionary IncludeDirectories = new Dictionary + { + { "aggregations.asciidoc", "aggregations-usage.asciidoc" }, + { "query-dsl.asciidoc", "query-dsl-usage.asciidoc" } + }; + + public RawAsciidocVisitor(FileInfo destination) + { + _destination = destination; + } + + public override void Visit(Document document) + { + // check if this document has generated includes to other files + var includeAttribute = document.Attributes.FirstOrDefault(a => a.Name == "includes-from-dirs"); + + if (includeAttribute != null) + { + var thisFileUri = new Uri(_destination.FullName); + var directories = includeAttribute.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var directory in directories) + { + foreach (var file in Directory.EnumerateFiles(Path.Combine(Program.OutputDirPath, directory), "*.asciidoc", SearchOption.AllDirectories)) + { + var fileInfo = new FileInfo(file); + var referencedFileUri = new Uri(fileInfo.FullName); + var relativePath = thisFileUri.MakeRelativeUri(referencedFileUri); + var include = new Include(relativePath.OriginalString); + + document.Elements.Add(include); + } + } + } + + base.Visit(document); + } + + public override void Visit(Open open) + { + // include links to all the query dsl usage and aggregation usage pages on the landing query dsl and aggregations pages, respectively. + string usageFilePath; + if (IncludeDirectories.TryGetValue(_destination.Name, out usageFilePath)) + { + var usageDoc = Document.Load(Path.Combine(Program.OutputDirPath, usageFilePath)); + + var includeAttribute = usageDoc.Attributes.FirstOrDefault(a => a.Name == "includes-from-dirs"); + + if (includeAttribute != null) + { + var directories = includeAttribute.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var directory in directories) + { + foreach (var file in Directory.EnumerateFiles(Path.Combine(Program.OutputDirPath, directory), "*usage.asciidoc", SearchOption.AllDirectories)) + { + var fileInfo = new FileInfo(file); + var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.Name); + + var listItem = new UnorderedListItem + { + Elements = + { + new Paragraph( + new InternalAnchor(fileNameWithoutExtension, fileNameWithoutExtension.LowercaseHyphenToPascal())) + } + }; + + open.Elements.Add(listItem); + } + } + } + } + + base.Visit(open); + } + } +} +#endif \ No newline at end of file diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs index 729dfc42531..d03be88b2bd 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/CSharpDocumentationFile.cs @@ -205,7 +205,7 @@ private void CleanDocumentAndWriteToFile(string body, FileInfo docFile) // add attributes and write to destination using (var file = new StreamWriter(docFile.FullName)) { - var visitor = new AddAttributeEntriesVisitor(docFile); + var visitor = new GeneratedAsciidocVisitor(docFile); document = visitor.Convert(document); document.Accept(new AsciiDocVisitor(file)); } diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs index 7d4f4555625..1f7c453bdc8 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/RawDocumentationFile.cs @@ -4,6 +4,7 @@ using System.Text.RegularExpressions; #if !DOTNETCORE using AsciiDoc; +using Nest.Litterateur.AsciiDoc; #endif namespace Nest.Litterateur.Documentation.Files @@ -20,31 +21,11 @@ public override void SaveToDocumentationFolder() #if !DOTNETCORE var document = Document.Load(FileLocation.FullName); - // check if this document has generated includes to other files - var includeAttribute = document.Attributes.FirstOrDefault(a => a.Name == "includes-from-dirs"); - - if (includeAttribute == null) - { - this.FileLocation.CopyTo(docFileName.FullName, true); - return; - } - - var thisFileUri = new Uri(docFileName.FullName); - var directories = includeAttribute.Value.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var directory in directories) - { - foreach (var file in Directory.EnumerateFiles(Path.Combine(Program.OutputDirPath, directory), "*.asciidoc", SearchOption.AllDirectories)) - { - var fileInfo = new FileInfo(file); - var referencedFileUri = new Uri(fileInfo.FullName); - var relativePath = thisFileUri.MakeRelativeUri(referencedFileUri); - var include = new Include(relativePath.OriginalString); - - document.Elements.Add(include); - } - } + // make any modifications + var rawVisitor = new RawAsciidocVisitor(FileLocation); + document.Accept(rawVisitor); + // write out asciidoc to file using (var visitor = new AsciiDocVisitor(docFileName.FullName)) { document.Accept(visitor); diff --git a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs index a604b9488f4..cf02728dd45 100644 --- a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs @@ -70,8 +70,40 @@ public static string RemoveLeadingSpacesAndAsterisk(this string input) } public static string RemoveNumberOfLeadingTabsAfterNewline(this string input, int numberOfTabs) - { - return Regex.Replace(input, $"(?[\n|\r\n]+\t{{{numberOfTabs}}})", m => m.Value.Replace("\t", string.Empty)); + { + var firstTab = input.IndexOf("\t", StringComparison.OrdinalIgnoreCase); + + if (firstTab == -1) + { + return input; + } + int count = 0; + char firstNonTabCharacter = Char.MinValue; + + for (int i = firstTab; i < input.Length; i++) + { + if (input[i] != '\t') + { + firstNonTabCharacter = input[i]; + count = i - firstTab; + break; + } + } + + if (firstNonTabCharacter == '{' && numberOfTabs != count) + { + numberOfTabs = count; + } + + return Regex.Replace( + Regex.Replace( + input, + $"(?[\n|\r\n]+\t{{{numberOfTabs}}})", + m => m.Value.Replace("\t", string.Empty) + ), + $"(?[\n|\r\n]+\\s{{{numberOfTabs * 4}}})", + m => m.Value.Replace(" ", string.Empty) + ); } public static string[] SplitOnNewLines(this string input, StringSplitOptions options) @@ -92,6 +124,8 @@ public static string[] SplitOnNewLines(this string input, StringSplitOptions opt "\"2015-01-01T00:00:00\",lastActivity = \"0001-01-01T00:00:00\",leadDeveloper = " + "new { gender = \"Male\", id = 0, firstName = \"Martijn\", lastName = \"Laarman\" }," + "location = new { lat = 42.1523, lon = -80.321 }}" }, + { "_templateString", "\"{ \\\"match\\\": { \\\"text\\\": \\\"{{query_string}}\\\" } }\"" }, + { "base.QueryJson", "new{ @bool = new { must = new[] { new { match_all = new { } } }, must_not = new[] { new { match_all = new { } } }, should = new[] { new { match_all = new { } } }, filter = new[] { new { match_all = new { } } }, minimum_should_match = 1, boost = 2.0, } }" } }; public static bool TryGetJsonForAnonymousType(this string anonymousTypeString, out string json) diff --git a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs index 959e08c55f1..0002dfc7c86 100644 --- a/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs +++ b/src/CodeGeneration/Nest.Litterateur/Walkers/DocumentationFileWalker.cs @@ -11,7 +11,7 @@ namespace Nest.Litterateur.Walkers { class DocumentationFileWalker : CSharpSyntaxWalker { - private static readonly string[] PropertyNamesOfInterest = + private static readonly string[] PropertyOrMethodNamesOfInterest = { "ExpectJson", "QueryJson", @@ -79,7 +79,7 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { _propertyOrMethodName = node.Identifier.Text; - if (PropertyNamesOfInterest.Contains(_propertyOrMethodName)) + if (PropertyOrMethodNamesOfInterest.Contains(_propertyOrMethodName)) { // TODO: Look to get the generic types for the call so that we can prettify the fluent and OIS calls in docs e.g. client.Search({Call}); // var genericArguments = node.DescendantNodes().OfType().FirstOrDefault(); @@ -97,7 +97,7 @@ public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) public override void VisitArrowExpressionClause(ArrowExpressionClauseSyntax node) { - if (!this.InsideFluentOrInitializerExample) return; + if (!this.InsideFluentOrInitializerExample && !PropertyOrMethodNamesOfInterest.Contains(_propertyOrMethodName)) return; var syntaxNode = node?.ChildNodes()?.LastOrDefault()?.WithAdditionalAnnotations(); if (syntaxNode == null) return; var line = node.SyntaxTree.GetLineSpan(node.Span).StartLinePosition.Line; diff --git a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs index 7aee813a2a8..10a5b6ac3b7 100644 --- a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs +++ b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationMapping.doc.cs @@ -3,8 +3,7 @@ namespace Tests.Aggregations.Bucket.Children { - /** == Child Aggregation Mapping - */ + /** == Child Aggregation Mapping */ public class ChildrenAggregationMapping { private void MappingExample() @@ -17,7 +16,7 @@ private void MappingExample() .Mappings(map => map .Map(tm => tm.AutoMap()) .Map(tm => tm - .Parent() + .Parent() //<1> Set the parent of `CommitActivity` to the `Project` type ) ) ); diff --git a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs index b90e9009608..4d053f39840 100644 --- a/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Children/ChildrenAggregationUsageTests.cs @@ -6,11 +6,11 @@ namespace Tests.Aggregations.Bucket.Children { - /** == Children Aggregation + /** * A special single bucket aggregation that enables aggregating from buckets on parent document types to * buckets on child documents. * - * Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] + * Be sure to read {ref_current}/search-aggregations-bucket-children-aggregation.html[the elasticsearch documentation on Children Aggregation] */ public class ChildrenAggregationUsageTests : AggregationUsageTestBase { @@ -59,21 +59,4 @@ public ChildrenAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : b } }; } - - // TODO: This looks to be a duplicate of what is in the writing aggregations documentation - public class ChildrenAggregationDslUsage : ChildrenAggregationUsageTests - { - public ChildrenAggregationDslUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } - - protected override SearchRequest Initializer => - new SearchRequest - { - Aggregations = new ChildrenAggregation("name_of_child_agg", typeof(CommitActivity)) - { - Aggregations = - new AverageAggregation("average_per_child", Field(p => p.ConfidenceFactor)) - && new MaxAggregation("max_per_child", Field(p => p.ConfidenceFactor)) - } - }; - } } diff --git a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs index 0e93b4cb277..aacbc04d007 100644 --- a/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/DateHistogram/DateHistogramAggregationUsageTests.cs @@ -8,14 +8,14 @@ namespace Tests.Aggregations.Bucket.DateHistogram { - /** == Date Histogram Aggregation + /** * A multi-bucket aggregation similar to the histogram except it can only be applied on date values. * From a functionality perspective, this histogram supports the same features as the normal histogram. * The main difference is that the interval can be specified by date/time expressions. * - * When specifying a format and extended_bounds, in order for Elasticsearch to be able to parse - * the serialized DateTimes of extended_bounds correctly, the date_optional_time format is included - * as part of the format value. + * NOTE: When specifying a `format` **and** `extended_bounds`, in order for Elasticsearch to be able to parse + * the serialized ``DateTime`` of `extended_bounds` correctly, the `date_optional_time` format is included + * as part of the `format` value. * * Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. */ @@ -35,7 +35,7 @@ public DateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage field = "startedOn", interval = "month", min_doc_count = 2, - format = "yyyy-MM-dd'T'HH:mm:ss||date_optional_time", + format = "yyyy-MM-dd'T'HH:mm:ss||date_optional_time", //<1> Note the inclusion of `date_optional_time` to `format` order = new { _count = "asc" }, extended_bounds = new { @@ -119,7 +119,7 @@ protected override void ExpectResponse(ISearchResponse response) { /** === Handling responses * Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily - * in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] + * in the correct type. <> */ response.IsValid.Should().BeTrue(); diff --git a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs index d51c010faa5..9fb785b9f55 100644 --- a/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/DateRange/DateRangeAggregationUsageTests.cs @@ -8,7 +8,7 @@ namespace Tests.Aggregations.Bucket.DateRange { - /**== Date Range Aggregation + /** * A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the `from` * and `to` values can be expressed in `DateMath` expressions, and it is also possible to specify a date format by which the from and * to response fields will be returned. @@ -81,7 +81,7 @@ protected override void ExpectResponse(ISearchResponse response) { /** === Handling Responses * Using the `.Agg` aggregation helper we can fetch our aggregation results easily - * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + * in the correct type. <> */ response.IsValid.Should().BeTrue(); diff --git a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs index d7a0d3cc5ed..2887bace38a 100644 --- a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs @@ -9,7 +9,7 @@ namespace Tests.Aggregations.Bucket.Filter { - /**== Filter Aggregation + /** * Defines a single bucket of all the documents in the current document set context that match a specified filter. * Often this will be used to narrow down the current aggregation context to a specific set of documents. * @@ -69,7 +69,7 @@ protected override void ExpectResponse(ISearchResponse response) { /** === Handling Responses * Using the `.Aggs` aggregation helper we can fetch our aggregation results easily - * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + * in the correct type. <> */ response.IsValid.Should().BeTrue(); diff --git a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs index 294d0314c30..d6be0522745 100644 --- a/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filters/FiltersAggregationUsageTests.cs @@ -9,16 +9,17 @@ namespace Tests.Aggregations.Bucket.Filters { - /** == Filters Aggregation + /** * Defines a multi bucket aggregations where each bucket is associated with a filter. * Each bucket will collect all documents that match its associated filter. For documents * that do not match any filter, these will be collected in the _other bucket_. * - * Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. + * Be sure to read the Elasticsearch documentation on {ref_current}/search-aggregations-bucket-filters-aggregation.html[Filters Aggregation]. */ /**[float] - * == Named filters **/ + * == Named filters + */ public class FiltersAggregationUsageTests : AggregationUsageTestBase { public FiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -86,7 +87,7 @@ protected override void ExpectResponse(ISearchResponse response) { /** === Handling Responses * Using the `.Agg` aggregation helper we can fetch our aggregation results easily - * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + * in the correct type. <> */ response.IsValid.Should().BeTrue(); @@ -112,7 +113,8 @@ protected override void ExpectResponse(ISearchResponse response) } /**[float] - *== Anonymous filters **/ + *== Anonymous filters + */ public class AnonymousUsage : AggregationUsageTestBase { public AnonymousUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -179,7 +181,7 @@ protected override void ExpectResponse(ISearchResponse response) { /** === Handling Responses * Using the `.Agg` aggregation helper we can fetch our aggregation results easily - * in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() + * in the correct type. <> */ response.IsValid.Should().BeTrue(); @@ -198,7 +200,8 @@ protected override void ExpectResponse(ISearchResponse response) } /**[float] - * == Empty Filters */ + * == Empty Filters + */ public class EmptyFiltersAggregationUsageTests : AggregationUsageTestBase { public EmptyFiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -240,7 +243,8 @@ protected override void ExpectResponse(ISearchResponse response) } } - /** == Conditionless Filters */ + /**[float] + * == Conditionless Filters */ public class ConditionlessFiltersAggregationUsageTests : AggregationUsageTestBase { public ConditionlessFiltersAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } diff --git a/src/Tests/Aggregations/WritingAggregations.doc.cs b/src/Tests/Aggregations/WritingAggregations.doc.cs index 550a07e985c..4765ca181b9 100644 --- a/src/Tests/Aggregations/WritingAggregations.doc.cs +++ b/src/Tests/Aggregations/WritingAggregations.doc.cs @@ -5,12 +5,14 @@ using static Nest.Infer; using System.Collections.Generic; using System.Linq; +using Tests.Aggregations.Bucket.Children; +using Tests.Framework.Integration; +using FluentAssertions; namespace Tests.Aggregations { - /** == Writing Aggregations - * - * Aggregations are arguably one of the most powerful features of Elasticsearch. + /** + *== Writing Aggregations * NEST allows you to write your aggregations using * * - a strict fluent DSL @@ -137,4 +139,49 @@ protected override Func, ISearchRequest> Fluent } } } + + /**[[aggs-vs-aggregations]] + *=== Aggs vs. Aggregations + * + * The response exposesboth `.Aggregations` and `.Aggs` properties for handling aggregations. Why two properties you ask? + * Well, the former is a dictionary of aggregation names to `IAggregate` types, a common interface for + * aggregation responses (termed __Aggregates__ in NEST), and the latter, is a convenience helper to get the right type + * of aggregation response out of the dictionary based on a key name. + * + * This is better illustrated with an example + */ + public class AggsUsage : ChildrenAggregationUsageTests + { + public AggsUsage(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } + + /** Let's imagine we make the following request. */ + protected override Func, ISearchRequest> Fluent => s => s + .Aggregations(aggs => aggs + .Children("name_of_child_agg", child => child + .Aggregations(childAggs => childAggs + .Average("average_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + .Max("max_per_child", avg => avg.Field(p => p.ConfidenceFactor)) + ) + ) + ); + + /**=== Aggs usage + * Now, using `.Aggs`, we can easily get the `Children` aggregation response out and from that, + * the `Average` and `Max` sub aggregations. + */ + protected override void ExpectResponse(ISearchResponse response) + { + response.IsValid.Should().BeTrue(); + + var childAggregation = response.Aggs.Children("name_of_child_agg"); + + var averagePerChild = childAggregation.Average("average_per_child"); + + averagePerChild.Should().NotBeNull(); //<1> Do something with the average per child. Here we just assert it's not null + + var maxPerChild = childAggregation.Max("max_per_child"); + + maxPerChild.Should().NotBeNull(); //<2> Do something with the max per child. Here we just assert it's not null + } + } } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs index 32883c7461c..5e7e2a1c380 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/MaxRetries/RespectsMaxRetry.doc.cs @@ -8,11 +8,12 @@ namespace Tests.ClientConcepts.ConnectionPooling.MaxRetries { public class RespectsMaxRetry { - /**[[max-retries]] - * == Max Retries - * By default retry as many times as we have nodes. However retries still respect the request timeout. - * Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can - * but give up after 20 seconds + /**[[max-retries]] + *== Max Retries + * By default, NEST will retry as many times as there are nodes in the cluster that the client knows about. + * Retries still respects the request timeout however, + * meaning if you have a 100 node cluster and a request timeout of 20 seconds, + * the client will retry as many times as it before giving up at the request timeout of 20 seconds. */ [U] @@ -43,8 +44,9 @@ public async Task DefaultMaxIsNumberOfNodes() } /** - * When you have a 100 node cluster you might want to ensure a fixed number of retries. - * Remember that the actual number of requests is initial attempt + set number of retries + * When you have a 100 node cluster, you might want to ensure a fixed number of retries. + * + * IMPORTANT: the actual number of requests is **initial attempt + set number of retries** */ [U] @@ -69,9 +71,10 @@ public async Task FixedMaximumNumberOfRetries() ); } /** - * In our previous test we simulated very fast failures, in the real world a call might take upwards of a second - * Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. - * In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted + * In our previous test we simulated very fast failures, but in the real world a call might take upwards of a second. + * In this next example, we simulate a particular heavy search that takes 10 seconds to fail, and set a request timeout of 20 seconds. + * We see that the request is tried twice and gives up before a third call is attempted, since the call takes 10 seconds and thus can be + * tried twice (initial call and one retry) before the request timeout. */ [U] public async Task RespectsOveralRequestTimeout() @@ -94,10 +97,11 @@ public async Task RespectsOveralRequestTimeout() } /** - * If you set smaller request time outs you might not want it to also affect the retry timeout, therefor you can configure these separately too. - * Here we simulate calls taking 3 seconds, a request time out of 2 and an overall retry timeout of 10 seconds. - * We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 - * wins over the configured request timeout + * If you set a smaller request timeout you might not want it to also affect the retry timeout. + * In cases like this, you can configure the `MaxRetryTimeout` separately. + * Here we simulate calls taking 3 seconds, a request timeout of 2 seconds and a max retry timeout of 10 seconds. + * We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that + * our max retry timeout of 10 seconds wins over the configured request timeout */ [U] public async Task RespectsMaxRetryTimeoutOverRequestTimeout() @@ -123,7 +127,7 @@ public async Task RespectsMaxRetryTimeoutOverRequestTimeout() } /** - * If your retry policy expands beyond available nodes we won't retry the same node twice + * If your retry policy expands beyond the number of available nodes, the client **won't** retry the same node twice */ [U] public async Task RetriesAreLimitedByNodesInPool() @@ -146,9 +150,9 @@ public async Task RetriesAreLimitedByNodesInPool() } /** - * This makes setting any retry setting on a single node connection pool a NOOP, this is by design! - * Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and - * not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. + * This makes setting any retry setting on a single node connection pool a no-op by design! + * Connection pooling and failover is all about trying to fail sanely whilst still utilizing the available resources and + * not giving up on the fail fast principle; **It is NOT a mechanism for forcing requests to succeed.** */ [U] public async Task DoesNotRetryOnSingleNodeConnectionPool() @@ -166,7 +170,6 @@ public async Task DoesNotRetryOnSingleNodeConnectionPool() { BadResponse, 9200 } } ); - } } } diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.doc.cs similarity index 79% rename from src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs rename to src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.doc.cs index b0e1af88864..137fbc40af4 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FeaturesInference.doc.cs @@ -8,14 +8,16 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FeaturesInference { - /**== Features + /**[[features-inference]] + * == Features Inference * Some URIs in Elasticsearch take a `Feature` enum. * Within NEST, route values on the URI are represented as classes that implement an interface, `IUrlParameter`. * Since enums _cannot_ implement interfaces in C#, a route parameter that would be of type `Feature` is represented using the `Features` class that * the `Feature` enum implicitly converts to. */ - /** Using the `Features` constructor directly is possible but rather involved */ + /**=== Constructor + * Using the `Features` constructor directly is possible but rather involved */ [U] public void Serializes() { Features fieldString = Feature.Mappings | Feature.Aliases; @@ -27,7 +29,7 @@ [U] public void Serializes() public void ImplicitConversion() { /** === Implicit conversion - * Here we new an GET index elasticsearch request whichs takes Indices and Features. + * Here we instantiate a GET index request whichs takes two features, settings and warmers. * Notice how we can use the `Feature` enum directly. */ var request = new GetIndexRequest(All, Feature.Settings | Feature.Warmers); diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs index 21dcc4d62d0..8cf2774f1a2 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs @@ -19,7 +19,7 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class FieldInferrence { - /**== Strongly typed Field Access + /**== Field Inference * * Several places in the elasticsearch API expect the path to a field from your original source document as a string. * NEST allows you to use C# expressions to strongly type these field path strings. @@ -27,13 +27,14 @@ public class FieldInferrence * These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: */ - /** Using the constructor directly is possible but rather involved */ + /**=== Constructor + * Using the constructor directly is possible but rather involved */ [U] public void UsingConstructors() { var fieldString = new Field { Name = "name" }; - /** especially when using C# expressions since these can not be simply new'ed*/ + /** This is more cumbersome when using C# expressions since they cannot be instantiated easily*/ Expression> expression = p => p.Name; var fieldExpression = Field.Create(expression); @@ -42,13 +43,14 @@ public void UsingConstructors() .WhenSerializing(fieldString); } - /** Therefore you can also implicitly convert strings and expressions to `Field`s */ + /**=== Implicit Conversion + * Therefore you can also implicitly convert strings and expressions to ``Field``s */ [U] public void ImplicitConversion() { Field fieldString = "name"; - /** but for expressions this is still rather involved */ + /** but for expressions this is _still_ rather involved */ Expression> expression = p => p.Name; Field fieldExpression = expression; @@ -57,7 +59,9 @@ public void ImplicitConversion() .WhenSerializing(fieldString); } - /** to ease creating `Field`s from expressions there is a static Property class you can use */ + /**=== ``Nest.Infer`` + * to ease creating ``Field``s from expressions there is a static `Infer` class you can use + */ [U] public void UsingStaticPropertyField() { @@ -66,18 +70,21 @@ public void UsingStaticPropertyField() /** but for expressions this is still rather involved */ var fieldExpression = Infer.Field(p => p.Name); - /** this can be even shortened even further using static imports in c# 6 i.e. - `using static Nest.Static;` + /** this can be even shortened even further using a https://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. + `using static Nest.Infer;` */ fieldExpression = Field(p => p.Name); - /** Now this is much much terser then our first example using the constructor! */ + /** Now that is much terser then our first example using the constructor! */ Expect("name") .WhenSerializing(fieldString) .WhenSerializing(fieldExpression); } - /** By default, NEST will camel-case all field names to be more _javascript-y_ */ + /**=== Field name casing + * By default, NEST will camel-case **all** field names to better align with typical + * javascript/json conventions + */ [U] public void DefaultFieldNameInferrer() { @@ -86,31 +93,34 @@ public void DefaultFieldNameInferrer() setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); - /** However string are *always* passed along verbatim */ + /** However ``string``s are *always* passed along verbatim */ setup.Expect("NaMe").WhenSerializing("NaMe"); - /** if you want the same behavior for expressions simply do nothing in the default inferrer */ + /** if you want the same behavior for expressions, simply pass a Func to `DefaultFieldNameInferrer` + * to make no changes to the name + */ setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); setup.Expect("Name").WhenSerializing(Field(p => p.Name)); } - /** === Complex field name expressions */ + /**=== Complex field name expressions */ [U] public void ComplexFieldNameExpressions() { - /** You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName */ + /** You can follow your property expression to any depth. Here we are traversing to the ``LeadDeveloper``'s `FirstName` */ Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); /** When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections */ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); - /** Similarly, LINQ's `.First()` method also works - * NOTE: remember these are expressions and not actual code that will be executed */ + /** Similarly, LINQ's `.First()` method also works */ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); Expect("curatedTags.added").WhenSerializing(Field(p => p.CuratedTags[0].Added)); Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.First().Name)); - /** An indexer on a dictionary is assumed to describe a property name */ + /** NOTE: Remember, these are _expressions_ and not actual code that will be executed + * + * An indexer on a dictionary is assumed to describe a property name */ Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metadata["hardcoded"].Created)); @@ -121,9 +131,9 @@ public void ComplexFieldNameExpressions() /** * If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow - * you to analyze a string in a number of different ways, these _"virtual"_ sub fields + * you to analyze a string in a number of different ways, these __"virtual"__ sub fields * do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that - * should be mapped and link:../mapping/auto-map[how they are mapped] + * should be mapped and <> */ Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); Expect("curatedTags.raw").WhenSerializing(Field(p => p.CuratedTags[0].Suffix("raw"))); @@ -169,7 +179,7 @@ public void AppendingSuffixToExpressions() Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); } - /** === Annotations + /**=== Annotations * * When using NEST's property attributes you can specify a new name for the properties */ @@ -248,8 +258,9 @@ public void ExpressionsAreCachedButSeeDifferentTypes() fieldNameOnB.Should().Be("c.name"); /** - * now we create a new connectionsettings with a remap for C on class A to `d` - * now when we resolve the field path for A will be different + * now we create a new connectionsettings with a remap for `C` on class `A` to `"d"` + * now when we resolve the field path for property `C` on `A`, it will be different than + * for property `C` on `B` */ var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s .InferMappingFor(m => m diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs index a8b0e478a77..83367c79c90 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IdsInference.doc.cs @@ -7,7 +7,8 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence { public class IdsInference { - /**== Id Inference + /**[[ids-inference]] + *== Ids Inference * * === Implicit Conversions * diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs index a7cbfd93972..1bbeef52b09 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IndicesPaths.doc.cs @@ -12,7 +12,8 @@ public class IndicesPaths * In nest this is encoded using `Indices` */ - /** Several types implicitly convert to `Indices` */ + /**=== Implicit Conversion + * Several types implicitly convert to `Indices` */ [U] public void ImplicitConversionFromString() { Nest.Indices singleIndexFromString = "name"; @@ -38,16 +39,18 @@ [U] public void ImplicitConversionFromString() ); } - /** to ease creating Field's from expressions there is a static Property class you can use */ + /**=== Using `Nest.Indices` + * To ease creating ``Indice``s from expressions, there is a static `Nest.Indices` class you can use + */ [U] public void UsingStaticPropertyField() { - /** */ - var all = Nest.Indices.All; - var many = Nest.Indices.Index("name1", "name2"); - var manyTyped = Nest.Indices.Index().And(); - var singleTyped = Nest.Indices.Index(); + var all = Nest.Indices.All; //<1> Using "_all" indices + var many = Nest.Indices.Index("name1", "name2"); //<2> specifying multiple indices using strings + var manyTyped = Nest.Indices.Index().And(); //<3> speciying multiple using types + var singleTyped = Nest.Indices.Index(); var singleString = Nest.Indices.Index("name1"); - var invalidSingleString = Nest.Indices.Index("name1, name2"); + + var invalidSingleString = Nest.Indices.Index("name1, name2"); //<4> **invalid** single index name } } } diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs index ec6b0de0b2a..5d1dfbe63c5 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs @@ -8,10 +8,12 @@ namespace Tests.ClientConcepts.HighLevel.Inferrence.PropertyNames { - /**== Property Names */ + /**[[property-inference]] + * == Property Name Inference + */ public class PropertyNames { - /** + /**=== Using `.Suffix()` extension method on `object` * Property names resolve to the last token. An example using the `.Suffix()` extension */ [U] public void PropertyNamesAreResolvedToLastTokenUsingSuffix() @@ -20,7 +22,7 @@ [U] public void PropertyNamesAreResolvedToLastTokenUsingSuffix() Expect("raw").WhenSerializing(expression); } - /** + /**=== `.ApplySuffix()` extension method on Expression Delegates * And an example using the `.ApplySuffix()` extension on lambda expressions */ [U] @@ -31,7 +33,7 @@ public void PropertyNamesAreResolvedToLastTokenUsingApplySuffix() Expect("raw").WhenSerializing(expression); } - /** Property names cannot contain a `.` in order to prevent the potential for collision with a field that + /** Property names cannot contain a ``.``. in order to prevent the potential for collision with a field that * may have {ref_current}/_multi_fields.html[`multi_fields`] */ [U] public void StringsContainingDotsIsAnException() diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs index 66496564eae..6eaddcba8aa 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/AutoMap.doc.cs @@ -234,17 +234,18 @@ public void UsingAutoMap() Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); } - /** ## Automapping with overrides + /**[float] + * == Auto mapping with overrides * In most cases, you'll want to map more than just the vanilla datatypes and also provide - * various options on your properties (analyzer, doc_values, etc...). In that case, it's - * possible to use AutoMap() in conjuction with explicitly mapped properties. + * various options for your properties (analyzer to use, whether to enable doc_values, etc...). + * In that case, it's possible to use `.AutoMap()` in conjuction with explicitly mapped properties. */ [U] public void OverridingAutoMappedProperties() { /** - * Here we are using AutoMap() to automatically map our company type, but then we're + * Here we are using `.AutoMap()` to automatically map our company type, but then we're * overriding our employee property and making it a `nested` type, since by default, - * AutoMap() will infer objects as `object`. + * `.AutoMap()` will infer objects as `object`. */ var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -286,10 +287,12 @@ [U] public void OverridingAutoMappedProperties() Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); } - /** ## Automap with attributes - * It is also possible to define your mappings using attributes on your POCOS. When you + /**[[attribute-mapping]] + * [float] + * == Attribute mapping + * It is also possible to define your mappings using attributes on your POCOs. When you * use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. - * Here we define the same two types but this time using attributes. + * Here we define the same two types as before, but this time using attributes to define the mappings. */ [ElasticsearchType(Name = "company")] public class CompanyWithAttributes @@ -327,9 +330,7 @@ public class EmployeeWithAttributes public List Employees { get; set; } } - /** - Then map the types by calling `.AutoMap()` - */ + /**Then we map the types by calling `.AutoMap()` */ [U] public void UsingAutoMapWithAttributes() { @@ -641,7 +642,8 @@ public void OverridingAutoMappedAttributes() Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); } - /** == Ignoring Properties + /**[float] + * == Ignoring Properties * Properties on a POCO can be ignored in a few ways: * * - Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO @@ -705,7 +707,8 @@ public void IgnoringProperties() settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); } - /** == Mapping Recursion + /**[float] + * == Mapping Recursion * If you notice in our previous `Company` and `Employee` examples, the `Employee` type is recursive * in that the `Employee` class itself contains a collection of type `Employee`. By default, `.AutoMap()` will only * traverse a single depth when it encounters recursive instances like this. Hence, in the @@ -802,25 +805,30 @@ public void ControllingRecursionDepth() Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); } - /** == Applying conventions through the Visitor pattern + /**[float] + * == Applying conventions through the Visitor pattern * It is also possible to apply a transformation on all or specific properties. * - * AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, + * AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, * does nothing and acts as a blank canvas for you to implement your own visiting methods. * - * For instance, lets create a custom visitor that disables doc values for numeric and boolean types. + * For instance, lets create a custom visitor that disables doc values for numeric and boolean types * (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) */ public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor - { - // Override the Visit method on INumberProperty and set DocValues = false - public override void Visit(INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + public override void Visit( + INumberProperty type, + PropertyInfo propertyInfo, + ElasticsearchPropertyAttributeBase attribute) //<1> Override the `Visit` method on `INumberProperty` and set `DocValues = false` { type.DocValues = false; } - // Similarily, override the Visit method on IBooleanProperty and set DocValues = false - public override void Visit(IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + public override void Visit( + IBooleanProperty type, + PropertyInfo propertyInfo, + ElasticsearchPropertyAttributeBase attribute) //<2> Similarily, override the `Visit` method on `IBooleanProperty` and set `DocValues = false` { type.DocValues = false; } @@ -832,12 +840,12 @@ public void UsingACustomPropertyVisitor() /** Now we can pass an instance of our custom visitor to `.AutoMap()` */ var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms - .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) //<1> Pass your `IPropertyVisitor` implementation to `.AutoMap` + .Map(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) ); - /** and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBooleanProperty`) - * it will apply the transformation defined in each `Visit()` respectively, which in this example - * disables {ref_current}/doc-values.html[doc values]. + /** and anytime the client maps a property of the POCO (``Employee`` in this example) as a number (``INumberProperty``) or boolean (``IBooleanProperty``), + * it will apply the transformation defined in each `Visit()` call respectively, which in this example + * disables {ref_current}/doc-values.html[doc_values]. */ var expected = new { @@ -880,14 +888,16 @@ public void UsingACustomPropertyVisitor() }; } - /** You can even take the visitor approach a step further, and instead of visiting on IProperty types, visit - * directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types - * to an Elasticsearch string (`IStringProperty`). + /**=== Visiting on ``PropertyInfo`` + * You can even take the visitor approach a step further, and instead of visiting on `IProperty` types, visit + * directly on your POCO properties (``PropertyInfo``). As an example, let's create a visitor that maps all CLR types + * to an Elasticsearch string (``IStringProperty``). */ public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { - public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => - new StringProperty(); + public override IProperty Visit( + PropertyInfo propertyInfo, + ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); } [U] diff --git a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs index ba6ca6a3b5f..50cbf5a10f8 100644 --- a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs @@ -78,13 +78,12 @@ public void SpecifyingClientOptions() public void AvailableOptions() { - var client = new ElasticLowLevelClient(); - var config = new ConnectionConfiguration() .DisableAutomaticProxyDetection() // <1> Disable automatic proxy detection. Defaults to `true`. .EnableHttpCompression() // <2> Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. See the {ref_current}/modules-http.html[http module settings] for more info). .DisableDirectStreaming(); // <3> By default responses are deserialized directly from the response stream to the object you tell it to. For debugging purposes, it can be very useful to keep a copy of the raw response on the result object, which is what calling this method will do. + var client = new ElasticLowLevelClient(config); var result = client.Search>(new { size = 12 }); /** This will only have a value if the client configuration has `DisableDirectStreaming` set */ diff --git a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs index cb78b2bcbe4..a81285e9b66 100644 --- a/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/PostData.doc.cs @@ -15,7 +15,7 @@ public class PostingData { /**== Post data * The low level client allows you to post a `string` or `byte[]` array directly. On top of this, - * if you pass a collection of `string`s or `object`s they will be serialized + * if you pass a collection of ``string``s or ``object``s they will be serialized * using Elasticsearch's special bulk/multi format. */ private readonly string @string = "fromString"; @@ -40,7 +40,7 @@ public PostingData() [U] public void ImplicitConversions() { - /** Even though the argument for `PostData` on the low level client takes a `PostData`, + /** Even 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 completely. * You can implicitly convert from the following types * - `string` @@ -65,8 +65,7 @@ [U] public void ImplicitConversions() fromListOfObject.Type.Should().Be(PostType.EnumerableOfObject); fromObject.Type.Should().Be(PostType.Serializable); - // and passing a `PostData` object to a method taking `PostData` should not wrap - + /** and passing a `PostData` object to a method taking `PostData` should not wrap */ fromString = ImplicitlyConvertsFrom(fromString); fromByteArray = ImplicitlyConvertsFrom(fromByteArray); fromListOfString = ImplicitlyConvertsFrom(fromListOfString); @@ -88,7 +87,6 @@ [U] public async Task WritesCorrectlyUsingBothLowAndHighLevelSettings() private async Task AssertOn(IConnectionConfigurationValues settings) { - /** Although each implicitly types behaves slightly differently */ await Post(() => @string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); @@ -107,10 +105,10 @@ private async Task AssertOn(IConnectionConfigurationValues settings) /** In all other cases postdata is serialized as is. */ await Post(() => @object, writes: objectJson, storesBytes: false, settings: settings); - /** If you want to maintain a copy of the request that went out use the following settings */ + /** If you want to maintain a copy of the request that went out, use `DisableDirectStreaming` */ settings = new ConnectionSettings().DisableDirectStreaming(); - /** by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream + /** by forcing `DisableDirectStreaming` on connection settings, serialization happens first in a private `MemoryStream` * so we can get hold of the serialized bytes */ await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); diff --git a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs index 30e29b5924f..8534d1f13b9 100644 --- a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs +++ b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs @@ -9,14 +9,14 @@ namespace Tests.QueryDsl.BoolDsl { - /** == Bool Queries + /**== Bool Queries */ public class BoolDslTests : OperatorUsageBase { protected readonly IElasticClient Client = TestClient.GetFixedReturnClient(new { }); /** Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, - * take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses + * take a single {ref_current}/query-dsl-bool-query.html[``bool`` query] with only two clauses */ public void VerboseWay() { @@ -81,27 +81,38 @@ public void UsingOperator() *.... */ - [U] public void JoinsMustQueries() => + [U] public void JoinsMustQueries() + { Assert( q => q.Query() && q.Query() && q.Query(), Query && Query && Query, c => c.Bool.Must.Should().HaveCount(3) - ); + ); + } /** The bool DSL offers also a short hand notation to mark a query as a `must_not` using the `!` operator */ - [U] public void MustNotOperator() => + [U] public void MustNotOperator() + { Assert(q => !q.Query(), !Query, c => c.Bool.MustNot.Should().HaveCount(1)); + } /** And to mark a query as a `filter` using the `+` operator*/ - [U] public void UnaryAddOperator() => + [U] public void UnaryAddOperator() + { Assert(q => +q.Query(), +Query, c => c.Bool.Filter.Should().HaveCount(1)); + } /** Both of these can be combined with `&&` to form a single bool query */ - [U] public void MustNotOperatorAnd() => + + [U] public void MustNotOperatorAnd() + { Assert(q => !q.Query() && !q.Query(), !Query && !Query, c => c.Bool.MustNot.Should().HaveCount(2)); + } - [U] public void UnaryAddOperatorAnd() => + [U] public void UnaryAddOperatorAnd() + { Assert(q => +q.Query() && +q.Query(), +Query && +Query, c => c.Bool.Filter.Should().HaveCount(2)); + } /** === Combining/Merging bool queries * @@ -148,30 +159,33 @@ [U] public void JoinsMustWithMustNot() * |___term *.... */ - - [U] public void JoinsMustWithMustNotAndFilter() => + [U] public void JoinsMustWithMustNotAndFilter() + { Assert( q => q.Query() && q.Query() && q.Query() && !q.Query() && +q.Query() && +q.Query(), Query && Query && Query && !Query && +Query && +Query, - c=> + c => { c.Bool.Must.Should().HaveCount(3); c.Bool.MustNot.Should().HaveCount(1); c.Bool.Filter.Should().HaveCount(2); }); + } /** You can still mix and match actual bool queries with the bool DSL e.g * `bool(must=term, term, term) && !term` would still merge into a single `bool` query. */ - [U] public void MixAndMatch() => + [U] public void MixAndMatch() + { Assert( - q => q.Bool(b=>b.Must(mq=>mq.Query(),mq=>mq.Query(), mq=>mq.Query())) && !q.Query(), + q => q.Bool(b => b.Must(mq => mq.Query(), mq => mq.Query(), mq => mq.Query())) && !q.Query(), new BoolQuery { Must = new QueryContainer[] { Query, Query, Query } } && !Query, - c=> + c => { c.Bool.Must.Should().HaveCount(3); c.Bool.MustNot.Should().HaveCount(1); }); + } /* NEST will also do the same with `should`s or `||` when it sees that the boolean queries in play **ONLY** consist of `should` clauses. * This is because the `bool` query does not quite follow the same boolean logic you expect from a programming language. @@ -218,12 +232,12 @@ [U] public void MixAndMatch() => * |___term4 *.... */ - - [U] public void JoinsWithShouldClauses() => + [U] public void JoinsWithShouldClauses() + { Assert( q => q.Query() && (q.Query() || q.Query() || q.Query()), Query && (Query || Query || Query), - c=> + c => { c.Bool.Must.Should().HaveCount(2); var lastClause = c.Bool.Must.Last() as IQueryContainer; @@ -231,6 +245,7 @@ [U] public void JoinsWithShouldClauses() => lastClause.Bool.Should().NotBeNull(); lastClause.Bool.Should.Should().HaveCount(3); }); + } /** TIP: You can add parentheses to force evaluation order * @@ -244,25 +259,28 @@ [U] public void JoinsWithShouldClauses() => * if NEST identified both sides of the OR operation as only containing `should` clauses and it would * join them together it would give a different meaning to the `minimum_should_match` parameter of the first boolean query. * Rewriting this to a single bool with 5 `should` clauses would break because only matching on `term5` or `term6` should still be a hit. - **/ - [U] public void MixAndMatchMinimumShouldMatch() => + **/ + [U] + public void MixAndMatchMinimumShouldMatch() + { Assert( - q => q.Bool(b=>b - .Should(mq=>mq.Query(),mq=>mq.Query(), mq=>mq.Query(), mq=>mq.Query()) - .MinimumShouldMatch(2) - ) - || !q.Query() || q.Query(), + q => q.Bool(b => b + .Should(mq => mq.Query(), mq => mq.Query(), mq => mq.Query(), mq => mq.Query()) + .MinimumShouldMatch(2) + ) + || !q.Query() || q.Query(), new BoolQuery { Should = new QueryContainer[] { Query, Query, Query, Query }, MinimumShouldMatch = 2 } || !Query || Query, - c=> + c => { c.Bool.Should.Should().HaveCount(3); var nestedBool = c.Bool.Should.First() as IQueryContainer; nestedBool.Bool.Should.Should().HaveCount(4); }); + } /** === Locked bool queries * @@ -271,30 +289,37 @@ [U] public void MixAndMatchMinimumShouldMatch() => * * Here we demonstrate that two locked `bool` queries are not combined */ - [U] public void DoNotCombineLockedBools() => + [U] public void DoNotCombineLockedBools() + { Assert( - q => q.Bool(b=>b.Name("leftBool").Should(mq=>mq.Query())) - || q.Bool(b=>b.Name("rightBool").Should(mq=>mq.Query())), + q => q.Bool(b => b.Name("leftBool").Should(mq => mq.Query())) + || q.Bool(b => b.Name("rightBool").Should(mq => mq.Query())), new BoolQuery { Name = "leftBool", Should = new QueryContainer[] { Query } } - || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, - c=>AssertDoesNotJoinOntoLockedBool(c, "leftBool")); + || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, + c => AssertDoesNotJoinOntoLockedBool(c, "leftBool")); + } - /** neither are two `bool` queries where either the left or the right query is locked */ - [U] public void DoNotCombineRightLockedBool() => + /** neither are two `bool` queries where either right query is locked */ + [U] public void DoNotCombineRightLockedBool() + { Assert( - q => q.Bool(b=>b.Should(mq=>mq.Query())) - || q.Bool(b=>b.Name("rightBool").Should(mq=>mq.Query())), + q => q.Bool(b => b.Should(mq => mq.Query())) + || q.Bool(b => b.Name("rightBool").Should(mq => mq.Query())), new BoolQuery { Should = new QueryContainer[] { Query } } - || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, - c=>AssertDoesNotJoinOntoLockedBool(c, "rightBool")); + || new BoolQuery { Name = "rightBool", Should = new QueryContainer[] { Query } }, + c => AssertDoesNotJoinOntoLockedBool(c, "rightBool")); + } - [U] public void DoNotCombineLeftLockedBool() => + /** or the left query is locked */ + [U] public void DoNotCombineLeftLockedBool() + { Assert( - q => q.Bool(b=>b.Name("leftBool").Should(mq=>mq.Query())) - || q.Bool(b=>b.Should(mq=>mq.Query())), + q => q.Bool(b => b.Name("leftBool").Should(mq => mq.Query())) + || q.Bool(b => b.Should(mq => mq.Query())), new BoolQuery { Name = "leftBool", Should = new QueryContainer[] { Query } } - || new BoolQuery { Should = new QueryContainer[] { Query } }, - c=>AssertDoesNotJoinOntoLockedBool(c, "leftBool")); + || new BoolQuery { Should = new QueryContainer[] { Query } }, + c => AssertDoesNotJoinOntoLockedBool(c, "leftBool")); + } private static void AssertDoesNotJoinOntoLockedBool(IQueryContainer c, string firstName) { diff --git a/src/Tests/QueryDsl/Span/Not/SpanNotQueryUsageTests.cs b/src/Tests/QueryDsl/Span/Not/SpanNotQueryUsageTests.cs index 17b41a1fc2e..ddb45def3df 100644 --- a/src/Tests/QueryDsl/Span/Not/SpanNotQueryUsageTests.cs +++ b/src/Tests/QueryDsl/Span/Not/SpanNotQueryUsageTests.cs @@ -36,8 +36,20 @@ public SpanNotUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage Dist = 12, Post = 13, Pre = 14, - Include = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya" } }, - Exclude = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2" } }, + Include = new SpanQuery + { + SpanTerm = new SpanTermQuery + { + Field = "field1", Value = "hoya" + } + }, + Exclude = new SpanQuery + { + SpanTerm = new SpanTermQuery + { + Field = "field1", Value = "hoya2" + } + }, }; protected override QueryContainer QueryFluent(QueryContainerDescriptor q) => q diff --git a/src/Tests/QueryDsl/Specialized/Script/ScriptQueryUsageTests.cs b/src/Tests/QueryDsl/Specialized/Script/ScriptQueryUsageTests.cs index 7c07d261865..783fe28028a 100644 --- a/src/Tests/QueryDsl/Specialized/Script/ScriptQueryUsageTests.cs +++ b/src/Tests/QueryDsl/Specialized/Script/ScriptQueryUsageTests.cs @@ -23,9 +23,6 @@ public ScriptUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) param1 = 1 } } - - - }; protected override QueryContainer QueryInitializer => new ScriptQuery diff --git a/src/Tests/QueryDsl/Specialized/Template/TemplateQueryUsageTests.cs b/src/Tests/QueryDsl/Specialized/Template/TemplateQueryUsageTests.cs index 014dc1a0ced..c6288903a2c 100644 --- a/src/Tests/QueryDsl/Specialized/Template/TemplateQueryUsageTests.cs +++ b/src/Tests/QueryDsl/Specialized/Template/TemplateQueryUsageTests.cs @@ -23,8 +23,6 @@ public TemplateUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usag query_string = "all about search" } } - - }; protected override QueryContainer QueryInitializer => new TemplateQuery diff --git a/src/Tests/aggregations.asciidoc b/src/Tests/aggregations.asciidoc index 38c5c57c03a..fd5ea121571 100644 --- a/src/Tests/aggregations.asciidoc +++ b/src/Tests/aggregations.asciidoc @@ -5,7 +5,8 @@ [partintro] -- -Something about aggregations +Aggregations are arguably one of the most powerful features of Elasticsearch and NEST +exposes all of the available Aggregation types -- include::{output-dir}/writing-aggregations.asciidoc[] diff --git a/src/Tests/client-concepts.asciidoc b/src/Tests/client-concepts.asciidoc index eb7ac6d6167..1d9bbe92f75 100644 --- a/src/Tests/client-concepts.asciidoc +++ b/src/Tests/client-concepts.asciidoc @@ -1,11 +1,7 @@ -[[client-concepts]] -= Client Concepts - -include::low-level.asciidoc[] +include::low-level.asciidoc[] include::high-level.asciidoc[] -include::connection-pooling.asciidoc[] diff --git a/src/Tests/high-level.asciidoc b/src/Tests/high-level.asciidoc index 6cab2b234d9..538b8230d3e 100644 --- a/src/Tests/high-level.asciidoc +++ b/src/Tests/high-level.asciidoc @@ -1,20 +1,38 @@ :output-dir: client-concepts/high-level -[[high-level]] -== High Level +[[nest]] += Client Concepts - High Level -A high level client that provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL -and takes advantage of specific .NET features such as covariant results. +[partintro] +-- +The high level client, `ElasticClient`, provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL. -NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> +It can be installed from the Package Manager Console inside Visual Studio using + +[source, shell] +---- +Install-Package NEST +---- + +Or by searching for https://www.nuget.org/packages/NEST[NEST] in the Package Manager GUI. + +NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> via +the `.LowLevel` property on `ElasticClient`. There are a number of conventions that NEST uses for inference of -- Field and Property names -- Document ids -- Building a URI path to a document -- Building a URI path to one or more indices -- Inferring +- <> and <> +- <> +- <> +- <> +- <> + +In addition to features such as + +- <> +- <> + +-- include::{output-dir}/inference/field-inference.asciidoc[] @@ -32,6 +50,8 @@ include::{output-dir}/mapping/auto-map.asciidoc[] include::{output-dir}/covariant-hits/covariant-search-results.asciidoc[] +include::connection-pooling.asciidoc[] + diff --git a/src/Tests/index.asciidoc b/src/Tests/index.asciidoc index 212cd2f5d73..b90d7bcdd69 100644 --- a/src/Tests/index.asciidoc +++ b/src/Tests/index.asciidoc @@ -1,5 +1,5 @@ [[elasticsearch-net-reference]] -= Elasticsearch.Net and NEST: the .NET Elasticsearch clients += Elasticsearch.Net and NEST: the .NET clients include::intro.asciidoc[] diff --git a/src/Tests/low-level.asciidoc b/src/Tests/low-level.asciidoc index 78b02a70ded..14ca78883e9 100644 --- a/src/Tests/low-level.asciidoc +++ b/src/Tests/low-level.asciidoc @@ -1,8 +1,10 @@ :output-dir: client-concepts/low-level -[[low-level]] -== Low Level +[[elasticsearch-net]] += Client Concepts - Low Level +[partintro] +-- The low level client, `ElasticLowLevelClient`, is a low level, dependency free client that has no opinions about how you build and represent your requests and responses. @@ -13,7 +15,9 @@ It can be installed from the Package Manager Console inside Visual Studio using Install-Package Elasticsearch.Net ---- -Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[`Elasticsearch.Net`] in the Package Manager GUI. +Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. +-- + include::{output-dir}/connecting.asciidoc[] diff --git a/src/Tests/query-dsl-usage.asciidoc b/src/Tests/query-dsl-usage.asciidoc index 21ee0ca3e77..ae871f36c9f 100644 --- a/src/Tests/query-dsl-usage.asciidoc +++ b/src/Tests/query-dsl-usage.asciidoc @@ -1,4 +1,4 @@ -:includes-from-dirs: +:includes-from-dirs: query-dsl/compound,query-dsl/full-text,query-dsl/geo,query-dsl/joining,query-dsl/nest-specific,query-dsl/span,query-dsl/specialized,query-dsl/term-level diff --git a/src/Tests/query-dsl.asciidoc b/src/Tests/query-dsl.asciidoc index 76eedce8e11..f79459d44c0 100644 --- a/src/Tests/query-dsl.asciidoc +++ b/src/Tests/query-dsl.asciidoc @@ -5,7 +5,7 @@ [partintro] -- -Something about the query DSL +NEST exposes all of the query DSL endpoints available in Elasticsearch -- include::{output-dir}/bool-dsl/bool-dsl.asciidoc[] diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index 1b6eb5b04c2ab2210ea54acdaf9375aa1d2aea45..1462a94be62966ab9631d4041fcc61996e5d17bf 100644 GIT binary patch literal 74752 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%0AP zC*P9oiJmF&1HlyHK9B5QNoNuKam4+Wzb^+<(U&9s705nDI#1!3gFg{(2)yJ?AUXuu zy{1fT2V`cJ&%w-&(AMzrR}q34dp`C=zu| zP0jP$B1q_ld=W)BUM7M>;kG0Z#KOMbF22m$?Kv1BW!>j1f{1RvP=biNvqA(pfA^u* z2qHmI1{-Wf5N@|?O$50hQE6lmY`>{b1VPzlC_?mLbIS-a?Kkj>AQ-gi2r`}QG#NoU z*h?pZOtAk}1ex~V^hXd3ip1T!C5oVXcB1T>Te1pc)5Hjgce3qF1Zj7(zzFf(%`PLv zcQ*-&5I-#&8%K%n?}F`b{t`jbI1Vp@q`Og0g!t*8c|;J3dM|Z%1&W~G-F+@X{QM3g z5rn*LT_Xs1djv%gDA?RJf|R!vSpb(nLArX5S=hT*t{!>l(&6b6p8#MWD%qa zx3rHW=ALCL5{~oDx^LF;xZ*xTd;jov1ZYOW}$t20=l_TF7 zdGF`DkGkU2hFxA-JhyHt6G9_6|8usx+xm#P>>SwYjA)%#KVp`hr8{3-aNkO|BBPnR~_v@;2_w*@E#|g5RSc#&ty;*6Z z^JNFNIz4>3K@MLoO;KB8TT_WP@Nn&(JG>q$+T^^d(hP5H-)%&%{MPpUL1_xy9TQ8; zfd3p&Lc;D0M~SKC`_1SHx5zQ!C0=WC)z1i8Y-z@~`A-?qEpPSCd|r>HI*)x|*VBBx zVCK2KUTH;eJlph^c*TgQyTfm3DYuY&b~kjNtD{$dFFnWGez{Z&yr=q7QZIN;k1p))VkJyop7#T`^_X(lwzZQ@kM^?7t_ zU`y2XEzA1+>$?(K$9g<>*3F=YYLo*Tr1(bh*nJw{4XJbIS3?H$TJYMA{jPQXvfuGv zxvLR(;5BJ)xJ&W-;BUq|epxa%ljn7L-M=F~Z+e~c`A3!mj_0-OVEh|+4J%6_Zh)61 zh<^aQfpzKuZ)Bb61g7!D@mALvz@vT+|3zNs4#ZzcWLf697rrdhI1QoU_`LPy6+YWu zVUH}QxCp~{z<(LPAO6ii;>c%VvYg}~UI`DwKb^n?eg-{z;$KXnJK--z*)I6+VNVvn z2l0pEKTSS%#Xpiv%5py0=5IHAiOWytK=LcgCLcksEDOE~`3(N)*jtI;jdb?FUyPn1 z__7RzpUxQ4+Zq2F^vbf6vDm#m{yQ6Z%f!2*FUH@8VBe1TeenC^zkojg|6Sx{Y02ZH zFH0ULQ4ZVUXONR++h3EuEFXP{^he;AVb>`9J|sQ}e;d;4i~j_f*d2cw>56Rw@TJ1H z#=bKAf1*#9AHRJ_Ii>kOUd?+zM_3a(>z!;7)KC zxEuT&`~utq?ghUD_ksI?oZIjKco4{$s>{K{;1RF_JPIBI@=edL!7A`Lcmg~Lo&ryU zXTY;S&i0XxqZaHBMuP*uf#4u828;yf~2I|0cKofJc1I0<|ooD5C@r-IYK>0lxF0XPGk3C;p%gLA+l za4t9xoDUWQ={J7}E(8~Wi@_z}N8nPh1pF9W1}+CzfGfdIz*XRCa1FQ?TnDZPH-H<# zPr*{~GjJ2Q87u?0fLpxzX11ud%-Wkec*oZEARk#5Ih8ygNMN* zU_d=G32WDVrzU<)AU z18fE48?|jfZ?G-s1GWQw!S-MW&=2$nGI-kw3;<;v`%Bf)-P6i9;%$buZG0kvR%Fd7^H z4g?2*F<>k>7>ons!6D#KFaaC}CIWe}bU2s{jsQo3qren!G&lxK1=Bzsm=5Z}4A1~( zf@8rfa2#j^vq2M>1LlHe&;pJJ^FS+T1M|TN;6$(hoCLlPP6nrdQ^9HAbg&To0Gt8N z1ZRP>!8u?NI2W7;&IgOZ1>lF^LU0kd7+eB=1TFmRY;Bs&UxDxyXTm}A9+;6ev ib+8(|0p0}Px$jEgyAt@W1imYQ?@Hji68OJe0{;z(l2t_j From 70cbe28e7fff70813ca266e35885501c97891903 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Wed, 23 Mar 2016 16:14:26 +1100 Subject: [PATCH 15/18] Update documentation following merge --- .../date-histogram-aggregation-usage.asciidoc | 2 +- .../unrecoverable-exceptions.asciidoc | 103 +++++++++ .../sticky/skip-dead-nodes.asciidoc | 197 ++++++++++++++++++ .../connection-pooling/sticky/sticky.asciidoc | 37 ++++ .../inference/document-paths.asciidoc | 6 +- .../inference/features-inference.asciidoc | 2 +- .../inference/field-inference.asciidoc | 61 ++++-- .../inference/ids-inference.asciidoc | 20 +- .../inference/index-name-inference.asciidoc | 88 ++++++++ .../inference/indices-paths.asciidoc | 4 +- .../inference/property-inference.asciidoc | 79 ++++++- .../high-level/mapping/auto-map.asciidoc | 160 ++++++++++---- .../low-level/connecting.asciidoc | 105 ++++++---- .../naming-conventions.asciidoc | 18 +- .../time-unit/time-units.asciidoc | 102 ++++++++- .../multi-match/multi-match-usage.asciidoc | 36 ++++ .../search/request/profile-usage.asciidoc | 50 +++++ .../search/request/sort-usage.asciidoc | 6 +- .../Inference/PropertyInference.doc.cs | 29 ++- 19 files changed, 940 insertions(+), 165 deletions(-) create mode 100644 docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc create mode 100644 docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc create mode 100644 docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc create mode 100644 docs/asciidoc/search/request/profile-usage.asciidoc diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index 407b221144c..04d03ec3773 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -15,7 +15,7 @@ NOTE: When specifying a `format` **and** `extended_bounds`, in order for Elastic the serialized ``DateTime`` of `extended_bounds` correctly, the `date_optional_time` format is included as part of the `format` value. -Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. +Be sure to read the elasticsearch documentation on {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[Date Histogram Aggregation]. === Fluent DSL Example diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 7b9df3334ef..9e6725feeb0 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -74,3 +74,106 @@ audit = await audit.TraceElasticsearchException( ); ---- +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.SucceedAlways()) + .ClientCalls(r => r.FailAlways(401).ReturnResponse(ResponseHtml)) + .StaticConnectionPool() + .AllDefaults() +); + +audit = await audit.TraceElasticsearchException( + new ClientCall { + { AuditEvent.PingSuccess, 9200 }, + { AuditEvent.BadResponse, 9200 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + e.Response.ResponseBodyInBytes.Should().BeNull(); + } +); + +e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + +e.Response.ResponseBodyInBytes.Should().BeNull(); +---- + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.SucceedAlways()) + .ClientCalls(r => r.FailAlways(401).ReturnResponse(ResponseHtml)) + .StaticConnectionPool() + .Settings(s=>s.DisableDirectStreaming()) +); + +audit = await audit.TraceElasticsearchException( + new ClientCall { + { AuditEvent.PingSuccess, 9200 }, + { AuditEvent.BadResponse, 9200 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + e.Response.ResponseBodyInBytes.Should().NotBeNull(); + var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); + responseString.Should().Contain("nginx/"); + e.DebugInformation.Should().Contain("nginx/"); + } +); + +e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + +e.Response.ResponseBodyInBytes.Should().NotBeNull(); + +var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); + +responseString.Should().Contain("nginx/"); + +e.DebugInformation.Should().Contain("nginx/"); +---- + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(10) + .Ping(r => r.SucceedAlways()) + .ClientCalls(r => r.FailAlways(401).ReturnResponse(ResponseHtml)) + .StaticConnectionPool() + .Settings(s=>s.DisableDirectStreaming().DefaultIndex("default-index")) + .ClientProxiesTo( + (c, r) => c.Get("1", s=>s.RequestConfiguration(r)), + async (c, r) => await c.GetAsync("1", s=>s.RequestConfiguration(r)) as IResponse + ) +); + +audit = await audit.TraceElasticsearchException( + new ClientCall { + { AuditEvent.PingSuccess, 9200 }, + { AuditEvent.BadResponse, 9200 }, + }, + (e) => + { + e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + e.Response.ResponseBodyInBytes.Should().NotBeNull(); + var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); + responseString.Should().Contain("nginx/"); + e.DebugInformation.Should().Contain("nginx/"); + } +); + +e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + +e.Response.ResponseBodyInBytes.Should().NotBeNull(); + +var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); + +responseString.Should().Contain("nginx/"); + +e.DebugInformation.Should().Contain("nginx/"); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc new file mode 100644 index 00000000000..dfaf1b175f3 --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc @@ -0,0 +1,197 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[skip-dead-nodes]] +== Skip Dead Nodes + +Sticky - Skipping Dead Nodes +When selecting nodes the connection pool will try and skip all the nodes that are marked dead. + +[source,csharp] +---- +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); + +seeds.First().MarkDead(DateTime.Now.AddDays(1)); + +var pool = new StickyConnectionPool(seeds); + +var node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9201); + +node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9201); +---- + +[source,csharp] +---- +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); +var pool = new StickyConnectionPool(seeds); +var node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +node = pool.CreateView().First(); +node.Uri.Port.Should().Be(9200); +---- + +After we marke the first node alive again we expect it to be hit again + +[source,csharp] +---- +seeds.First().MarkAlive(); + +var node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9200); + +node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9200); + +node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9200); +---- + +[source,csharp] +---- +var dateTimeProvider = new TestableDateTimeProvider(); + +var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); + +seeds.First().MarkDead(dateTimeProvider.Now().AddDays(1)); + +var pool = new StickyConnectionPool(seeds, dateTimeProvider: dateTimeProvider); + +var node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9201); + +node = pool.CreateView().First(); + +node.Uri.Port.Should().Be(9201); +---- + +If we forward our clock 2 days the node that was marked dead until tomorrow (or yesterday!) should be resurrected + +[source,csharp] +---- +dateTimeProvider.ChangeTime(d => d.AddDays(2)); + +var n = pool.CreateView().First(); + +n.Uri.Port.Should().Be(9200); + +n = pool.CreateView().First(); + +n.Uri.Port.Should().Be(9200); + +n = pool.CreateView().First(); + +n.Uri.Port.Should().Be(9200); + +n.IsResurrected.Should().BeTrue(); +---- + +A cluster with 2 nodes where the second node fails on ping + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .ClientCalls(p => p.Succeeds(Always)) + .ClientCalls(p => p.OnPort(9200).FailAlways()) + .ClientCalls(p => p.OnPort(9201).FailAlways()) + .StickyConnectionPool() + .Settings(p => p.DisablePing()) +); +---- + +The first call goes to 9200 which succeeds + +The 2nd call does a ping on 9201 because its used for the first time. +It fails so we wrap over to node 9202 + +Finally we assert that the connectionpool has one node that is marked as dead + +[source,csharp] +---- +await audit.TraceCalls( +new ClientCall { + { BadResponse, 9200}, + { BadResponse, 9201}, + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, +new ClientCall { + { HealthyResponse, 9202}, +{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + }, + new ClientCall { + { HealthyResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(2) } + } +); +---- + +A cluster with 2 nodes where the second node fails on ping + +[source,csharp] +---- +var audit = new Auditor(() => Framework.Cluster + .Nodes(4) + .ClientCalls(p => p.Fails(Always)) + .StickyConnectionPool() + .Settings(p => p.DisablePing()) +); +---- + +All the calls fail + +After all our registered nodes are marked dead we want to sample a single dead node +each time to quickly see if the cluster is back up. We do not want to retry all 4 +nodes + +[source,csharp] +---- +await audit.TraceCalls( +new ClientCall { + { BadResponse, 9200}, + { BadResponse, 9201}, + { BadResponse, 9202}, + { BadResponse, 9203}, + { MaxRetriesReached }, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, +new ClientCall { + { AllNodesDead }, + { Resurrection, 9200}, + { BadResponse, 9200}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9201}, + { BadResponse, 9201}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9202}, + { BadResponse, 9202}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + }, + new ClientCall { + { AllNodesDead }, + { Resurrection, 9203}, + { BadResponse, 9203}, + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(4) } + } +); +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc new file mode 100644 index 00000000000..f8d05a08b1a --- /dev/null +++ b/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc @@ -0,0 +1,37 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[sticky]] +== Sticky + +Sticky +Each connection pool returns the first `live` node so that it is sticky between requests + +[source,csharp] +---- +var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); +var staticPool = new StickyConnectionPool(uris); +this.AssertCreateView(staticPool); +---- + +Here we have setup a static connection pool seeded with 10 nodes. +So what order we expect? Imagine the following: + +Thread A calls GetNext and gets returned the first live node +Thread B calls GetNext() and gets returned the same node as it's still the first live. + +[source,csharp] +---- +var startingPositions = Enumerable.Range(0, NumberOfNodes) + .Select(i => pool.CreateView().First()) + .Select(n => n.Uri.Port) + .ToList(); + +var expectedOrder = Enumerable.Repeat(9200, NumberOfNodes); + +startingPositions.Should().ContainInOrder(expectedOrder); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index d586e2ca949..02296b1fcc4 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -9,7 +9,7 @@ Many API's in Elasticsearch describe a path to a document. In NEST, besides generating a constructor that takes and Index, Type and Id seperately, we also generate a constructor taking a `DocumentPath` that allows you to describe the path -to your document more succintly +to your document more succintly === Creating new instances @@ -48,7 +48,7 @@ Expect(1).WhenSerializing(path.Id); === Creating from a document type instance -if you have an instance of your document you can use it as well generate document paths +if you have an instance of your document you can use it as well generate document paths [source,csharp] ---- @@ -113,7 +113,7 @@ request = new IndexRequest(project) { }; ---- when comparing with the full blown constructor and passing document manually, -`DocumentPath`'s benefits become apparent. +`DocumentPath`'s benefits become apparent. [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc index 984d30e38bb..888e4ff039b 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc @@ -12,7 +12,7 @@ Within NEST, route values on the URI are represented as classes that implement a Since enums _cannot_ implement interfaces in C#, a route parameter that would be of type `Feature` is represented using the `Features` class that the `Feature` enum implicitly converts to. -=== Constructor +=== Constructor Using the `Features` constructor directly is possible but rather involved diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index 8894ae008d3..efd18a1cff7 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -8,11 +8,11 @@ == Field Inference Several places in the elasticsearch API expect the path to a field from your original source document as a string. -NEST allows you to use C# expressions to strongly type these field path strings. +NEST allows you to use C# expressions to strongly type these field path strings. These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: -=== Constructor +=== Constructor Using the constructor directly is possible but rather involved @@ -33,7 +33,7 @@ Expect("name") .WhenSerializing(fieldString); ---- -=== Implicit Conversion +=== Implicit Conversion Therefore you can also implicitly convert strings and expressions to ``Field``s @@ -55,9 +55,9 @@ Expect("name") .WhenSerializing(fieldString); ---- -=== ``Nest.Infer`` +=== ``Nest.Infer`` -to ease creating ``Field``s from expressions there is a static `Infer` class you can use +to ease creating ``Field``s from expressions there is a static `Infer` class you can use [source,csharp] ---- @@ -72,7 +72,7 @@ var fieldExpression = Infer.Field(p => p.Name); ---- this can be even shortened even further using a https://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. - `using static Nest.Infer;` + `using static Nest.Infer;` [source,csharp] ---- @@ -86,6 +86,21 @@ Now that is much terser then our first example using the constructor! Expect("name") .WhenSerializing(fieldString) .WhenSerializing(fieldExpression); + +fieldString = "name^2.1"; + +fieldString.Boost.Should().Be(2.1); + +fieldExpression = Field(p => p.Name, 2.1); +---- + +Now this is much much terser then our first example using the constructor! + +[source,csharp] +---- +Expect("name^2.1") + .WhenSerializing(fieldString) + .WhenSerializing(fieldExpression); ---- === Field name casing @@ -109,8 +124,8 @@ However ``string``s are *always* passed along verbatim setup.Expect("NaMe").WhenSerializing("NaMe"); ---- -if you want the same behavior for expressions, simply pass a Func to `DefaultFieldNameInferrer` -to make no changes to the name +if you want the same behavior for expressions, simply pass a Func to `DefaultFieldNameInferrer` +to make no changes to the name [source,csharp] ---- @@ -168,10 +183,10 @@ Expect("metadata.var").WhenSerializing(Field(p => p.Metadata[variable]) Expect("metadata.var.created").WhenSerializing(Field(p => p.Metadata[variable].Created)); ---- -If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow -you to analyze a string in a number of different ways, these __"virtual"__ sub fields -do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that -should be mapped and <> +If you are using Elasticearch's {ref_current}/_multi_fields.html[multi_fields], which you really should as they allow +you to analyze a string in a number of different ways, these __"virtual"__ sub fields +do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that +should be mapped and <> [source,csharp] ---- @@ -207,7 +222,7 @@ Expect("metadata.var.created.unanalyzed").WhenSerializing(Field(p => p. ---- Suffixes can also be appended to expressions using `.ApplySuffix()`. This is useful in cases where you want to apply the same suffix -to a list of fields. +to a list of fields. Here we have a list of expressions @@ -226,7 +241,7 @@ and we want to append the suffix "raw" to each [source,csharp] ---- -var fieldExpressions = +var fieldExpressions = expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); Expect("name.raw").WhenSerializing(fieldExpressions[0]); @@ -238,7 +253,7 @@ Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]); Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); ---- -=== Annotations +=== Annotations When using NEST's property attributes you can specify a new name for the properties @@ -257,7 +272,7 @@ Expect("naam").WhenSerializing(Field(p => p.Name)); ---- Starting with NEST 2.x we also ask the serializer if it can resolve the property to a name. -Here we ask the default `JsonNetSerializer` to resolve a property name and it takes +Here we ask the default `JsonNetSerializer` to resolve a property name and it takes the `JsonPropertyAttribute` into account [source,csharp] @@ -274,7 +289,7 @@ public class SerializerSpecific Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ---- -If both a NEST property attribute and a serializer specific attribute are present on a property, +If both a NEST property attribute and a serializer specific attribute are present on a property, NEST takes precedence [source,csharp] @@ -401,8 +416,8 @@ class Precedence [JsonProperty("dontaskme")] public string AskSerializer { get; set; } - // We are going to register a DefaultFieldNameInferrer on ConnectionSettings - // that will uppercase all properties. + // We are going to register a DefaultFieldNameInferrer on ConnectionSettings + // that will uppercase all properties. public string DefaultFieldNameInferrer { get; set; } } ---- @@ -417,8 +432,8 @@ class CustomSerializer : JsonNetSerializer public override IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) { - return memberInfo.Name == nameof(Precedence.AskSerializer) - ? new PropertyMapping { Name = "ask" } + return memberInfo.Name == nameof(Precedence.AskSerializer) + ? new PropertyMapping { Name = "ask" } : base.CreatePropertyMapping(memberInfo); } } @@ -430,7 +445,7 @@ and all properties that are not mapped verbatim should be uppercased [source,csharp] ---- var usingSettings = WithConnectionSettings(s => s - + .InferMappingFor(m => m .Rename(p => p.RenamedOnConnectionSettings, "renamed") ) @@ -452,7 +467,7 @@ The same naming rules also apply when indexing a document [source,csharp] ---- -usingSettings.Expect(new [] +usingSettings.Expect(new [] { "ask", "DEFAULTFIELDNAMEINFERRER", diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index e3b70d1f834..ed345c9c60e 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -9,7 +9,7 @@ === Implicit Conversions -Several places in the Elasticsearch API expect an `Id` object to be passed. +Several places in the Elasticsearch API expect an `Id` object to be passed. This is a special box type that you can implicitly convert to from the following types * `Int32` @@ -20,7 +20,7 @@ This is a special box type that you can implicitly convert to from the following * `Guid` -Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` +Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` [source,csharp] ---- @@ -34,10 +34,10 @@ Expect("hello-world").WhenSerializing(idFromString); Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenSerializing(idFromGuid); ---- -=== Inferring from a Type +=== Inferring from a Type Sometimes a method takes an object and we need an Id from that object to build up a path. -There is no implicit conversion from any object to Id but we can call `Id.From`. +There is no implicit conversion from any object to Id but we can call `Id.From`. Imagine your codebase has the following type that we want to index into Elasticsearch @@ -67,7 +67,7 @@ Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); ---- Using the connection settings you can specify a different property that NEST should use to infer the document Id. -Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property +Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property [source,csharp] ---- @@ -92,10 +92,10 @@ WithConnectionSettings(x => x ).Expect("y").WhenInferringIdOn(dto); ---- -=== Using the `ElasticsearchType` attribute +=== Using the `ElasticsearchType` attribute -Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` -to the name of the property that should be used for the document id +Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` +to the name of the property that should be used for the document id [source,csharp] ---- @@ -117,9 +117,9 @@ var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E") Expect("x").WhenInferringIdOn(dto); ---- -=== Using Mapping inference on `ConnectionSettings` +=== Using Mapping inference on `ConnectionSettings` -This attribute *is* cached statically/globally, however an inference rule on the `ConnectionSettings` for the type will +This attribute *is* cached statically/globally, however an inference rule on the `ConnectionSettings` for the type will still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance that will infer the document id from the property `OtherName`: diff --git a/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc new file mode 100644 index 00000000000..e956c78aec0 --- /dev/null +++ b/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc @@ -0,0 +1,88 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images/ + +[[index-name-inference]] +== Index Name Inference + +[source,csharp] +---- +var settings = new ConnectionSettings() + .MapDefaultTypeIndices(m => m + .Add(typeof(Project), "projects") + ); + +var resolver = new IndexNameResolver(settings); + +var index = resolver.Resolve(); + +index.Should().Be("projects"); +---- + +[source,csharp] +---- +var settings = new ConnectionSettings() + .DefaultIndex("defaultindex") + .MapDefaultTypeIndices(m => m + .Add(typeof(Project), "projects") + ); + +var resolver = new IndexNameResolver(settings); + +var index = resolver.Resolve(); + +index.Should().Be("projects"); +---- + +[source,csharp] +---- +var settings = new ConnectionSettings() + .DefaultIndex("Default") + .MapDefaultTypeIndices(m => m + .Add(typeof(Project), "myProjects") + ); + +var resolver = new IndexNameResolver(settings); + +var e = Assert.Throws(() => resolver.Resolve()); + +e.Message.Should().Be($"Index names cannot contain uppercase characters: myProjects."); + +e = Assert.Throws(() => resolver.Resolve()); + +e.Message.Should().Be($"Index names cannot contain uppercase characters: Default."); + +e = Assert.Throws(() => resolver.Resolve("Foo")); + +e.Message.Should().Be($"Index names cannot contain uppercase characters: Foo."); +---- + +[source,csharp] +---- +var settings = new ConnectionSettings(); + +var resolver = new IndexNameResolver(settings); + +var e = Assert.Throws(() => resolver.Resolve()); + +e.Message.Should().Contain("Index name is null"); +---- + +[source,csharp] +---- +var client = TestClient.GetInMemoryClient(s => new ConnectionSettings()); + +var e = Assert.Throws(() => client.Search()); +---- + +[source,csharp] +---- +var settings = new ConnectionSettings() + .DefaultIndex("defaultindex"); +var resolver = new IndexNameResolver(settings); +var index = resolver.Resolve(); +index.Should().Be("defaultindex"); +---- + diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index 89a5731bbb8..bdb5a7f96ce 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -10,7 +10,7 @@ Some API's in elasticsearch take one or many index name or a special "_all" marker to send the request to all the indices In nest this is encoded using `Indices` -=== Implicit Conversion +=== Implicit Conversion Several types implicitly convert to `Indices` @@ -40,7 +40,7 @@ allWithOthersFromString.Match( === Using `Nest.Indices` -To ease creating ``Indice``s from expressions, there is a static `Nest.Indices` class you can use +To ease creating ``Indice``s from expressions, there is a static `Nest.Indices` class you can use [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index c1e746c38a9..cbbe14e3475 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -5,11 +5,17 @@ :imagesdir: ../../../images/ [[property-inference]] -== Property Name Inference +== Property Name Inference -=== Using `.Suffix()` extension method on `object` +=== Appending suffixes to a Lambda expression body -Property names resolve to the last token. An example using the `.Suffix()` extension +Suffixes can be appended to the body of a lambda expression, useful in cases where +you have a POCO property mapped as a {ref_current}/_multi_fields.html[multi_field] +and want to use strongly typed access based on the property, yet append a suffix to the +generated field name in order to access a particular `multi_field`. + +The `.Suffix()` extension method can be used for this purpose and when serializing expressions suffixed +in this way, the serialized field name resolves to the last token [source,csharp] ---- @@ -17,24 +23,79 @@ Expression> expression = p => p.Name.Suffix("raw"); Expect("raw").WhenSerializing(expression); ---- -=== `.ApplySuffix()` extension method on Expression Delegates +=== Appending suffixes to a Lambda expression -And an example using the `.ApplySuffix()` extension on lambda expressions +Alternatively, suffixes can be applied to a lambda expression directly using +the `.ApplySuffix()` extension method. Again, the serialized field name +resolves to the last token [source,csharp] ---- Expression> expression = p => p.Name; -expression.AppendSuffix("raw"); +expression = expression.AppendSuffix("raw"); Expect("raw").WhenSerializing(expression); ---- -Property names cannot contain a ``.``. in order to prevent the potential for collision with a field that -may have {ref_current}/_multi_fields.html`multi_fields`] +=== Naming conventions + +Currently, the name of a field cannot contain a `.` in Elasticsearch due to the potential for ambiguity with +a field that is mapped as a {ref_current}/_multi_fields.html[multi_field]. + +In these cases, NEST allows the call to go to Elasticsearch, deferring the naming conventions to the server side and, +in the case of a `.` in a field name, a `400 Bad Response` is returned with a server error indicating the reason + +[source,csharp] +---- +var createIndexResponse = _client.CreateIndex("random-" + Guid.NewGuid().ToString().ToLowerInvariant(), c => c + .Mappings(m => m + .Map("type-with-dot", mm => mm + .Properties(p => p + .String(s => s + .Name("name-with.dot") + ) + ) + ) + ) +); +---- + +The response is not valid + +[source,csharp] +---- +createIndexResponse.IsValid.Should().BeFalse(); +---- + +`DebugInformation` provides an audit trail of information to help diagnose the issue + +[source,csharp] +---- +createIndexResponse.DebugInformation.Should().NotBeNullOrEmpty(); +---- + +`ServerError` contains information about the response from Elasticsearch + +[source,csharp] +---- +createIndexResponse.ServerError.Should().NotBeNull(); + +createIndexResponse.ServerError.Status.Should().Be(400); + +createIndexResponse.ServerError.Error.Should().NotBeNull(); + +createIndexResponse.ServerError.Error.RootCause.Should().NotBeNullOrEmpty(); + +var rootCause = createIndexResponse.ServerError.Error.RootCause[0]; +---- + +We can see that the underlying reason is a `.` in the field name "name-with.dot" [source,csharp] ---- -Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); +rootCause.Reason.Should().Be("Field name [name-with.dot] cannot contain '.'"); + +rootCause.Type.Should().Be("mapper_parsing_exception"); ---- diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index 952e059c6b0..b25e46314b7 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -13,9 +13,9 @@ Elasticsearch datatypes of the POCO properties you are mapping. Alternatively, you're using attributes to map your properties, then calling AutoMap() is required in order for your attributes to be applied. We'll look at examples of both. -For these examples, we'll define two POCOS, `Company`, which has a name -and a collection of Employees, and `Employee` which has various properties of -different types, and itself has a collection of `Employee` types. +For these examples, we'll define two POCOs, `Company`, which has a name +and a collection of Employees, and `Employee` which has various properties of +different types, and itself has a collection of `Employee` types. [source,csharp] ---- @@ -113,12 +113,12 @@ var expected = new } }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +Expect(expected).WhenSerializing((ICreateIndexRequest)descriptor); ---- === Simple Automapping -This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, +This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work [source,csharp] @@ -130,16 +130,16 @@ var descriptor = new CreateIndexDescriptor("myindex") ); ---- -Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. -In this example, +Observe that NEST has inferred the Elasticsearch types based on the CLR type of our POCO properties. +In this example, -* Birthday was mapped as a date, +* Birthday was mapped as a date, * Hours was mapped as a long (ticks) -* IsManager was mapped as a boolean, +* IsManager was mapped as a boolean, -* Salary as an integer +* Salary as an integer * Employees as an object and the remaining string properties as strings. @@ -173,7 +173,7 @@ var expected = new }, hours = new { - type = "long" + type = "long" }, isManager = new { @@ -234,7 +234,7 @@ var expected = new } }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +Expect(expected).WhenSerializing((ICreateIndexRequest)descriptor); ---- [[auto-mapping-with-overrides]] @@ -242,8 +242,8 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); == Auto mapping with overrides In most cases, you'll want to map more than just the vanilla datatypes and also provide -various options for your properties (analyzer to use, whether to enable doc_values, etc...). -In that case, it's possible to use `.AutoMap()` in conjuction with explicitly mapped properties. +various options for your properties (analyzer to use, whether to enable doc_values, etc...). +In that case, it's possible to use `.AutoMap()` in conjuction with explicitly mapped properties. Here we are using `.AutoMap()` to automatically map our company type, but then we're overriding our employee property and making it a `nested` type, since by default, `.AutoMap()` will infer objects as `object`. @@ -257,9 +257,6 @@ var descriptor = new CreateIndexDescriptor("myindex") .Properties(ps => ps .Nested(n => n .Name(c => c.Employees) - .Properties(eps => eps - // snip - ) ) ) ) @@ -279,15 +276,34 @@ var expected = new }, employees = new { - type = "nested", - properties = new {} + type = "nested" } } } } }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +Expect(expected).WhenSerializing((ICreateIndexRequest)descriptor); +---- + +`.AutoMap()` is __idempotent__; calling it before or after manually +mapped properties should still yield the same results. + +[source,csharp] +---- +descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m + .Properties(ps => ps + .Nested(n => n + .Name(c => c.Employees) + ) + ) + .AutoMap() + ) + ); + +Expect(expected).WhenSerializing((ICreateIndexRequest)descriptor); ---- [[attribute-mapping]] @@ -306,7 +322,7 @@ public class CompanyWithAttributes [String(Analyzer = "keyword", NullValue = "null", Similarity = SimilarityOption.BM25)] public string Name { get; set; } - [String] + [String(Name = "office_hours")] public TimeSpan? HeadOfficeHours { get; set; } [Object(Path = "employees", Store = false)] @@ -316,10 +332,10 @@ public class CompanyWithAttributes [ElasticsearchType(Name = "employee")] public class EmployeeWithAttributes { - [String] + [String(Name = "first_name")] public string FirstName { get; set; } - [String] + [String(Name = "last_name")] public string LastName { get; set; } [Number(DocValues = false, IgnoreMalformed = true, Coerce = true)] @@ -400,7 +416,7 @@ var expected = new similarity = "BM25", type = "string" }, - headOfficeHours = new + office_hours = new { type = "string" } @@ -453,7 +469,7 @@ var expected = new }, type = "nested" }, - firstName = new + first_name = new { type = "string" }, @@ -463,7 +479,7 @@ var expected = new store = true, type = "boolean" }, - lastName = new + last_name = new { type = "string" }, @@ -503,7 +519,7 @@ var descriptor = new CreateIndexDescriptor("myindex") .TtlField(ttl => ttl .Enable() .Default("10m") - ) + ) .Properties(ps => ps .String(s => s .Name(e => e.FirstName) @@ -550,7 +566,7 @@ var expected = new similarity = "BM25", type = "string" }, - headOfficeHours = new + office_hours = new { type = "string" } @@ -607,7 +623,7 @@ var expected = new }, type = "nested" }, - firstName = new + first_name = new { fields = new { @@ -630,7 +646,7 @@ var expected = new store = true, type = "boolean" }, - lastName = new + last_name = new { type = "string" }, @@ -644,14 +660,14 @@ var expected = new } }; -Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +Expect(expected).WhenSerializing((ICreateIndexRequest)descriptor); ---- [[ignoring-properties]] [float] == Ignoring Properties -Properties on a POCO can be ignored in a few ways: +Properties on a POCO can be ignored in a few ways: * Using the `Ignore` property on a derived `ElasticsearchPropertyAttribute` type applied to the property that should be ignored on the POCO @@ -659,7 +675,7 @@ Properties on a POCO can be ignored in a few ways: * Using an ignore attribute applied to the POCO property that is understood by the `IElasticsearchSerializer` used, and inspected inside of the `CreatePropertyMapping()` on the serializer. In the case of the default `JsonNetSerializer`, this is the Json.NET `JsonIgnoreAttribute` -This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the +This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` [source,csharp] @@ -713,7 +729,7 @@ var settings = WithConnectionSettings(s => s ) ); -settings.Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); +settings.Expect(expected).WhenSerializing((ICreateIndexRequest)descriptor); ---- [[mapping-recursion]] @@ -831,13 +847,69 @@ var expectedWithMaxRecursion = new Expect(expectedWithMaxRecursion).WhenSerializing((ICreateIndexRequest) withMaxRecursionDescriptor); ---- +[source,csharp] +---- +var descriptor = new PutMappingDescriptor().AutoMap(); + +var expected = new +{ + properties = new + { + child = new + { + properties = new { }, + type = "object" + } + } +}; + +Expect(expected).WhenSerializing((IPutMappingRequest)descriptor); + +var withMaxRecursionDescriptor = new PutMappingDescriptor().AutoMap(3); + +var expectedWithMaxRecursion = new +{ + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new + { + child = new + { + type = "object", + properties = new { } + } + } + } + } + } + } + } + } +}; + +Expect(expectedWithMaxRecursion).WhenSerializing((IPutMappingRequest)withMaxRecursionDescriptor); +---- + [[applying-conventions-through-the-visitor-pattern]] [float] == Applying conventions through the Visitor pattern It is also possible to apply a transformation on all or specific properties. -AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, +AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, does nothing and acts as a blank canvas for you to implement your own visiting methods. For instance, lets create a custom visitor that disables doc values for numeric and boolean types @@ -846,18 +918,18 @@ For instance, lets create a custom visitor that disables doc values for numeric [source,csharp] ---- public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor -{ +{ public override void Visit( - INumberProperty type, - PropertyInfo propertyInfo, + INumberProperty type, + PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) <1> { type.DocValues = false; } public override void Visit( - IBooleanProperty type, - PropertyInfo propertyInfo, + IBooleanProperty type, + PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) <2> { type.DocValues = false; @@ -878,7 +950,7 @@ var descriptor = new CreateIndexDescriptor("myindex") ); ---- -and anytime the client maps a property of the POCO (``Employee`` in this example) as a number (``INumberProperty``) or boolean (``IBooleanProperty``), +and anytime the client maps a property of the POCO (``Employee`` in this example) as a number (``INumberProperty``) or boolean (``IBooleanProperty``), it will apply the transformation defined in each `Visit()` call respectively, which in this example disables {ref_current}/doc-values.html[doc_values]. @@ -925,10 +997,10 @@ var expected = new }; ---- -=== Visiting on ``PropertyInfo`` +=== Visiting on ``PropertyInfo`` You can even take the visitor approach a step further, and instead of visiting on `IProperty` types, visit -directly on your POCO properties (``PropertyInfo``). As an example, let's create a visitor that maps all CLR types +directly on your POCO properties (``PropertyInfo``). As an example, let's create a visitor that maps all CLR types to an Elasticsearch string (``IStringProperty``). [source,csharp] @@ -936,7 +1008,7 @@ to an Elasticsearch string (``IStringProperty``). public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { public override IProperty Visit( - PropertyInfo propertyInfo, + PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new StringProperty(); } ---- diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 3615da648ff..29baa210742 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -19,7 +19,7 @@ If you simply new an `ElasticLowLevelClient`, it will be a non-failover connecti var client = new ElasticLowLevelClient(); ---- -If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then +If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then you will need to pass in some instance of `IConnectionConfigurationValues`. The easiest way to do this is: @@ -49,7 +49,7 @@ var client = new ElasticLowLevelClient(config); ---- Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. -Be sure to read more about <>. +Be sure to read more about <>. === Configuration Options @@ -177,6 +177,24 @@ client.RootNodeInfoAsync(); counter.Should().Be(2); ---- +[source,csharp] +---- +var counter = 0; + +var client = TestClient.GetFixedReturnClient(new { }, 500, s => s + .ThrowExceptions() + .OnRequestCompleted(r => counter++) +); + +Assert.Throws(() => client.RootNodeInfo()); + +counter.Should().Be(1); + +Assert.ThrowsAsync(() => client.RootNodeInfoAsync()); + +counter.Should().Be(2); +---- + [[complex-logging]] Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` @@ -189,52 +207,57 @@ var list = new List(); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) <1> - .DisableDirectStreaming() - .OnRequestCompleted(response => - { - // log out the request - if (response.RequestBodyInBytes != null) - { - list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); - } - else - { - list.Add($"{response.HttpMethod} {response.Uri}"); - } - - // log out the response - if (response.ResponseBodyInBytes != null) - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); - } - else - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); - } - }); + .DefaultIndex("default-index") + .DisableDirectStreaming() + .OnRequestCompleted(response => + { + // log out the request + if (response.RequestBodyInBytes != null) + { + list.Add( + $"{response.HttpMethod} {response.Uri} \n" + + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); + } + else + { + list.Add($"{response.HttpMethod} {response.Uri}"); + } + + // log out the response + if (response.ResponseBodyInBytes != null) + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + + $"{new string('-', 30)}\n"); + } + else + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{new string('-', 30)}\n"); + } + }); var client = new ElasticClient(settings); var syncResponse = client.Search(s => s - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) - ); + .AllTypes() + .AllIndices() + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) +); list.Count.Should().Be(2); var asyncResponse = await client.SearchAsync(s => s - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) - ); + .AllTypes() + .AllIndices() + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) +); list.Count.Should().Be(4); @@ -270,7 +293,7 @@ therefore **we recommend doing some minimal introspection on the passed in certi Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful -Create a subclass of the `JsonNetSerializer` +Create a subclass of the `JsonNetSerializer` Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 6abf43be885..f313bce5535 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -85,21 +85,6 @@ the `Exists` requests. ---- var exceptions = new[] <1> { - typeof(CatAliasesRequest), - typeof(CatAllocationRequest), - typeof(CatCountRequest), - typeof(CatFielddataRequest), - typeof(CatHealthRequest), - typeof(CatHelpRequest), - typeof(CatIndicesRequest), - typeof(CatMasterRequest), - typeof(CatNodesRequest), - typeof(CatPendingTasksRequest), - typeof(CatPluginsRequest), - typeof(CatRecoveryRequest), - typeof(CatSegmentsRequest), - typeof(CatShardsRequest), - typeof(CatThreadPoolRequest), typeof(DocumentExistsRequest), typeof(DocumentExistsRequest<>), typeof(AliasExistsRequest), @@ -115,7 +100,9 @@ var exceptions = new[] <1> typeof(SourceRequest<>), typeof(ValidateQueryRequest<>), typeof(GetAliasRequest), +#pragma warning disable 612 typeof(CatNodeattrsRequest), +#pragma warning restore 612 typeof(IndicesShardStoresRequest), typeof(RenderSearchTemplateRequest) }; @@ -128,6 +115,7 @@ var requests = new HashSet(types !t.IsAbstract() && typeof(IRequest).IsAssignableFrom(t) && !typeof(IDescriptor).IsAssignableFrom(t) + && !t.Name.StartsWith("Cat") && !exceptions.Contains(t)) .Select(t => t.Name.Split('`')[0].Replace("Request", "")) ); diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index b03fd54f3b0..b2b0662ffc4 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -86,15 +86,27 @@ Time twoWeeks = TimeSpan.FromDays(14); Time twoDays = 1000*60*60*24*2; ---- -Again, the `Milliseconds` property is calculated on `Time`, -allowing you to do comparisons +Milliseconds are calculated even when values are not passed as long [source,csharp] ---- -oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); - twoWeeks.Milliseconds.Should().BeGreaterThan(1); +---- + +Except when dealing with years or months, whose millsecond value cannot +be calculated *accurately*, since they are not fixed durations. For instance, +30 vs 31 vs 28 days in a month, or 366 vs 365 days in a year. +In this instance, Milliseconds will be -1. + +[source,csharp] +---- +oneAndHalfYear.Milliseconds.Should().Be(-1); +---- + +This allows you to do comparisons on the expressions +[source,csharp] +---- oneAndHalfYear.Should().BeGreaterThan(twoWeeks); (oneAndHalfYear > twoWeeks).Should().BeTrue(); @@ -123,6 +135,10 @@ twoDays.Should().Be(new Time("2d")); (twoDays != new Time("2.1d")).Should().BeTrue(); (new Time("2.1d") == new Time(TimeSpan.FromDays(2.1))).Should().BeTrue(); + +(new Time("1") == new Time(1)).Should().BeTrue(); + +(new Time("-1") == new Time(-1)).Should().BeTrue(); ---- === Time units @@ -153,3 +169,81 @@ Expect("2d").WhenSerializing>((Time)"2d"); Expect("1.16w").WhenSerializing>((Time)TimeSpan.FromDays(8.1)); ---- +[source,csharp] +---- +double millisecondsInAMonth = 2592000000; + +Expect("4.29w").WhenSerializing(new Time(millisecondsInAMonth)); + +Expect("8.57w").WhenSerializing(new Time(millisecondsInAMonth * 2)); + +Expect("51.43w").WhenSerializing(new Time(millisecondsInAMonth * 12)); + +Expect("102.86w").WhenSerializing(new Time(millisecondsInAMonth * 24)); +---- + +[source,csharp] +---- +Expect("-1").WhenSerializing(new Time(-1)); + +Expect("-1").WhenSerializing(new Time("-1")); + +Assert( + 1, Nest.TimeUnit.Year, -1, "1y", + new Time(1, Nest.TimeUnit.Year), + new Time("1y") +); + +Assert( + 1, Nest.TimeUnit.Month, -1, "1M", + new Time(1, Nest.TimeUnit.Month), + new Time("1M") +); + +Assert( + 1, Nest.TimeUnit.Week, TimeSpan.FromDays(7).TotalMilliseconds, "1w", + new Time(1, Nest.TimeUnit.Week), + new Time("1w"), + new Time(TimeSpan.FromDays(7).TotalMilliseconds) +); + +Assert( + 1, Nest.TimeUnit.Day, TimeSpan.FromDays(1).TotalMilliseconds, "1d", + new Time(1, Nest.TimeUnit.Day), + new Time("1d"), + new Time(TimeSpan.FromDays(1).TotalMilliseconds) +); + +Assert( + 1, Nest.TimeUnit.Hour, TimeSpan.FromHours(1).TotalMilliseconds, "1h", + new Time(1, Nest.TimeUnit.Hour), + new Time("1h"), + new Time(TimeSpan.FromHours(1).TotalMilliseconds) +); + +Assert( + 1, Nest.TimeUnit.Minute, TimeSpan.FromMinutes(1).TotalMilliseconds, "1m", + new Time(1, Nest.TimeUnit.Minute), + new Time("1m"), + new Time(TimeSpan.FromMinutes(1).TotalMilliseconds) +); + +Assert( + 1, Nest.TimeUnit.Second, TimeSpan.FromSeconds(1).TotalMilliseconds, "1s", + new Time(1, Nest.TimeUnit.Second), + new Time("1s"), + new Time(TimeSpan.FromSeconds(1).TotalMilliseconds) +); +---- + +[source,csharp] +---- +time.Factor.Should().Be(expectedFactor); + +time.Interval.Should().Be(expectedInterval); + +time.Milliseconds.Should().Be(expectedMilliseconds); + +Expect(expectedSerialized).WhenSerializing(time); +---- + diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index 12e44e1907e..fdace521fe7 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -85,3 +85,39 @@ new MultiMatchQuery } ---- +=== Fluent DSL Example + +[source,csharp] +---- +q +.MultiMatch(c => c + .Fields(f => f.Field(p=>p.Description, 2.2).Field("myOtherField^0.3")) + .Query("hello world") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new MultiMatchQuery +{ + Fields = Field(p=>p.Description, 2.2).And("myOtherField^0.3"), + Query = "hello world", +} +---- + +[source,javascript] +.Example json output +---- +{ + "multi_match": { + "query": "hello world", + "fields": [ + "description^2.2", + "myOtherField^0.3" + ] + } +} +---- + diff --git a/docs/asciidoc/search/request/profile-usage.asciidoc b/docs/asciidoc/search/request/profile-usage.asciidoc new file mode 100644 index 00000000000..a5a4340afe5 --- /dev/null +++ b/docs/asciidoc/search/request/profile-usage.asciidoc @@ -0,0 +1,50 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images/ + +[[profile-usage]] +== Profile Usage + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Profile() +.Query(q => q + .Term(p => p.Name, "elasticsearch") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Profile = true, + Query = new TermQuery + { + Field = "name", + Value = "elasticsearch" + } +} +---- + +[source,javascript] +.Example json output +---- +{ + "profile": true, + "query": { + "term": { + "name": { + "value": "elasticsearch" + } + } + } +} +---- + diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 0d7af40826a..11d5fee7ae2 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -31,7 +31,7 @@ s => s ) .GeoDistance(g => g .Field(p => p.Location) - .DistanceType(GeoDistanceType.SloppyArc) + .DistanceType(GeoDistanceType.Arc) .Order(SortOrder.Ascending) .Unit(DistanceUnit.Centimeters) .Mode(SortMode.Min) @@ -144,7 +144,9 @@ new SearchRequest } ], "order": "asc", - "mode": "min" + "mode": "min", + "distance_type": "arc", + "unit": "cm" } }, { diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs index c70a8f2ee5f..caa0ec550b8 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/PropertyInference.doc.cs @@ -23,8 +23,14 @@ public PropertyNames(IndexingCluster cluster) : base(cluster) _client = cluster.Node.Client(); } - /**=== Using `.Suffix()` extension method on `object` - * Property names resolve to the last token. An example using the `.Suffix()` extension + /**=== Appending suffixes to a Lambda expression body + * Suffixes can be appended to the body of a lambda expression, useful in cases where + * you have a POCO property mapped as a {ref_current}/_multi_fields.html[multi_field] + * and want to use strongly typed access based on the property, yet append a suffix to the + * generated field name in order to access a particular `multi_field`. + * + * The `.Suffix()` extension method can be used for this purpose and when serializing expressions suffixed + * in this way, the serialized field name resolves to the last token */ [U] public void PropertyNamesAreResolvedToLastToken() { @@ -32,8 +38,10 @@ [U] public void PropertyNamesAreResolvedToLastToken() Expect("raw").WhenSerializing(expression); } - /**=== `.ApplySuffix()` extension method on Expression Delegates - * And an example using the `.ApplySuffix()` extension on lambda expressions + /**=== Appending suffixes to a Lambda expression + * Alternatively, suffixes can be applied to a lambda expression directly using + * the `.ApplySuffix()` extension method. Again, the serialized field name + * resolves to the last token */ [U] public void PropertyNamesAreResolvedToLastTokenUsingApplySuffix() @@ -43,12 +51,12 @@ public void PropertyNamesAreResolvedToLastTokenUsingApplySuffix() Expect("raw").WhenSerializing(expression); } - /**=== Property naming conventions - *Property names cannot contain a `.` (dot), because of the potential for ambiguity with - *a field that is mapped as a {ref_current}/_multi_fields.html[`multi_field`]. + /**=== Naming conventions + * Currently, the name of a field cannot contain a `.` in Elasticsearch due to the potential for ambiguity with + * a field that is mapped as a {ref_current}/_multi_fields.html[multi_field]. * - *NEST allows the call to go to Elasticsearch, deferring the naming conventions to the server side and, - * in the case of dots in field names, returns a `400 Bad Response` with a server error indicating the reason. + * In these cases, NEST allows the call to go to Elasticsearch, deferring the naming conventions to the server side and, + * in the case of a `.` in a field name, a `400 Bad Response` is returned with a server error indicating the reason */ [I] public void PropertyNamesContainingDotsCausesElasticsearchServerError() { @@ -70,7 +78,7 @@ [I] public void PropertyNamesContainingDotsCausesElasticsearchServerError() /** `DebugInformation` provides an audit trail of information to help diagnose the issue */ createIndexResponse.DebugInformation.Should().NotBeNullOrEmpty(); - /** `ServerError` contains information from the response from Elasticsearch */ + /** `ServerError` contains information about the response from Elasticsearch */ createIndexResponse.ServerError.Should().NotBeNull(); createIndexResponse.ServerError.Status.Should().Be(400); createIndexResponse.ServerError.Error.Should().NotBeNull(); @@ -78,6 +86,7 @@ [I] public void PropertyNamesContainingDotsCausesElasticsearchServerError() var rootCause = createIndexResponse.ServerError.Error.RootCause[0]; + /** We can see that the underlying reason is a `.` in the field name "name-with.dot" */ rootCause.Reason.Should().Be("Field name [name-with.dot] cannot contain '.'"); rootCause.Type.Should().Be("mapper_parsing_exception"); } From 9df1554c7977de7f88c6d7934af150fd017de8f2 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 24 Mar 2016 13:56:37 +1100 Subject: [PATCH 16/18] update documentation following merge --- .../children-aggregation-mapping.asciidoc | 2 + .../children-aggregation-usage.asciidoc | 2 + .../date-histogram-aggregation-usage.asciidoc | 2 + .../date-range-aggregation-usage.asciidoc | 2 + .../filter/filter-aggregation-usage.asciidoc | 70 +- .../filters-aggregation-usage.asciidoc | 2 + .../geo-distance-aggregation-usage.asciidoc | 2 + .../geo-hash-grid-aggregation-usage.asciidoc | 2 + .../global/global-aggregation-usage.asciidoc | 2 + .../histogram-aggregation-usage.asciidoc | 2 + .../ip-range-aggregation-usage.asciidoc | 2 + .../missing-aggregation-usage.asciidoc | 2 + .../nested/nested-aggregation-usage.asciidoc | 2 + .../range/range-aggregation-usage.asciidoc | 2 + .../reverse-nested-aggregation-usage.asciidoc | 2 + .../sampler-aggregation-usage.asciidoc | 2 + ...gnificant-terms-aggregation-usage.asciidoc | 2 + .../terms/terms-aggregation-usage.asciidoc | 2 + .../average-aggregation-usage.asciidoc | 2 + .../cardinality-aggregation-usage.asciidoc | 2 + .../extended-stats-aggregation-usage.asciidoc | 2 + .../geo-bounds-aggregation-usage.asciidoc | 2 + .../metric/max/max-aggregation-usage.asciidoc | 2 + .../metric/min/min-aggregation-usage.asciidoc | 2 + ...ercentile-ranks-aggregation-usage.asciidoc | 2 + .../percentiles-aggregation-usage.asciidoc | 2 + ...scripted-metric-aggregation-usage.asciidoc | 2 + .../stats/stats-aggregation-usage.asciidoc | 2 + .../metric/sum/sum-aggregation-usage.asciidoc | 2 + .../top-hits-aggregation-usage.asciidoc | 2 + .../value-count-aggregation-usage.asciidoc | 2 + .../average-bucket-aggregation-usage.asciidoc | 2 + .../bucket-script-aggregation-usage.asciidoc | 2 + ...bucket-selector-aggregation-usage.asciidoc | 2 + .../cumulative-sum-aggregation-usage.asciidoc | 2 + .../derivative-aggregation-usage.asciidoc | 2 + .../max-bucket-aggregation-usage.asciidoc | 2 + .../min-bucket-aggregation-usage.asciidoc | 2 + ...ng-average-ewma-aggregation-usage.asciidoc | 2 + ...age-holt-linear-aggregation-usage.asciidoc | 2 + ...ge-holt-winters-aggregation-usage.asciidoc | 2 + ...-average-linear-aggregation-usage.asciidoc | 2 + ...-average-simple-aggregation-usage.asciidoc | 2 + ...al-differencing-aggregation-usage.asciidoc | 2 + .../sum-bucket-aggregation-usage.asciidoc | 2 + .../writing-aggregations.asciidoc | 2 + .../analyzers/analyzer-usage.asciidoc | 2 + .../char-filters/char-filter-usage.asciidoc | 2 + .../token-filters/token-filter-usage.asciidoc | 2 + .../tokenizers/tokenizer-usage.asciidoc | 2 + .../connection-pooling.asciidoc | 2 + .../date-time-providers.asciidoc | 2 + .../keeping-track-of-nodes.asciidoc | 2 + .../request-pipelines.asciidoc | 2 + .../building-blocks/transports.asciidoc | 11 +- .../exceptions/unexpected-exceptions.asciidoc | 2 + .../unrecoverable-exceptions.asciidoc | 11 + .../failover/falling-over.asciidoc | 2 + .../max-retries/respects-max-retry.asciidoc | 2 + .../pinging/first-usage.asciidoc | 36 +- .../pinging/revival.asciidoc | 2 + .../disable-sniff-ping-per-request.asciidoc | 2 + .../request-timeouts-overrides.asciidoc | 2 + .../respects-allowed-status-code.asciidoc | 2 + .../respects-force-node.asciidoc | 2 + .../respects-max-retry-overrides.asciidoc | 2 + .../round-robin/round-robin.asciidoc | 2 + .../round-robin/skip-dead-nodes.asciidoc | 2 + .../round-robin/volatile-updates.asciidoc | 2 + .../sniffing/on-connection-failure.asciidoc | 2 + .../sniffing/on-stale-cluster-state.asciidoc | 2 + .../sniffing/on-startup.asciidoc | 2 + .../sniffing/role-detection.asciidoc | 2 + .../sticky/skip-dead-nodes.asciidoc | 2 + .../connection-pooling/sticky/sticky.asciidoc | 2 + .../covariant-search-results.asciidoc | 2 + .../inference/document-paths.asciidoc | 2 + .../inference/features-inference.asciidoc | 2 + .../inference/field-inference.asciidoc | 6 +- .../inference/ids-inference.asciidoc | 2 + .../inference/index-name-inference.asciidoc | 124 +++- .../inference/indices-paths.asciidoc | 2 + .../inference/property-inference.asciidoc | 2 + .../high-level/mapping/auto-map.asciidoc | 4 +- .../low-level/connecting.asciidoc | 678 +++++++++--------- .../low-level/lifetimes.asciidoc | 8 +- .../low-level/post-data.asciidoc | 2 + .../code-standards/descriptors.asciidoc | 2 + .../code-standards/elastic-client.asciidoc | 2 + .../naming-conventions.asciidoc | 2 + docs/asciidoc/code-standards/queries.asciidoc | 2 + .../serialization/properties.asciidoc | 2 + docs/asciidoc/common-options.asciidoc | 9 +- .../date-math/date-math-expressions.asciidoc | 2 + .../distance-unit/distance-units.asciidoc | 38 +- .../time-unit/time-units.asciidoc | 16 +- docs/asciidoc/high-level.asciidoc | 18 +- docs/asciidoc/intro.asciidoc | 10 +- docs/asciidoc/low-level.asciidoc | 6 +- docs/asciidoc/query-dsl-usage.asciidoc | 2 + docs/asciidoc/query-dsl.asciidoc | 2 + .../query-dsl/bool-dsl/bool-dsl.asciidoc | 2 + .../operators/and-operator-usage.asciidoc | 2 + .../operators/not-operator-usage.asciidoc | 2 + .../operators/or-operator-usage.asciidoc | 2 + .../unary-add-operator-usage.asciidoc | 2 + .../compound/and/and-query-usage.asciidoc | 2 + .../bool-dsl-complex-query-usage.asciidoc | 2 + .../compound/bool/bool-query-usage.asciidoc | 2 + .../boosting/boosting-query-usage.asciidoc | 2 + .../constant-score-query-usage.asciidoc | 2 + .../dismax/dismax-query-usage.asciidoc | 2 + .../filtered/filtered-query-usage.asciidoc | 2 + .../function-score-query-usage.asciidoc | 4 +- .../indices-no-match-query-usage.asciidoc | 2 + .../indices/indices-query-usage.asciidoc | 2 + .../compound/limit/limit-query-usage.asciidoc | 2 + .../compound/not/not-query-usage.asciidoc | 2 + .../compound/or/or-query-usage.asciidoc | 2 + .../common-terms/common-terms-usage.asciidoc | 2 + .../match/match-phrase-prefix-usage.asciidoc | 2 + .../match/match-phrase-usage.asciidoc | 2 + .../full-text/match/match-usage.asciidoc | 2 + .../multi-match/multi-match-usage.asciidoc | 5 +- .../query-string/query-string-usage.asciidoc | 2 + .../simple-query-string-usage.asciidoc | 2 + .../geo-bounding-box-query-usage.asciidoc | 2 + .../geo-distance-range-query-usage.asciidoc | 2 + .../geo-distance-query-usage.asciidoc | 2 + .../geo-hash-cell-query-usage.asciidoc | 2 + .../polygon/geo-polygon-query-usage.asciidoc | 2 + .../circle/geo-shape-circle-usage.asciidoc | 2 + .../envelope/geo-envelope-usage.asciidoc | 2 + .../geo-indexed-shape-usage.asciidoc | 2 + .../geo-line-string-usage.asciidoc | 2 + .../geo-multi-line-string-usage.asciidoc | 2 + .../geo-multi-point-usage.asciidoc | 2 + .../geo/shape/point/geo-point-usage.asciidoc | 2 + .../shape/polygon/geo-polygon-usage.asciidoc | 2 + .../has-child/has-child-query-usage.asciidoc | 2 + .../has-parent-query-usage.asciidoc | 2 + .../nested/nested-query-usage.asciidoc | 2 + .../raw/raw-combine-usage.asciidoc | 2 + .../raw/raw-query-usage.asciidoc | 2 + .../span-containing-query-usage.asciidoc | 2 + .../first/span-first-query-usage.asciidoc | 2 + .../span-multi-term-query-usage.asciidoc | 2 + .../span/near/span-near-query-usage.asciidoc | 2 + .../span/not/span-not-query-usage.asciidoc | 2 + .../span/or/span-or-query-usage.asciidoc | 2 + .../span/term/span-term-query-usage.asciidoc | 2 + .../within/span-within-query-usage.asciidoc | 2 + .../more-like-this-query-usage.asciidoc | 2 + .../script/script-query-usage.asciidoc | 10 +- .../template/template-query-usage.asciidoc | 2 + .../exists/exists-query-usage.asciidoc | 2 + .../fuzzy/fuzzy-date-query-usage.asciidoc | 2 + .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 2 + .../fuzzy/fuzzy-query-usage.asciidoc | 2 + .../term-level/ids/ids-query-usage.asciidoc | 2 + .../missing/missing-query-usage.asciidoc | 2 + .../prefix/prefix-query-usage.asciidoc | 2 + .../range/date-range-query-usage.asciidoc | 2 + .../range/numeric-range-query-usage.asciidoc | 2 + .../range/term-range-query-usage.asciidoc | 2 + .../regexp/regexp-query-usage.asciidoc | 2 + .../term-level/term/term-query-usage.asciidoc | 2 + .../terms/terms-list-query-usage.asciidoc | 150 ++++ .../terms/terms-lookup-query-usage.asciidoc | 2 + .../terms/terms-query-usage.asciidoc | 27 +- .../term-level/type/type-query-usage.asciidoc | 2 + .../wildcard/wildcard-query-usage.asciidoc | 2 + .../search/request/explain-usage.asciidoc | 2 + .../request/fielddata-fields-usage.asciidoc | 2 + .../search/request/fields-usage.asciidoc | 2 + .../request/from-and-size-usage.asciidoc | 2 + .../request/highlighting-usage.asciidoc | 2 + .../search/request/index-boost-usage.asciidoc | 2 + .../search/request/inner-hits-usage.asciidoc | 2 + .../search/request/min-score-usage.asciidoc | 2 + .../search/request/post-filter-usage.asciidoc | 2 + .../search/request/profile-usage.asciidoc | 2 + .../search/request/query-usage.asciidoc | 2 + .../request/script-fields-usage.asciidoc | 2 + .../search/request/sort-usage.asciidoc | 2 + .../request/source-filtering-usage.asciidoc | 2 + .../search/request/suggest-usage.asciidoc | 2 + .../search/suggesters/suggest-api.asciidoc | 2 + .../AsciiDoc/GeneratedAsciidocVisitor.cs | 23 +- .../Nest.Litterateur/StringExtensions.cs | 30 +- .../Filter/FilterAggregationUsageTests.cs | 17 +- .../BuildingBlocks/ConnectionPooling.Doc.cs | 2 +- .../BuildingBlocks/Transports.Doc.cs | 9 +- .../Pinging/FirstUsage.doc.cs | 37 +- .../HighLevel/Inference/FieldInference.doc.cs | 2 +- .../Inference/IndexNameInference.doc.cs | 95 ++- .../ClientConcepts/LowLevel/Connecting.doc.cs | 80 ++- .../ClientConcepts/LowLevel/Lifetimes.doc.cs | 6 +- .../DistanceUnit/DistanceUnits.doc.cs | 45 +- .../CommonOptions/TimeUnit/TimeUnits.doc.cs | 24 +- .../TermLevel/Terms/TermsQueryUsageTests.cs | 8 + src/Tests/common-options.asciidoc | 7 +- src/Tests/high-level.asciidoc | 13 +- src/Tests/low-level.asciidoc | 5 +- src/lib/dnx451/AsciiDoc.dll | Bin 74752 -> 75776 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 249344 -> 253440 bytes 206 files changed, 1420 insertions(+), 560 deletions(-) create mode 100644 docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index a7baf5059c9..227fa6c5495 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[child-aggregation-mapping]] diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index 15175f7c864..6afb38f8ff4 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[children-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index 04d03ec3773..566299b3bba 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[date-histogram-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index d27e1c5bad4..655dc315bea 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[date-range-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index db5d7c97272..6f01eb49406 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -2,15 +2,17 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[filter-aggregation-usage]] == Filter Aggregation Usage -Defines a single bucket of all the documents in the current document set context that match a specified filter. +Defines a single bucket of all the documents in the current document set context that match a specified filter. Often this will be used to narrow down the current aggregation context to a specific set of documents. -Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] +Be sure to read the Elasticsearch documentation on {ref_current}/search-aggregations-bucket-filter-aggregation.html[Filter Aggregation] === Fluent DSL Example @@ -69,7 +71,7 @@ new SearchRequest === Handling Responses -Using the `.Aggs` aggregation helper we can fetch our aggregation results easily +Using the `.Aggs` aggregation helper we can fetch our aggregation results easily in the correct type. <> [source,csharp] @@ -143,3 +145,65 @@ response.IsValid.Should().BeTrue(); response.Aggs.Filter("empty_filter").DocCount.Should().BeGreaterThan(0); ---- +[[inline-script-filter]] +[float] +== Inline Script Filter + +=== Fluent DSL Example + +[source,csharp] +---- +s => s +.Aggregations(aggs => aggs + .Filter(_aggName, date => date + .Filter(f => f + .Script(b => b + .Inline(_ctxNumberofCommits) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new SearchRequest +{ + Aggregations = new FilterAggregation(_aggName) + { + Filter = new ScriptQuery + { + Inline = _ctxNumberofCommits + } + } +} +---- + +[source,javascript] +.Example json output +---- +{ + "aggs": { + "script_filter": { + "filter": { + "script": { + "script": { + "inline": "_source.numberOfCommits > 0" + } + } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp] +---- +response.IsValid.Should().BeTrue(); +response.Aggs.Filter(_aggName).DocCount.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index 1b139fc2614..3668fd5139b 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[filters-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index 59644c37817..d9162e623fa 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-distance-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index 1a2403a212e..563ff562bc6 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-hash-grid-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index 95df9ed2413..1965601fe08 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[global-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index 151408b1e3f..839dc1200b5 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[histogram-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index 323cc4ff3ae..7966d7965bd 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[ip-range-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index d1285525650..b2c1325173e 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[missing-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index 2d8091a61ee..90bf74c6d73 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[nested-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index 5e238c80372..c69d8f05c9d 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[range-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index 916200e2ec8..729d393ae18 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[reverse-nested-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index 3ded3c03bf1..b2599904fa2 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sampler-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index be714e87a81..8e24eecc122 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[significant-terms-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index a5660ff1827..14eb8a70b6b 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[terms-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index 69410c317f1..ac327c453b1 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[average-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index dab1cba4fc6..93f380ba8d8 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[cardinality-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 13caf7ff775..0545ef2d91e 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[extended-stats-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index 670c6ef6fad..fc4165515ac 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-bounds-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index 2c8e8242868..6ef21ffde76 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[max-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index 4f7d6ad1dc9..b4df7cccfcb 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[min-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index 8adec6bdbda..7b0912b4a2b 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[percentile-ranks-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index d3918a86202..712d5ea3d79 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[percentiles-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index e93b1a34588..f0071a8ae18 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[scripted-metric-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index 4508c2ad5d5..201336fdc24 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[stats-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 01c966930c0..35e2b978162 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sum-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index f344702a819..6b607cd99b4 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[top-hits-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index b7e9641fc88..3101a4be5af 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[value-count-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index b51898f2570..0609a89f8c9 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[average-bucket-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index 5313f8f5a7b..1f39b46e9af 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[bucket-script-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 67bc25de59b..11078eee6fa 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[bucket-selector-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index 0106cac1193..8c7a1b14cc2 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[cumulative-sum-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index f312a81f3e8..6792dc03690 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[derivative-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index 05f6811050e..b4b0d9a2dab 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[max-bucket-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index ab8bec24559..1c42f828b75 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[min-bucket-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index 786eec57ee3..cc2812d7b4d 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[moving-average-ewma-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index 8b2738167bf..f54486acfb8 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[moving-average-holt-linear-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index 7ec758fe642..5a01ed41876 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[moving-average-holt-winters-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index a6f24fb454b..6a314695bb7 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[moving-average-linear-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index 5f4e11d7c0b..f65a4547172 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[moving-average-simple-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index 5bb13c323f5..abd6323b1bc 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[serial-differencing-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index 42bef649d07..f4c5bc51cc0 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sum-bucket-aggregation-usage]] diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index de13cad4025..84470d77b8d 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../images/ [[writing-aggregations]] diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc index dd56131007b..451a42d2158 100644 --- a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[analyzer-usage]] diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc index 6716d582b88..7cd72547a9f 100644 --- a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[char-filter-usage]] diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc index 742485c7145..123b5bec790 100644 --- a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[token-filter-usage]] diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc index d7fede38f0e..2109522962a 100644 --- a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[tokenizer-usage]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index 31d4f37c163..b2a857d1839 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[connection-pooling]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 905e673a20b..21b974474ea 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[date-time-providers]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 3d9fa5746ae..3959adfe0b2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[keeping-track-of-nodes]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 00930feafb5..e103179846a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[request-pipeline]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index 218a1348258..9b5a068640f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[transports]] @@ -18,14 +20,14 @@ by implementing a custom `ITransport`, you can circumvent all of it and introduc Transport is generically typed to a type that implements `IConnectionConfigurationValues` This is the minimum `ITransport` needs to report back for the client to function. -e.g in the low level client, transport is instantiated like this: +e.g in the low level client, Elasticsearch.Net, transport is instantiated like this: [source,csharp] ---- var lowLevelTransport = new Transport(new ConnectionConfiguration()); ---- -and in the high level client, like this: +and in the high level client, NEST, like this: [source,csharp] ---- @@ -43,6 +45,9 @@ If you feel this need, {github}/issues[please let us know] as we'd love to learn ---- var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); -response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); +response = await inMemoryTransport.RequestAsync>( + HttpMethod.GET, + "/_search", + new { query = new { match_all = new { } } }); ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index e054b702a20..500db6ac62c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[unexpected-exceptions]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 9e6725feeb0..ca926a265d4 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[unrecoverable-exceptions]] @@ -92,12 +94,15 @@ audit = await audit.TraceElasticsearchException( (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().BeNull(); } ); e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); +e.Response.HttpStatusCode.Should().Be(401); + e.Response.ResponseBodyInBytes.Should().BeNull(); ---- @@ -119,6 +124,7 @@ audit = await audit.TraceElasticsearchException( (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); responseString.Should().Contain("nginx/"); @@ -128,6 +134,8 @@ audit = await audit.TraceElasticsearchException( e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); +e.Response.HttpStatusCode.Should().Be(401); + e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); @@ -159,6 +167,7 @@ audit = await audit.TraceElasticsearchException( (e) => { e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); + e.Response.HttpStatusCode.Should().Be(401); e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); responseString.Should().Contain("nginx/"); @@ -168,6 +177,8 @@ audit = await audit.TraceElasticsearchException( e.FailureReason.Should().Be(PipelineFailure.BadAuthentication); +e.Response.HttpStatusCode.Should().Be(401); + e.Response.ResponseBodyInBytes.Should().NotBeNull(); var responseString = Encoding.UTF8.GetString(e.Response.ResponseBodyInBytes); diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 9186510e22b..2292c45ff15 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[fail-over]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index ae988a04eb7..4c36843adcc 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[max-retries]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index 2b1e5071f14..d3cfd035c18 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -4,16 +4,18 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[pinging---first-usage]] == Pinging - First Usage -Pinging is enabled by default for the Static & Sniffing connection pool. -This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. -This allows us to fail and fallover to a healthy node faster +Pinging is enabled by default for the <> and <> connection pools. +This means that the first time a node is used or resurrected, a ping is issued a with a small (configurable) timeout, +allowing the client to fail and fallover to a healthy node much faster than attempting a request that may be heavier than a ping. -A cluster with 2 nodes where the second node fails on ping +Here's an example with a cluster with 2 nodes where the second node fails on ping [source,csharp] ---- @@ -26,17 +28,17 @@ var audit = new Auditor(() => Framework.Cluster ); ---- -The first call goes to 9200 which succeeds - -The 2nd call does a ping on 9201 because its used for the first time. -It fails so we wrap over to node 9200 which we've already pinged +When making the calls, the first call goes to 9200 which succeeds, +and the 2nd call does a ping on 9201 because it's used for the first time. +The ping fails so we wrap over to node 9200 which we've already pinged. -Finally we assert that the connectionpool has one node that is marked as dead +Finally we assert that the connectionpool has one node that is marked as dead [source,csharp] ---- await audit.TraceCalls( -new ClientCall { + + new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200}, { pool => @@ -44,10 +46,10 @@ new ClientCall { pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); } } }, -new ClientCall { + new ClientCall { { PingFailure, 9201}, { HealthyResponse, 9200}, -{ pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } + { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } } ); ---- @@ -68,8 +70,8 @@ var audit = new Auditor(() => Framework.Cluster The first call goes to 9200 which succeeds -The 2nd call does a ping on 9201 because its used for the first time. -It fails and so we ping 9202 which also fails. We then ping 9203 becuase +The 2nd call does a ping on 9201 because its used for the first time. +It fails and so we ping 9202 which also fails. We then ping 9203 becuase we haven't used it before and it succeeds Finally we assert that the connectionpool has two nodes that are marked as dead @@ -77,7 +79,7 @@ Finally we assert that the connectionpool has two nodes that are marked as dead [source,csharp] ---- await audit.TraceCalls( -new ClientCall { +new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200}, { pool => @@ -85,7 +87,7 @@ new ClientCall { pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); } } }, -new ClientCall { +new ClientCall { { PingFailure, 9201}, { PingFailure, 9202}, { PingSuccess, 9203}, @@ -95,7 +97,7 @@ new ClientCall { ); ---- - A healthy cluster of 4 (min master nodes of 3 of course!) +A healthy cluster of 4 (min master nodes of 3 of course!) [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 67440272733..7343f05bbca 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[pinging---revival]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 5e2bd823275..7e8a733e2c2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[disabling-sniffing-and-pinging-on-a-request-basis]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 43f35f438c2..8e24f08e9e5 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[request-timeouts]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 7fbf81a9fed..765b2ab630f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[allowed-status-codes]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 8349ebbef31..460e50b2ddb 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[forcing-nodes]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index 15ad8ed5a77..54afcfaff38 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[maximum-retries]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index b0a11d96e03..14de1602a14 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[round-robin]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index e04b858a954..19871482cfa 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[round-robin---skipping-dead-nodes]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index aba5be664b3..7a033a704b8 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[volatile-updates]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index ba017205415..08006671d02 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sniffing-on-connection-failure]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index f9893d493c1..439ddbc04f9 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sniffing-periodically]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index 07cdd01401d..852b9f1a0a2 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sniffing-on-startup]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index c676e67fa36..ef4d656fd15 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -4,6 +4,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sniffing-role-detection]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc index dfaf1b175f3..4830ed2159d 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[skip-dead-nodes]] diff --git a/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc index f8d05a08b1a..c2f48b87e4a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[sticky]] diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index 383eca9f0b9..e6207bba61d 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[covariant-search-results]] diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index 02296b1fcc4..af595ad36cf 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[document-paths]] diff --git a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc index 888e4ff039b..86653650bef 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[features-inference]] diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index efd18a1cff7..14c505e6258 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -2,12 +2,14 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[field-inference]] == Field Inference -Several places in the elasticsearch API expect the path to a field from your original source document as a string. +Several places in the Elasticsearch API expect the path to a field from your original source document as a string. NEST allows you to use C# expressions to strongly type these field path strings. These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: @@ -71,7 +73,7 @@ but for expressions this is still rather involved var fieldExpression = Infer.Field(p => p.Name); ---- -this can be even shortened even further using a https://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. +this can be even shortened even further using ahttps://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. `using static Nest.Infer;` [source,csharp] diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index ed345c9c60e..49301f29934 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[ids-inference]] diff --git a/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc index e956c78aec0..579a34df096 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc @@ -2,11 +2,36 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[index-name-inference]] == Index Name Inference +Many endpoints within the Elasticsearch API expect to receive one or more index names +as part of the request in order to know what index/indices a request should operate on. + +NEST has a number of ways in which an index name can be specified + +=== Default Index name on ConnectionSettings + +A default index name can be specified on `ConnectionSettings` usinf `.DefaultIndex()`. +This is the default index name to use when no other index name can be resolved for a request + +[source,csharp] +---- +var settings = new ConnectionSettings() + .DefaultIndex("defaultindex"); +var resolver = new IndexNameResolver(settings); +var index = resolver.Resolve(); +index.Should().Be("defaultindex"); +---- + +=== Mapping an Index name for POCOs + +A index name can be mapped for CLR types using `.MapDefaultTypeIndices()` on `ConnectionSettings`. + [source,csharp] ---- var settings = new ConnectionSettings() @@ -21,6 +46,11 @@ var index = resolver.Resolve(); index.Should().Be("projects"); ---- +=== Mapping an Index name for POCOs + +An index name for a POCO provided using `.MapDefaultTypeIndices()` **will take precedence** over +the default index name + [source,csharp] ---- var settings = new ConnectionSettings() @@ -36,6 +66,58 @@ var index = resolver.Resolve(); index.Should().Be("projects"); ---- +=== Explicitly specifying Index name on the request + +For API calls that expect an index name, the index name can be explicitly provided +on the request + +[source,csharp] +---- +Uri requestUri = null; + +var client = TestClient.GetInMemoryClient(s => s + .OnRequestCompleted(r => { requestUri = r.Uri; })); + +var response = client.Search(s => s.Index("some-other-index")); <1> + +requestUri.Should().NotBeNull(); + +requestUri.LocalPath.Should().StartWith("/some-other-index/"); +---- +<1> Provide the index name on the request + +When an index name is provided on a request, it **will take precedence** over the default +index name and any index name specified for the POCO type using `.MapDefaultTypeIndices()` + +[source,csharp] +---- +var client = TestClient.GetInMemoryClient(s => + new ConnectionSettings() + .DefaultIndex("defaultindex") + .MapDefaultTypeIndices(m => m + .Add(typeof(Project), "projects") + ) +); + +var response = client.Search(s => s.Index("some-other-index")); <1> + +response.ApiCall.Uri.Should().NotBeNull(); + +response.ApiCall.Uri.LocalPath.Should().StartWith("/some-other-index/"); +---- +<1> Provide the index name on the request + +=== Naming Conventions + +Index names within Elasticsearch cannot contain upper case letters. +NEST will check the index name at the point at which the index +name needs to be resolved to make a request; if the index name contains +upper case letters, a `ResolveException` will be thrown indicating +the problem and the index name that caused the problem. + +In the following example, we create a connection settings withboth a default index +name and an index name to use for the `Project` type. + [source,csharp] ---- var settings = new ConnectionSettings() @@ -45,20 +127,49 @@ var settings = new ConnectionSettings() ); var resolver = new IndexNameResolver(settings); +---- +When resolving the index name for the `Project` type, a `ResolveException` +is thrown, indicating that the index name "__myProjects__" contains upper case letters + +[source,csharp] +---- var e = Assert.Throws(() => resolver.Resolve()); e.Message.Should().Be($"Index names cannot contain uppercase characters: myProjects."); +---- +Similarly, when resolving the index name for the `Tag` type, which will use the default index +name, a `ResolveException` is thrown indicating that the default index name contains upper case +letters + +[source,csharp] +---- e = Assert.Throws(() => resolver.Resolve()); e.Message.Should().Be($"Index names cannot contain uppercase characters: Default."); +---- +Finally, when resolving an index name from a string, a `ResolveException` will be thrown +if the string contains upper case letters + +[source,csharp] +---- e = Assert.Throws(() => resolver.Resolve("Foo")); e.Message.Should().Be($"Index names cannot contain uppercase characters: Foo."); ---- +If no index name can be resolved for a request i.e. if + +* no default index name is set on connection settings + +* no index name is mapped for a POCO + +* no index name is explicitly specified on the request + +then a `ResolveException` will be thrown to indicate that the index name is `null` + [source,csharp] ---- var settings = new ConnectionSettings(); @@ -70,6 +181,10 @@ var e = Assert.Throws(() => resolver.Resolve()); e.Message.Should().Contain("Index name is null"); ---- +``ResolveException``s bubble out of the client and should be dealt with as <> +similar to `ArgumentException`, `ArgumentOutOfRangeException` and other exceptions that _usually_ indicate +misuse of the client API + [source,csharp] ---- var client = TestClient.GetInMemoryClient(s => new ConnectionSettings()); @@ -77,12 +192,3 @@ var client = TestClient.GetInMemoryClient(s => new ConnectionSettings()); var e = Assert.Throws(() => client.Search()); ---- -[source,csharp] ----- -var settings = new ConnectionSettings() - .DefaultIndex("defaultindex"); -var resolver = new IndexNameResolver(settings); -var index = resolver.Resolve(); -index.Should().Be("defaultindex"); ----- - diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index bdb5a7f96ce..3b40b15a455 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[indices-paths]] diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index cbbe14e3475..7a4da607b78 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[property-inference]] diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index b25e46314b7..b56885dd165 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[auto-map]] @@ -909,7 +911,7 @@ Expect(expectedWithMaxRecursion).WhenSerializing((IPutMappingRequest)withMaxRecu It is also possible to apply a transformation on all or specific properties. -AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, +AutoMap internally implements thehttps://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, does nothing and acts as a blank canvas for you to implement your own visiting methods. For instance, lets create a custom visitor that disables doc values for numeric and boolean types diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 29baa210742..3d05528b918 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -1,345 +1,351 @@ -:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current - -:github: https://github.com/elastic/elasticsearch-net - -:imagesdir: ../../images/ - -[[connecting]] -== Connecting - -Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. - -[[connection-strategies]] -=== Choosing the right Connection Strategy - -If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` - -[source,csharp] ----- -var client = new ElasticLowLevelClient(); ----- - -If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then -you will need to pass in some instance of `IConnectionConfigurationValues`. - -The easiest way to do this is: - -[source,csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); - -var config = new ConnectionConfiguration(node); - -var client = new ElasticLowLevelClient(config); ----- - -This will still be a non-failover connection, meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. - -To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. - -[source,csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); - -var connectionPool = new SniffingConnectionPool(new[] { node }); - -var config = new ConnectionConfiguration(connectionPool); - -var client = new ElasticLowLevelClient(config); ----- - -Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. -Be sure to read more about <>. - -=== Configuration Options - - Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: - -[source,csharp] ----- -var node = new Uri("http://mynode.example.com:8082/apiKey"); - -var connectionPool = new SniffingConnectionPool(new[] { node }); - -var config = new ConnectionConfiguration(connectionPool) - .DisableDirectStreaming() - .BasicAuthentication("user", "pass") - .RequestTimeout(TimeSpan.FromSeconds(5)); ----- - -The following is a list of available connection configuration options: - -[source,csharp] ----- -var config = new ConnectionConfiguration() +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:nuget: https://www.nuget.org/packages + +:imagesdir: ../../images/ + +[[connecting]] +== Connecting + +Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a few options to suit a number of different use cases. + +[[connection-strategies]] +=== Choosing the right Connection Strategy + +If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` + +[source,csharp] +---- +var client = new ElasticLowLevelClient(); +---- + +If your Elasticsearch node does not live at `http://localhost:9200` but instead lives somewhere else, for example, `http://mynode.example.com:8082/apiKey`, then +you will need to pass in some instance of `IConnectionConfigurationValues`. + +The easiest way to do this is: + +[source,csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); + +var config = new ConnectionConfiguration(node); + +var client = new ElasticLowLevelClient(config); +---- + +This will still be a non-failover connection, meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. + +To get a failover connection we have to pass an <> instance instead of a `Uri`. + +[source,csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); + +var connectionPool = new SniffingConnectionPool(new[] { node }); + +var config = new ConnectionConfiguration(connectionPool); + +var client = new ElasticLowLevelClient(config); +---- + +Here instead of directly passing `node`, we pass a <> +which will use our `node` to find out the rest of the available cluster nodes. +Be sure to read more about <>. + +=== Configuration Options + +Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: + +[source,csharp] +---- +var node = new Uri("http://mynode.example.com:8082/apiKey"); + +var connectionPool = new SniffingConnectionPool(new[] { node }); + +var config = new ConnectionConfiguration(connectionPool) + .DisableDirectStreaming() <1> + .BasicAuthentication("user", "pass") <1> + .RequestTimeout(TimeSpan.FromSeconds(5)); <1> +---- +<1> Additional options + +The following is a list of available connection configuration options: + +[source,csharp] +---- +var config = new ConnectionConfiguration() .DisableAutomaticProxyDetection() <1> .EnableHttpCompression() <2> .DisableDirectStreaming(); <3> - -var client = new ElasticLowLevelClient(config); - -var result = client.Search>(new { size = 12 }); ----- -<1> Disable automatic proxy detection. Defaults to `true`. - -<2> Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. See the {ref_current}/modules-http.html[http module settings] for more info). - -<3> By default responses are deserialized directly from the response stream to the object you tell it to. For debugging purposes, it can be very useful to keep a copy of the raw response on the result object, which is what calling this method will do. - -This will only have a value if the client configuration has `DisableDirectStreaming` set - -[source,csharp] ----- -var raw = result.ResponseBodyInBytes; ----- - -Please note that using `.DisableDirectStreaming` only makes sense if you need the mapped response **and** the raw response __at the same time__. -If you need a only `string` or `byte[]` response simply call - -[source,csharp] ----- -var stringResult = client.Search(new { }); ----- - -other configuration options - -[source,csharp] ----- -config = config + +var client = new ElasticLowLevelClient(config); + +var result = client.Search>(new { size = 12 }); +---- +<1> Disable automatic proxy detection. Defaults to `true`. + +<2> Enable compressed request and reesponses from Elasticsearch (Note that nodes need to be configured to allow this. See the {ref_current}/modules-http.html[http module settings] for more info). + +<3> By default responses are deserialized directly from the response stream to the object you tell it to. For debugging purposes, it can be very useful to keep a copy of the raw response on the result object, which is what calling this method will do. + +This will only have a value if the client configuration has `DisableDirectStreaming` set + +[source,csharp] +---- +var raw = result.ResponseBodyInBytes; +---- + +Please note that using `.DisableDirectStreaming` only makes sense if you need the mapped response **and** the raw response __at the same time__. +If you need a only `string` or `byte[]` response simply call + +[source,csharp] +---- +var stringResult = client.Search(new { }); +---- + +other configuration options + +[source,csharp] +---- +config = config .GlobalQueryStringParameters(new NameValueCollection()) <1> .Proxy(new Uri("http://myproxy"), "username", "pass") <2> .RequestTimeout(TimeSpan.FromSeconds(4)) <3> .ThrowExceptions() <4> .PrettyJson() <5> - .BasicAuthentication("username", "password"); ----- -<1> Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. - -<2> Sets proxy information on the connection. - -<3> Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). - -<4> As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to <>. - -<5> forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well - -NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: - -[source,csharp] ----- -var uri = new Uri("http://username:password@localhost:9200"); - -var settings = new ConnectionConfiguration(uri); ----- - -...but this may become tedious when using connection pooling with multiple nodes. - -[[thrown-exceptions]] -=== Exceptions - -There are three category of exceptions that may be thrown: - -. `ElasticsearchClientException`: These are known exceptions, either an exception that occurred in the request pipeline -(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could -not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property -on the response will contain the the actual error that was returned. The inner exception will always contain the -root causing exception. - -. `UnexpectedElasticsearchClientException`: These are unknown exceptions, for instance a response from Elasticsearch not -properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` -so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. - -. Development time exceptions: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown -when an API in the client is misused. These should not be handled as you want to know about them during development. - -=== OnRequestCompleted - -You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. -If you have complex logging needs this is a good place to add that in. - -[source,csharp] ----- -var counter = 0; - -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); - -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) - .OnRequestCompleted(r => counter++); - -var client = new ElasticClient(settings); - -client.RootNodeInfo(); - -counter.Should().Be(1); - -client.RootNodeInfoAsync(); - -counter.Should().Be(2); ----- - -[source,csharp] ----- -var counter = 0; - -var client = TestClient.GetFixedReturnClient(new { }, 500, s => s - .ThrowExceptions() - .OnRequestCompleted(r => counter++) -); - -Assert.Throws(() => client.RootNodeInfo()); - -counter.Should().Be(1); - -Assert.ThrowsAsync(() => client.RootNodeInfoAsync()); - -counter.Should().Be(2); ----- - -[[complex-logging]] -Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like -to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` -to `true` - -[source,csharp] ----- -var list = new List(); - -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); - + .BasicAuthentication("username", "password"); +---- +<1> Allows you to set querystring parameters that have to be added to every request. For instance, if you use a hosted elasticserch provider, and you need need to pass an `apiKey` parameter onto every request. + +<2> Sets proxy information on the connection. + +<3> Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts (seehttp://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). + +<4> As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to <>. + +<5> forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well + +NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: + +[source,csharp] +---- +var uri = new Uri("http://username:password@localhost:9200"); + +var settings = new ConnectionConfiguration(uri); +---- + +...but this may become tedious when using connection pooling with multiple nodes. + +[[thrown-exceptions]] +=== Exceptions + +There are three category of exceptions that may be thrown: + +`ElasticsearchClientException`:: +These are known exceptions, either an exception that occurred in the request pipeline +(such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could +not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property +on the response will contain the the actual error that was returned. The inner exception will always contain the +root causing exception. + +`UnexpectedElasticsearchClientException`:: +These are unknown exceptions, for instance a response from Elasticsearch not +properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` +so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. + +Development time exceptions:: +These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException`, etc. and other exceptions like `ResolveException` that are thrown when an API in the client is misused. +These should not be handled as you want to know about them during development. + +=== OnRequestCompleted + +You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. +If you have complex logging needs this is a good place to add that in. + +[source,csharp] +---- +var counter = 0; + +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); + +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) + .OnRequestCompleted(r => counter++); + +var client = new ElasticClient(settings); + +client.RootNodeInfo(); + +counter.Should().Be(1); + +client.RootNodeInfoAsync(); + +counter.Should().Be(2); +---- + +`OnRequestCompleted` is called even when an exception is thrown + +[source,csharp] +---- +var counter = 0; + +var client = TestClient.GetFixedReturnClient(new { }, 500, s => s + .ThrowExceptions() + .OnRequestCompleted(r => counter++) +); + +Assert.Throws(() => client.RootNodeInfo()); + +counter.Should().Be(1); + +Assert.ThrowsAsync(() => client.RootNodeInfoAsync()); + +counter.Should().Be(2); +---- + +[[complex-logging]] +Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like +to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` + +[source,csharp] +---- +var list = new List(); + +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); + var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) <1> - .DefaultIndex("default-index") - .DisableDirectStreaming() - .OnRequestCompleted(response => - { - // log out the request - if (response.RequestBodyInBytes != null) - { - list.Add( - $"{response.HttpMethod} {response.Uri} \n" + - $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); - } - else - { - list.Add($"{response.HttpMethod} {response.Uri}"); - } - - // log out the response - if (response.ResponseBodyInBytes != null) - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + - $"{new string('-', 30)}\n"); - } - else - { - list.Add($"Status: {response.HttpStatusCode}\n" + - $"{new string('-', 30)}\n"); - } - }); - -var client = new ElasticClient(settings); - -var syncResponse = client.Search(s => s - .AllTypes() - .AllIndices() - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) -); - -list.Count.Should().Be(2); - -var asyncResponse = await client.SearchAsync(s => s - .AllTypes() - .AllIndices() - .Scroll("2m") - .Sort(ss => ss - .Ascending(SortSpecialField.DocumentIndexOrder) - ) -); - -list.Count.Should().Be(4); - -list.ShouldAllBeEquivalentTo(new [] - { - "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", - "Status: 200\n------------------------------\n", - "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", - "Status: 200\n------------------------------\n" - }); ----- -<1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` to make the actual request - -[[configuring-ssl]] -=== Configuring SSL - -SSL must be configured outside of the client using .NET's -http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] -class and setting the http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx[ServerCertificateValidationCallback] -property. - -The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: - -[source,csharp] ----- -ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; ----- - -However, this will accept **all** requests from the AppDomain to untrusted SSL sites, -therefore **we recommend doing some minimal introspection on the passed in certificate.** - -=== Overriding default Json.NET behavior - -Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful - -Create a subclass of the `JsonNetSerializer` - -Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` - -You can inject contract resolved converters by implementing the ContractConverters property -This can be much faster then registering them on JsonSerializerSettings.Converters - -[source,csharp] ----- -public class MyJsonNetSerializer : JsonNetSerializer -{ - public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } -public int CallToModify { get; set; } = 0; - protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; -public int CallToContractConverter { get; set; } = 0; - protected override IList> ContractConverters => new List> - { - t => { - CallToContractConverter++; - return null; - } - }; - -} ----- - -You can then register a factory on `ConnectionSettings` to create an instance of your subclass instead. -This is **_called once per instance_** of ConnectionSettings. - -[source,csharp] ----- -var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); - -var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); - -var client = new ElasticClient(settings); - -client.RootNodeInfo(); - -client.RootNodeInfo(); - -var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; - -serializer.CallToModify.Should().BeGreaterThan(0); - -serializer.SerializeToString(new Project { }); - -serializer.CallToContractConverter.Should().BeGreaterThan(0); ----- - + .DefaultIndex("default-index") + .DisableDirectStreaming() + .OnRequestCompleted(response => + { + // log out the request and the request body, if available + if (response.RequestBodyInBytes != null) + { + list.Add( + $"{response.HttpMethod} {response.Uri} \n" + + $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); + } + else + { + list.Add($"{response.HttpMethod} {response.Uri}"); + } + + // log out the response and the response body, if available + if (response.ResponseBodyInBytes != null) + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + + $"{new string('-', 30)}\n"); + } + else + { + list.Add($"Status: {response.HttpStatusCode}\n" + + $"{new string('-', 30)}\n"); + } + }); + +var client = new ElasticClient(settings); + +var syncResponse = client.Search(s => s + .AllTypes() + .AllIndices() + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) +); + +list.Count.Should().Be(2); + +var asyncResponse = await client.SearchAsync(s => s + .AllTypes() + .AllIndices() + .Scroll("2m") + .Sort(ss => ss + .Ascending(SortSpecialField.DocumentIndexOrder) + ) +); + +list.Count.Should().Be(4); + +list.ShouldAllBeEquivalentTo(new [] + { + "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", + "Status: 200\n------------------------------\n", + "POST http://localhost:9200/_search?scroll=2m \n{\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", + "Status: 200\n------------------------------\n" + }); +---- +<1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` that actually makes a request. + +[[configuring-ssl]] +=== Configuring SSL + +SSL must be configured outside of the client using .NET's http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] +class and setting thehttp://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx[ServerCertificateValidationCallback] +property. + +The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: + +[source,csharp] +---- +ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; +---- + +However, this will accept **all** requests from the AppDomain to untrusted SSL sites, +therefore **we recommend doing some minimal introspection on the passed in certificate.** + +=== Overriding default Json.NET behavior + +Overriding the default Json.NET behaviour in NEST is an expert behavior but if you need to get to the nitty gritty, this can be really useful. +First, create a subclass of the `JsonNetSerializer` + +Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` + +You can inject contract resolved converters by implementing the ContractConverters property +This can be much faster then registering them on `JsonSerializerSettings.Converters` + +[source,csharp] +---- +public class MyJsonNetSerializer : JsonNetSerializer +{ + public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } +public int CallToModify { get; set; } = 0; + protected override void ModifyJsonSerializerSettings(JsonSerializerSettings settings) => ++CallToModify; +public int CallToContractConverter { get; set; } = 0; + protected override IList> ContractConverters => new List> + { + t => { + CallToContractConverter++; + return null; + } + }; + +} +---- + +You can then register a factory on `ConnectionSettings` to create an instance of your subclass instead. +This is **_called once per instance_** of ConnectionSettings. + +[source,csharp] +---- +var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); + +var settings = new ConnectionSettings(connectionPool, new InMemoryConnection(), s => new MyJsonNetSerializer(s)); + +var client = new ElasticClient(settings); + +client.RootNodeInfo(); + +client.RootNodeInfo(); + +var serializer = ((IConnectionSettingsValues)settings).Serializer as MyJsonNetSerializer; + +serializer.CallToModify.Should().BeGreaterThan(0); + +serializer.SerializeToString(new Project { }); + +serializer.CallToContractConverter.Should().BeGreaterThan(0); +---- + diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 8c2a4a71a4d..ce97ddf0f78 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[lifetimes]] @@ -18,9 +20,9 @@ application is `ConnectionSettings`; caches are __per__ `ConnectionSettings`. In some applications it could make perfect sense to have multiple singleton `ElasticClient`'s registered with different connection settings. e.g if you have 2 functionally isolated Elasticsearch clusters. -NOTE: Due to the semantic versioning of NEST and the alignment of versions to Elasticsearch, all instances of `ElasticClient` and thus -Elasticsearch that are connected to must be on the same major version i.e. it is not possible to have both an `ElasticClient` to connect to -Elasticsearch 1.x and 2.x in the same application as the former would require NEST 1.x and the latter, NEST 2.x. +NOTE: Due to the semantic versioning of Elasticsearch.Net and NEST and their alignment to versions of Elasticsearch, all instances of `ElasticClient` and +Elasticsearch clusters that are connected to must be on the **same major version** i.e. it is not possible to have both an `ElasticClient` to connect to +Elasticsearch 1.x _and_ 2.x in the same application as the former would require NEST 1.x and the latter, NEST 2.x. Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index 299d025ef0e..24fdc246c4b 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[post-data]] diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index efe65c27fab..6edaf28a066 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../images/ [[descriptors]] diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index cb4fded5230..d833454b09c 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../images/ [[elastic-client]] diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index f313bce5535..11a2fc316a0 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../images/ [[naming-conventions]] diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index b91485f4145..fb5312d5fb1 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../images/ [[queries]] diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index 699310c30e2..06f69b8a55e 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[properties]] diff --git a/docs/asciidoc/common-options.asciidoc b/docs/asciidoc/common-options.asciidoc index de10d6b64a8..b0d00578726 100644 --- a/docs/asciidoc/common-options.asciidoc +++ b/docs/asciidoc/common-options.asciidoc @@ -5,7 +5,14 @@ [partintro] -- -Something about the convenience types for working with time and distance units and date math expressions +NEST has a number of types for working with Elasticsearch conventions for: + + +* <> + +* <> + +* <> -- diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index 5852e072014..fa5f88e32d9 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[date-math-expressions]] diff --git a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc index b51a727aa21..f81f3185a82 100644 --- a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc +++ b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc @@ -2,13 +2,15 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[distance-units]] == Distance Units -Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], -the distance unit can be specified as a double number representing distance in meters, as a new instance of +Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], +the distance unit can be specified as a double number representing distance in meters, as a new instance of a `Distance`, or as a string of the form number and distance unit e.g. "`2.72km`" === Using Distance units in NEST @@ -21,11 +23,11 @@ The most straight forward way to construct a `Distance` is through its construct [source,csharp] ---- -var unitComposed = new Nest.Distance(25); -var unitComposedWithUnits = new Nest.Distance(25, Nest.DistanceUnit.Meters); +var unitComposed = new Distance(25); +var unitComposedWithUnits = new Distance(25, Nest.DistanceUnit.Meters); ---- -`Distance` serializes to a string composed of a factor and distance unit. +`Distance` serializes to a string composed of a factor and distance unit. The factor is a double so always has at least one decimal place when serialized [source,csharp] @@ -37,16 +39,16 @@ Expect("25.0m") ==== Implicit conversion -Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. +Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. If no `DistanceUnit` is specified, the default distance unit is meters [source,csharp] ---- -Nest.Distance distanceString = "25"; +Distance distanceString = "25"; -Nest.Distance distanceStringWithUnits = "25m"; +Distance distanceStringWithUnits = "25m"; -Expect(new Nest.Distance(25)) +Expect(new Distance(25)) .WhenSerializing(distanceString) .WhenSerializing(distanceStringWithUnits); ---- @@ -61,28 +63,28 @@ A number of distance units are supported, from millimeters to nautical miles [source,csharp] ---- -Expect("2.0mm").WhenSerializing(new Nest.Distance(2, Nest.DistanceUnit.Millimeters)); +Expect("2.0mm").WhenSerializing(new Distance(2, Nest.DistanceUnit.Millimeters)); ---- `cm` (Centimeters) [source,csharp] ---- -Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, Nest.DistanceUnit.Centimeters)); +Expect("123.456cm").WhenSerializing(new Distance(123.456, Nest.DistanceUnit.Centimeters)); ---- `m` (Meters) [source,csharp] ---- -Expect("400.0m").WhenSerializing(new Nest.Distance(400, Nest.DistanceUnit.Meters)); +Expect("400.0m").WhenSerializing(new Distance(400, Nest.DistanceUnit.Meters)); ---- `km` (Kilometers) [source,csharp] ---- -Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilometers)); +Expect("0.1km").WhenSerializing(new Distance(0.1, Nest.DistanceUnit.Kilometers)); ---- ===== Imperial @@ -91,34 +93,34 @@ Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilomet [source,csharp] ---- -Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, Nest.DistanceUnit.Inch)); +Expect("43.23in").WhenSerializing(new Distance(43.23, Nest.DistanceUnit.Inch)); ---- `ft` (Feet) [source,csharp] ---- -Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, Nest.DistanceUnit.Feet)); +Expect("3.33ft").WhenSerializing(new Distance(3.33, Nest.DistanceUnit.Feet)); ---- `yd` (Yards) [source,csharp] ---- -Expect("9.0yd").WhenSerializing(new Nest.Distance(9, Nest.DistanceUnit.Yards)); +Expect("9.0yd").WhenSerializing(new Distance(9, Nest.DistanceUnit.Yards)); ---- `mi` (Miles) [source,csharp] ---- -Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, Nest.DistanceUnit.Miles)); +Expect("0.62mi").WhenSerializing(new Distance(0.62, Nest.DistanceUnit.Miles)); ---- `nmi` or `NM` (Nautical Miles) [source,csharp] ---- -Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, Nest.DistanceUnit.NauticalMiles)); +Expect("45.5nmi").WhenSerializing(new Distance(45.5, Nest.DistanceUnit.NauticalMiles)); ---- diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index b2b0662ffc4..bc38db8c699 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -2,13 +2,15 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[time-units]] == Time units -Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified -as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. +Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified +as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. === Using Time units in NEST @@ -26,15 +28,15 @@ var unitTimeSpan = new Time(TimeSpan.FromDays(2)); var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); ---- -When serializing Time constructed from +When serializing Time constructed from -* a string +* a string -* milliseconds (as a double) +* milliseconds (as a double) * composition of factor and interval -* a `TimeSpan` +* a `TimeSpan` the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` @@ -60,7 +62,7 @@ unitString.Milliseconds.Should().Be(1000*60*60*24*2); ==== Implicit conversion -Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` +Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` [source,csharp] ---- diff --git a/docs/asciidoc/high-level.asciidoc b/docs/asciidoc/high-level.asciidoc index 9a4401707dd..3eee68fcd44 100644 --- a/docs/asciidoc/high-level.asciidoc +++ b/docs/asciidoc/high-level.asciidoc @@ -1,7 +1,7 @@ :output-dir: client-concepts/high-level [[nest]] -= Client Concepts - High Level += Client Concepts - NEST [partintro] -- @@ -16,7 +16,7 @@ Install-Package NEST ---- -Or by searching for https://www.nuget.org/packages/NEST[NEST] in the Package Manager GUI. +Or by searching forhttps://www.nuget.org/packages/NEST[NEST] in the Package Manager GUI. NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> via the `.LowLevel` property on `ElasticClient`. @@ -24,14 +24,16 @@ the `.LowLevel` property on `ElasticClient`. There are a number of conventions that NEST uses for inference of +* <> + +* <> + * <> and <> * <> * <> -* <> - * <> @@ -44,6 +46,10 @@ In addition to features such as -- +include::{output-dir}/inference/index-name-inference.asciidoc[] + +include::{output-dir}/inference/indices-paths.asciidoc[] + include::{output-dir}/inference/field-inference.asciidoc[] include::{output-dir}/inference/property-inference.asciidoc[] @@ -52,13 +58,9 @@ include::{output-dir}/inference/ids-inference.asciidoc[] include::{output-dir}/inference/document-paths.asciidoc[] -include::{output-dir}/inference/indices-paths.asciidoc[] - include::{output-dir}/inference/features-inference.asciidoc[] include::{output-dir}/mapping/auto-map.asciidoc[] include::{output-dir}/covariant-hits/covariant-search-results.asciidoc[] -include::connection-pooling.asciidoc[] - diff --git a/docs/asciidoc/intro.asciidoc b/docs/asciidoc/intro.asciidoc index ddc314e19bd..0ff5442b350 100644 --- a/docs/asciidoc/intro.asciidoc +++ b/docs/asciidoc/intro.asciidoc @@ -23,22 +23,22 @@ Please read the getting started guide for both. * https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). * http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. - They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] + They are so pleased with Elasticsearch thathttp://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] === Other resources -http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a great http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] +http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a greathttp://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] using NEST. -Also checkout the https://searchbox.io/[searchbox.io guys] rocking NEST http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] -with their https://github.com/searchbox-io/.net-sample[demo project] +Also checkout thehttps://searchbox.io/[searchbox.io guys] rocking NESThttp://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] +with theirhttps://github.com/searchbox-io/.net-sample[demo project] === Questions, bugs, comments, requests All of these are more then welcome on the {github}/issues[github issues pages]! We try to at least reply within the same day. We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or -{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow], as well as https://discuss.elastic.co[discussions on our discourse site] +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow], as well ashttps://discuss.elastic.co[discussions on our discourse site] === License diff --git a/docs/asciidoc/low-level.asciidoc b/docs/asciidoc/low-level.asciidoc index e6d50c0a974..39d361c5a09 100644 --- a/docs/asciidoc/low-level.asciidoc +++ b/docs/asciidoc/low-level.asciidoc @@ -1,7 +1,7 @@ :output-dir: client-concepts/low-level [[elasticsearch-net]] -= Client Concepts - Low Level += Client Concepts - Elasticsearch.Net [partintro] -- @@ -17,7 +17,7 @@ Install-Package Elasticsearch.Net ---- -Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. +Or by searching forhttps://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. -- @@ -27,3 +27,5 @@ include::{output-dir}/lifetimes.asciidoc[] include::{output-dir}/post-data.asciidoc[] +include::connection-pooling.asciidoc[] + diff --git a/docs/asciidoc/query-dsl-usage.asciidoc b/docs/asciidoc/query-dsl-usage.asciidoc index 5d3586ad3ec..8d752caf371 100644 --- a/docs/asciidoc/query-dsl-usage.asciidoc +++ b/docs/asciidoc/query-dsl-usage.asciidoc @@ -122,6 +122,8 @@ include::../../docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asci include::../../docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc[] +include::../../docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc[] + include::../../docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc[] include::../../docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc[] diff --git a/docs/asciidoc/query-dsl.asciidoc b/docs/asciidoc/query-dsl.asciidoc index f861089183a..32d3b0f824a 100644 --- a/docs/asciidoc/query-dsl.asciidoc +++ b/docs/asciidoc/query-dsl.asciidoc @@ -129,6 +129,8 @@ NEST exposes all of the query DSL endpoints available in Elasticsearch * <> +* <> + * <> * <> diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index ca408b6cf38..9c03b085a64 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[bool-queries]] diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc index 57c6af17071..4fa321b6646 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[and-operator-usage]] diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc index 021d856ae2a..0aa593da19d 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[not-operator-usage]] diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc index b072709a6d3..74ce4dfd929 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[or-operator-usage]] diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc index 9246aac2caf..613ee8fc3fc 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[unary-add-operator-usage]] diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index 3f1f067a7c5..7183af22e9a 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[and-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc index eed5831eaf7..2d8759668d0 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[bool-dsl-complex-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc index d2b1cc27c36..a06025b5b0c 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[bool-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc index 0129cd6434d..cd724fb85e5 100644 --- a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[boosting-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc index 64ef531eb41..602ac8f2072 100644 --- a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[constant-score-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc index 1fd63790b5c..cf1b38a5fe5 100644 --- a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[dismax-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc index ed35edf83a5..15bcc1b8f97 100644 --- a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[filtered-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc index 095e1eb11af..a73c5495f59 100644 --- a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[function-score-query-usage]] @@ -51,7 +53,7 @@ new FunctionScoreQuery() new ExponentialDecayFunction { Origin = 1.0, Decay = 0.5, Field = Field(p=>p.NumberOfCommits), Scale = 0.1, Weight = 2.1 }, new GaussDateDecayFunction { Origin = DateMath.Now, Field = Field(p=>p.LastActivity), Decay = 0.5, Scale = TimeSpan.FromDays(1) }, new LinearGeoDecayFunction { Origin = new GeoLocation(70, -70), Field = Field(p=>p.Location), Scale = Distance.Miles(1), MultiValueMode = MultiValueMode.Average }, - new FieldValueFactorFunction + new FieldValueFactorFunction { Field = "x", Factor = 1.1, Missing = 0.1, Modifier = FieldValueFactorModifier.Ln }, diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc index 350006fefa9..8b1ec531a4b 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[indices-no-match-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc index 33f957a3d9f..49c5f5fe8ef 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[indices-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc index a8c2bc166fb..e2a4be7de4f 100644 --- a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[limit-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc index 5adf9ff6b3f..6b4eee5f44e 100644 --- a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[not-query-usage]] diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc index 445009593b4..14aae89dc50 100644 --- a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[or-query-usage]] diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc index 838a1270d4f..e2c8fe6b994 100644 --- a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[common-terms-usage]] diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc index f0e19a71af7..a156ccfe256 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[match-phrase-prefix-usage]] diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc index 2610ac4ada4..dd8e390cd11 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[match-phrase-usage]] diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc index ecc310194eb..8af0f92c08d 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[match-usage]] diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index fdace521fe7..bb01742e0eb 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[multi-match-usage]] @@ -91,7 +93,8 @@ new MultiMatchQuery ---- q .MultiMatch(c => c - .Fields(f => f.Field(p=>p.Description, 2.2).Field("myOtherField^0.3")) + //.Fields(f => f.Field(p=>p.Description, 2.2).Field("myOtherField^0.3")) + .Fields(Field(p=>p.Description, 2.2).And("myOtherField^0.3")) .Query("hello world") ) ---- diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc index da703d9af6f..e6dde3f8b94 100644 --- a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[query-string-usage]] diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc index 1bd88f2691e..f12b8d531ae 100644 --- a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[simple-query-string-usage]] diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc index 9479a4edb7c..efe5bbcbb06 100644 --- a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-bounding-box-query-usage]] diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc index 5a955ae340a..7e12f55372d 100644 --- a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-distance-range-query-usage]] diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc index 98bb57d3060..e92f71df069 100644 --- a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-distance-query-usage]] diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc index cad7398f97e..24b04a0d652 100644 --- a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-hash-cell-query-usage]] diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc index ed0ea98258d..140a59b156f 100644 --- a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[geo-polygon-query-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc index 58be9d7a7fd..76fe2be6538 100644 --- a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-shape-circle-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc index 82d2f37d48f..47d198fa1c0 100644 --- a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-envelope-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc index 4ec907dcaa7..447f86c7beb 100644 --- a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-indexed-shape-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc index 9e2ef3cc9c7..a960f4bdd71 100644 --- a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-line-string-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc index a451a70869b..2ec0cf02c1a 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-multi-line-string-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc index 3b46211d663..76e9b8c285e 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-multi-point-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc index 93a173ac826..3cb97776277 100644 --- a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-point-usage]] diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc index e7043835380..ee2f03c05ad 100644 --- a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../../images/ [[geo-polygon-usage]] diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc index 0a2be5e8663..5c655f0a92c 100644 --- a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[has-child-query-usage]] diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc index ecb7cfbc839..46eae8a05ef 100644 --- a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[has-parent-query-usage]] diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc index 2fc19d0286c..3615e980563 100644 --- a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[nested-query-usage]] diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc index 7e757b84cbe..99c46a0088e 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[raw-combine-usage]] diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc index bb86243202f..585b10f6dd8 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[raw-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc index 1ac458d4646..41d6747c3b6 100644 --- a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-containing-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc index af3b148cdbb..8214697f5be 100644 --- a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-first-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc index 6e298543839..4b365f3bef9 100644 --- a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-multi-term-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc index 9a7ede543ac..c783f45d8b8 100644 --- a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-near-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc index 6aa8f74b640..d6c458d5f96 100644 --- a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-not-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc index 968742e3af2..1f4fbb93312 100644 --- a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-or-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc index feaadab2811..3d2a60f2ce1 100644 --- a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-term-query-usage]] diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc index 4a0b1acf65b..4a33735dbdb 100644 --- a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[span-within-query-usage]] diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc index d897f2aff76..9c33308b5b5 100644 --- a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[more-like-this-query-usage]] diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc index 6eb03580099..1b79cf678d8 100644 --- a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[script-query-usage]] @@ -43,9 +45,11 @@ new ScriptQuery "script": { "_name": "named_query", "boost": 1.1, - "inline": "doc['num1'].value > param1", - "params": { - "param1": 1 + "script": { + "inline": "doc['num1'].value > param1", + "params": { + "param1": 1 + } } } } diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc index 41639a3ef99..2764d79f9ba 100644 --- a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[template-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc index ecd457d6b69..6d68bda89fd 100644 --- a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[exists-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc index 8ae64f6b8fc..34efcbc5cc7 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[fuzzy-date-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc index 6b5be0877c7..7f5456ab690 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[fuzzy-numeric-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc index 7072ac95b46..d63c21c67f5 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[fuzzy-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc index 4d38095c146..5595cc0a9cc 100644 --- a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[ids-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc index 00744f32413..3fb6978d2a7 100644 --- a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[missing-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc index 12385a142d5..51957a5cccc 100644 --- a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[prefix-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc index 1d7be7e1702..0719d56aa5e 100644 --- a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[date-range-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc index b205a8df690..d44488a6783 100644 --- a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[numeric-range-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc index 76ee62d518b..ec1caa8532b 100644 --- a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[term-range-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc index 55ea47a337b..3fcf9536a2c 100644 --- a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[regexp-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc index 95814a28b9a..c04e5c603ba 100644 --- a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[term-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc new file mode 100644 index 00000000000..2a175595558 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc @@ -0,0 +1,150 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:nuget: https://www.nuget.org/packages + +:imagesdir: ../../../images/ + +[[terms-list-query-usage]] +== Terms List Query Usage + +=== Fluent DSL Example + +[source,csharp] +---- +q +.Terms(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .DisableCoord() + .MinimumShouldMatch(MinimumShouldMatch.Fixed(2)) + .Terms(new List { "term1", "term2" }) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermsQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Terms = new List { "term1", "term2" }, + DisableCoord = true, + MinimumShouldMatch = 2 +} +---- + +[source,javascript] +.Example json output +---- +{ + "terms": { + "_name": "named_query", + "boost": 1.1, + "description": [ + "term1", + "term2" + ], + "disable_coord": true, + "minimum_should_match": 2 + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +q +.Terms(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .DisableCoord() + .Terms(_terms) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermsQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "description", + Terms = _terms, + DisableCoord = true, +} +---- + +[source,javascript] +.Example json output +---- +{ + "terms": { + "_name": "named_query", + "boost": 1.1, + "description": [ + [ + "term1", + "term2" + ] + ], + "disable_coord": true + } +} +---- + +=== Fluent DSL Example + +[source,csharp] +---- +q +.Terms(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.NumberOfCommits) + .DisableCoord() + .Terms(_terms) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp] +---- +new TermsQuery +{ + Name = "named_query", + Boost = 1.1, + Field = "numberOfCommits", + Terms = _terms, + DisableCoord = true, +} +---- + +[source,javascript] +.Example json output +---- +{ + "terms": { + "_name": "named_query", + "boost": 1.1, + "numberOfCommits": [ + [ + "term1", + "term2" + ] + ], + "disable_coord": true + } +} +---- + diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc index d1872500ccc..31eb25bead4 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[terms-lookup-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc index 4fb23152c66..baa9e848df9 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -2,11 +2,17 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[terms-query-usage]] == Terms Query Usage +Filters documents that have fields that match any of the provided terms (not analyzed). + +Be sure to read the Elasticsearch documentation on {ref_current}/query-dsl-terms-query.html[Terms query] for more information. + === Fluent DSL Example [source,csharp] @@ -31,7 +37,7 @@ new TermsQuery Name = "named_query", Boost = 1.1, Field = "description", - Terms = new [] { "term1", "term2" }, + Terms = ExpectedTerms, DisableCoord = true, MinimumShouldMatch = 2 } @@ -54,3 +60,22 @@ new TermsQuery } ---- +[[single-term-terms-query]] +[float] +== Single term Terms Query + +=== Fluent DSL Example + +[source,csharp] +---- +q +.Terms(c => c + .Name("named_query") + .Boost(1.1) + .Field(p => p.Description) + .DisableCoord() + .MinimumShouldMatch(MinimumShouldMatch.Fixed(2)) + .Terms("term1") +) +---- + diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc index 6cfb8816a66..e2b1301e1fc 100644 --- a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[type-query-usage]] diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc index b2bfa6ed973..6c375e0d0fe 100644 --- a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../../images/ [[wildcard-query-usage]] diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc index fdbe102da03..4f574058595 100644 --- a/docs/asciidoc/search/request/explain-usage.asciidoc +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[explain-usage]] diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index 8ec77e8b766..85baee860e7 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[fielddata-fields-usage]] diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index 44cd2a1a51f..94323e1affb 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[fields-usage]] diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index ddeef4f585c..0bf9d99c658 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[from-and-size-usage]] diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index 9220f1b1c97..7b0419975ef 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[highlighting-usage]] diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index 1f84cbfb1c0..a810de773d1 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[index-boost-usage]] diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc index b6e3210f360..d3c6cb424cb 100644 --- a/docs/asciidoc/search/request/inner-hits-usage.asciidoc +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[inner-hits-usage]] diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index e0ef7c85657..6e00e307375 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[min-score-usage]] diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index 2a7d48dd579..56d90489302 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[post-filter-usage]] diff --git a/docs/asciidoc/search/request/profile-usage.asciidoc b/docs/asciidoc/search/request/profile-usage.asciidoc index a5a4340afe5..63a9486b471 100644 --- a/docs/asciidoc/search/request/profile-usage.asciidoc +++ b/docs/asciidoc/search/request/profile-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[profile-usage]] diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index 8e614cb9645..6e952a8b284 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[query-usage]] diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index 8fed749f668..719c8cd7ae5 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[script-fields-usage]] diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 11d5fee7ae2..1416b67100b 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[sort-usage]] diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index 8adcebf9841..472eceb4929 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[source-filtering-usage]] diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index 51ed1b0831a..ed7255d73d1 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[suggest-usage]] diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index 4c911d5696c..072ff19b334 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -2,6 +2,8 @@ :github: https://github.com/elastic/elasticsearch-net +:nuget: https://www.nuget.org/packages + :imagesdir: ../../images/ [[suggest-api]] diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs index ee1a054defd..1e168b094d9 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/GeneratedAsciidocVisitor.cs @@ -11,7 +11,7 @@ namespace Nest.Litterateur.AsciiDoc { /// - /// Visits the "raw" asciidoc generated using Roslyn and adds attribute entries, + /// Visits the "raw" asciidoc generated using Roslyn and adds attribute entries, /// section titles, rearranges sections, etc. /// public class GeneratedAsciidocVisitor : NoopVisitor @@ -61,6 +61,11 @@ public override void Visit(Document document) _newDocument.Attributes.Add(new AttributeEntry("github", "https://github.com/elastic/elasticsearch-net")); } + if (!document.Attributes.Any(a => a.Name == "nuget")) + { + _newDocument.Attributes.Add(new AttributeEntry("nuget", "https://www.nuget.org/packages")); + } + if (!document.Attributes.Any(a => a.Name == "imagesdir")) { var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; @@ -103,7 +108,7 @@ public override void Visit(IList elements) { var element = elements[index]; var source = element as Source; - + if (source != null) { // remove empty source blocks @@ -119,8 +124,8 @@ public override void Visit(IList elements) continue; } - if ((method.Value == "expectjson" || method.Value == "queryjson") && - source.Attributes.Count > 1 && + if ((method.Value == "expectjson" || method.Value == "queryjson") && + source.Attributes.Count > 1 && source.Attributes[1].Name == "javascript") { exampleJson = source; @@ -153,7 +158,7 @@ public override void Visit(IList elements) _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); _newDocument.Elements.Add(objectInitializerExample); objectInitializerExample = null; - + if (exampleJson != null) { _newDocument.Elements.Add(exampleJson); @@ -176,7 +181,7 @@ public override void Visit(IList elements) { _newDocument.Elements.Add(new SectionTitle("Object Initializer Syntax Example", 3)); _newDocument.Elements.Add(objectInitializerExample); - + // Move the example json to after the initializer example if (exampleJson != null) { @@ -210,14 +215,14 @@ public override void Visit(IList elements) public override void Visit(Source source) { - if (source.Attributes.Count > 1 && + if (source.Attributes.Count > 1 && source.Attributes[1].Name == "javascript" && !source.Attributes.HasTitle) { source.Attributes.Add(new Title("Example json output")); } - // remove method attributes as the elastic doc generation doesn't like them; it + // remove method attributes as the elastic doc generation doesn't like them; it // expects a linenumbering in the index 2 position of a source block var methodAttribute = source.Attributes.FirstOrDefault(a => a.Name == "method"); if (methodAttribute != null) @@ -225,7 +230,7 @@ public override void Visit(Source source) source.Attributes.Remove(methodAttribute); } - // Replace tabs with spaces and remove comment escaping from output + // Replace tabs with spaces and remove comment escaping from output // (elastic docs generation does not like this callout format) source.Text = Regex.Replace(source.Text.Replace("\t", " "), @"//[ \t]*\<(\d+)\>.*", "<$1>"); diff --git a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs index cf02728dd45..ea279952f55 100644 --- a/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs +++ b/src/CodeGeneration/Nest.Litterateur/StringExtensions.cs @@ -70,7 +70,7 @@ public static string RemoveLeadingSpacesAndAsterisk(this string input) } public static string RemoveNumberOfLeadingTabsAfterNewline(this string input, int numberOfTabs) - { + { var firstTab = input.IndexOf("\t", StringComparison.OrdinalIgnoreCase); if (firstTab == -1) @@ -94,14 +94,14 @@ public static string RemoveNumberOfLeadingTabsAfterNewline(this string input, in { numberOfTabs = count; } - + return Regex.Replace( Regex.Replace( - input, - $"(?[\n|\r\n]+\t{{{numberOfTabs}}})", + input, + $"(?[\n|\r\n]+\t{{{numberOfTabs}}})", m => m.Value.Replace("\t", string.Empty) ), - $"(?[\n|\r\n]+\\s{{{numberOfTabs * 4}}})", + $"(?[\n|\r\n]+\\s{{{numberOfTabs * 4}}})", m => m.Value.Replace(" ", string.Empty) ); } @@ -112,8 +112,8 @@ public static string[] SplitOnNewLines(this string input, StringSplitOptions opt } #if !DOTNETCORE - // TODO: Hack of replacements for now. Resolved by referencing tests assembly when building compilation unit, but might - // want to put doc generation at same directory level as Tests to reference project directly. + // TODO: Hack of replacements in anonymous types that represent json. This can be resolved by referencing tests assembly when building the dynamic assembly, + // but might want to put doc generation at same directory level as Tests to reference project directly. private static Dictionary Substitutions = new Dictionary { { "FixedDate", "new DateTime(2015, 06, 06, 12, 01, 02, 123)" }, @@ -125,8 +125,10 @@ public static string[] SplitOnNewLines(this string input, StringSplitOptions opt "new { gender = \"Male\", id = 0, firstName = \"Martijn\", lastName = \"Laarman\" }," + "location = new { lat = 42.1523, lon = -80.321 }}" }, { "_templateString", "\"{ \\\"match\\\": { \\\"text\\\": \\\"{{query_string}}\\\" } }\"" }, - { "base.QueryJson", "new{ @bool = new { must = new[] { new { match_all = new { } } }, must_not = new[] { new { match_all = new { } } }, should = new[] { new { match_all = new { } } }, filter = new[] { new { match_all = new { } } }, minimum_should_match = 1, boost = 2.0, } }" } - }; + { "base.QueryJson", "new{ @bool = new { must = new[] { new { match_all = new { } } }, must_not = new[] { new { match_all = new { } } }, should = new[] { new { match_all = new { } } }, filter = new[] { new { match_all = new { } } }, minimum_should_match = 1, boost = 2.0, } }" }, + { "ExpectedTerms", "new [] { \"term1\", \"term2\" }" }, + { "_ctxNumberofCommits", "\"_source.numberOfCommits > 0\"" } + }; public static bool TryGetJsonForAnonymousType(this string anonymousTypeString, out string json) { @@ -140,14 +142,14 @@ public static bool TryGetJsonForAnonymousType(this string anonymousTypeString, o var text = $@" using System; - using System.Collections.Generic; + using System.Collections.Generic; using System.ComponentModel; - using Newtonsoft.Json; + using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Temporary {{ - public class Json + public class Json {{ public string Write() {{ @@ -165,7 +167,7 @@ public string Write() MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(JsonConvert).GetTypeInfo().Assembly.Location), - MetadataReference.CreateFromFile(typeof(ITypedList).GetTypeInfo().Assembly.Location), + MetadataReference.CreateFromFile(typeof(ITypedList).GetTypeInfo().Assembly.Location), }; var compilation = @@ -214,4 +216,4 @@ public string Write() } #endif } -} \ No newline at end of file +} diff --git a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs index fd337f23cf4..15d0731c5ea 100644 --- a/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs +++ b/src/Tests/Aggregations/Bucket/Filter/FilterAggregationUsageTests.cs @@ -68,7 +68,7 @@ public FilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : bas protected override void ExpectResponse(ISearchResponse response) { /** === Handling Responses - * Using the `.Aggs` aggregation helper we can fetch our aggregation results easily + * Using the `.Aggs` aggregation helper we can fetch our aggregation results easily * in the correct type. <> */ response.IsValid.Should().BeTrue(); @@ -81,8 +81,8 @@ protected override void ExpectResponse(ISearchResponse response) tags.Buckets.Should().NotBeEmpty(); } } - - /**[float] + + /**[float] * == Empty Filter * When the collection of filters is empty or all are conditionless, NEST will serialize them * to an empty object. @@ -129,10 +129,13 @@ protected override void ExpectResponse(ISearchResponse response) } } + /**[float] + * == Inline Script Filter + */ //reproduce of https://github.com/elastic/elasticsearch-net/issues/1931 public class InlineScriptFilterAggregationUsageTests : AggregationUsageTestBase { - private string _ctxNumberofcommits = "_source.numberOfCommits > 0"; + private string _ctxNumberofCommits = "_source.numberOfCommits > 0"; private string _aggName = "script_filter"; public InlineScriptFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } @@ -144,7 +147,7 @@ public InlineScriptFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage filter = new { script = new { script = new { - inline = _ctxNumberofcommits + inline = _ctxNumberofCommits } } } @@ -157,7 +160,7 @@ public InlineScriptFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage .Filter(_aggName, date => date .Filter(f => f .Script(b => b - .Inline(_ctxNumberofcommits) + .Inline(_ctxNumberofCommits) ) ) ) @@ -170,7 +173,7 @@ public InlineScriptFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage { Filter = new ScriptQuery { - Inline = _ctxNumberofcommits + Inline = _ctxNumberofCommits } } }; diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs index 524f9d7b2ec..476cacc948b 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/ConnectionPooling.Doc.cs @@ -9,7 +9,7 @@ namespace Tests.ClientConcepts.ConnectionPooling.BuildingBlocks { public class ConnectionPooling { - /** == Connection Pooling + /**== Connection Pooling * Connection pooling is the internal mechanism that takes care of registering what nodes there are in the cluster and which * NEST can use to issue client calls on. There are 3 types of connection pool * diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs index d22f4cc0f61..359df954292 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/Transports.Doc.cs @@ -23,11 +23,11 @@ public async Task InterfaceExplained() * Transport is generically typed to a type that implements `IConnectionConfigurationValues` * This is the minimum `ITransport` needs to report back for the client to function. * - * e.g in the low level client, transport is instantiated like this: + * e.g in the low level client, Elasticsearch.Net, transport is instantiated like this: */ var lowLevelTransport = new Transport(new ConnectionConfiguration()); - /** and in the high level client, like this: */ + /** and in the high level client, NEST, like this: */ var highlevelTransport = new Transport(new ConnectionSettings()); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); @@ -39,7 +39,10 @@ public async Task InterfaceExplained() * If you feel this need, {github}/issues[please let us know] as we'd love to learn why you've go down this route! */ var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); - response = await inMemoryTransport.RequestAsync>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); + response = await inMemoryTransport.RequestAsync>( + HttpMethod.GET, + "/_search", + new { query = new { match_all = new { } } }); } } } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs index 54770bc14d9..c07486835fd 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Pinging/FirstUsage.doc.cs @@ -11,18 +11,18 @@ namespace Tests.ClientConcepts.ConnectionPooling.Pinging { public class FirstUsage { - /** :section-number: 5.1 + /** :section-number: 5.1 * == Pinging - First Usage - * - * Pinging is enabled by default for the Static & Sniffing connection pool. - * This means that the first time a node is used or resurrected we issue a ping with a smaller (configurable) timeout. - * This allows us to fail and fallover to a healthy node faster + * + * Pinging is enabled by default for the <> and <> connection pools. + * This means that the first time a node is used or resurrected, a ping is issued a with a small (configurable) timeout, + * allowing the client to fail and fallover to a healthy node much faster than attempting a request that may be heavier than a ping. */ [U, SuppressMessage("AsyncUsage", "AsyncFixer001:Unnecessary async/await usage", Justification = "Its a test")] public async Task PingFailsFallsOverToHealthyNodeWithoutPing() { - /** A cluster with 2 nodes where the second node fails on ping */ + /** Here's an example with a cluster with 2 nodes where the second node fails on ping */ var audit = new Auditor(() => Framework.Cluster .Nodes(2) .Ping(p => p.Succeeds(Always)) @@ -31,9 +31,15 @@ public async Task PingFailsFallsOverToHealthyNodeWithoutPing() .AllDefaults() ); + /** When making the calls, the first call goes to 9200 which succeeds, + * and the 2nd call does a ping on 9201 because it's used for the first time. + * The ping fails so we wrap over to node 9200 which we've already pinged. + * + * Finally we assert that the connectionpool has one node that is marked as dead + */ await audit.TraceCalls( - /** The first call goes to 9200 which succeeds */ - new ClientCall { + + new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200}, { pool => @@ -41,12 +47,9 @@ await audit.TraceCalls( pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); } } }, - /** The 2nd call does a ping on 9201 because its used for the first time. - * It fails so we wrap over to node 9200 which we've already pinged */ - new ClientCall { + new ClientCall { { PingFailure, 9201}, { HealthyResponse, 9200}, - /** Finally we assert that the connectionpool has one node that is marked as dead */ { pool => pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(1) } } ); @@ -66,7 +69,7 @@ public async Task PingFailsFallsOverMultipleTimesToHealthyNode() await audit.TraceCalls( /** The first call goes to 9200 which succeeds */ - new ClientCall { + new ClientCall { { PingSuccess, 9200}, { HealthyResponse, 9200}, { pool => @@ -74,10 +77,10 @@ await audit.TraceCalls( pool.Nodes.Where(n=>!n.IsAlive).Should().HaveCount(0); } } }, - /** The 2nd call does a ping on 9201 because its used for the first time. - * It fails and so we ping 9202 which also fails. We then ping 9203 becuase + /** The 2nd call does a ping on 9201 because its used for the first time. + * It fails and so we ping 9202 which also fails. We then ping 9203 becuase * we haven't used it before and it succeeds */ - new ClientCall { + new ClientCall { { PingFailure, 9201}, { PingFailure, 9202}, { PingSuccess, 9203}, @@ -90,7 +93,7 @@ await audit.TraceCalls( [U, SuppressMessage("AsyncUsage", "AsyncFixer001:Unnecessary async/await usage", Justification = "Its a test")] public async Task AllNodesArePingedOnlyOnFirstUseProvidedTheyAreHealthy() { - /** A healthy cluster of 4 (min master nodes of 3 of course!) */ + /**A healthy cluster of 4 (min master nodes of 3 of course!) */ var audit = new Auditor(() => Framework.Cluster .Nodes(4) .Ping(p => p.SucceedAlways()) diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs index cffe9ca5d13..cd9110ef09e 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/FieldInference.doc.cs @@ -21,7 +21,7 @@ public class FieldInferrence { /**== Field Inference * - * Several places in the elasticsearch API expect the path to a field from your original source document as a string. + * Several places in the Elasticsearch API expect the path to a field from your original source document as a string. * NEST allows you to use C# expressions to strongly type these field path strings. * * These expressions are assigned to a type called `Field` and there are several ways to create an instance of one: diff --git a/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs b/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs index 5166cc6b979..db607fd075e 100644 --- a/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Inference/IndexNameInference.doc.cs @@ -12,8 +12,20 @@ namespace Tests.ClientConcepts.HighLevel.Inference { + /**[[index-name-inference]] + *== Index Name Inference + * + * Many endpoints within the Elasticsearch API expect to receive one or more index names + * as part of the request in order to know what index/indices a request should operate on. + * + * NEST has a number of ways in which an index name can be specified + */ public class IndexNameInference { + /**=== Default Index name on ConnectionSettings + * A default index name can be specified on `ConnectionSettings` usinf `.DefaultIndex()`. + * This is the default index name to use when no other index name can be resolved for a request + */ [U] public void DefaultIndexIsInferred() { @@ -24,6 +36,9 @@ public void DefaultIndexIsInferred() index.Should().Be("defaultindex"); } + /**=== Mapping an Index name for POCOs + * A index name can be mapped for CLR types using `.MapDefaultTypeIndices()` on `ConnectionSettings`. + */ [U] public void ExplicitMappingIsInferred() { @@ -36,6 +51,10 @@ public void ExplicitMappingIsInferred() index.Should().Be("projects"); } + /**=== Mapping an Index name for POCOs + * An index name for a POCO provided using `.MapDefaultTypeIndices()` **will take precedence** over + * the default index name + */ [U] public void ExplicitMappingTakesPrecedence() { @@ -49,9 +68,57 @@ public void ExplicitMappingTakesPrecedence() index.Should().Be("projects"); } + /**=== Explicitly specifying Index name on the request + * For API calls that expect an index name, the index name can be explicitly provided + * on the request + */ + [U] + public void ExplicitIndexOnRequest() + { + Uri requestUri = null; + var client = TestClient.GetInMemoryClient(s => s + .OnRequestCompleted(r => { requestUri = r.Uri; })); + + var response = client.Search(s => s.Index("some-other-index")); //<1> Provide the index name on the request + + requestUri.Should().NotBeNull(); + requestUri.LocalPath.Should().StartWith("/some-other-index/"); + } + + /** When an index name is provided on a request, it **will take precedence** over the default + * index name and any index name specified for the POCO type using `.MapDefaultTypeIndices()` + */ + [U] + public void ExplicitIndexOnRequestTakesPrecedence() + { + var client = TestClient.GetInMemoryClient(s => + new ConnectionSettings() + .DefaultIndex("defaultindex") + .MapDefaultTypeIndices(m => m + .Add(typeof(Project), "projects") + ) + ); + + var response = client.Search(s => s.Index("some-other-index")); //<1> Provide the index name on the request + + response.ApiCall.Uri.Should().NotBeNull(); + response.ApiCall.Uri.LocalPath.Should().StartWith("/some-other-index/"); + } + + /**=== Naming Conventions + * Index names within Elasticsearch cannot contain upper case letters. + * NEST will check the index name at the point at which the index + * name needs to be resolved to make a request; if the index name contains + * upper case letters, a `ResolveException` will be thrown indicating + * the problem and the index name that caused the problem. + */ [U] public void UppercaseCharacterThrowsResolveException() { + /** + * In the following example, we create a connection settings withboth a default index + * name and an index name to use for the `Project` type. + */ var settings = new ConnectionSettings() .DefaultIndex("Default") .MapDefaultTypeIndices(m => m @@ -60,14 +127,36 @@ public void UppercaseCharacterThrowsResolveException() var resolver = new IndexNameResolver(settings); + /** When resolving the index name for the `Project` type, a `ResolveException` + * is thrown, indicating that the index name "__myProjects__" contains upper case letters + */ var e = Assert.Throws(() => resolver.Resolve()); e.Message.Should().Be($"Index names cannot contain uppercase characters: myProjects."); + + /** + * Similarly, when resolving the index name for the `Tag` type, which will use the default index + * name, a `ResolveException` is thrown indicating that the default index name contains upper case + * letters + */ e = Assert.Throws(() => resolver.Resolve()); e.Message.Should().Be($"Index names cannot contain uppercase characters: Default."); + + /** + * Finally, when resolving an index name from a string, a `ResolveException` will be thrown + * if the string contains upper case letters + */ e = Assert.Throws(() => resolver.Resolve("Foo")); e.Message.Should().Be($"Index names cannot contain uppercase characters: Foo."); } + /** If no index name can be resolved for a request i.e. if + * + * - no default index name is set on connection settings + * - no index name is mapped for a POCO + * - no index name is explicitly specified on the request + * + * then a `ResolveException` will be thrown to indicate that the index name is `null` + */ [U] public void NoIndexThrowsResolveException() { @@ -77,12 +166,16 @@ public void NoIndexThrowsResolveException() e.Message.Should().Contain("Index name is null"); } + /** + * ``ResolveException``s bubble out of the client and should be dealt with as <> + * similar to `ArgumentException`, `ArgumentOutOfRangeException` and other exceptions that _usually_ indicate + * misuse of the client API + */ [U] public void ResolveExceptionBubblesOut() { var client = TestClient.GetInMemoryClient(s => new ConnectionSettings()); var e = Assert.Throws(() => client.Search()); - } } } diff --git a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs index c3b09554b5f..8e4a2318793 100644 --- a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs @@ -28,7 +28,7 @@ public void InstantiateUsingAllDefaults() var client = new ElasticLowLevelClient(); } /** - * If your Elasticsearch node does not live at `http://localhost:9200` but i.e `http://mynode.example.com:8082/apiKey`, then + * If your Elasticsearch node does not live at `http://localhost:9200` but instead lives somewhere else, for example, `http://mynode.example.com:8082/apiKey`, then * you will need to pass in some instance of `IConnectionConfigurationValues`. * * The easiest way to do this is: @@ -44,7 +44,7 @@ public void InstantiatingASingleNodeClient() /** * This will still be a non-failover connection, meaning if that `node` goes down the operation will not be retried on any other nodes in the cluster. * - * To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. + * To get a failover connection we have to pass an <> instance instead of a `Uri`. */ public void InstantiatingAConnectionPoolClient() { @@ -55,12 +55,13 @@ public void InstantiatingAConnectionPoolClient() } /** - * Here instead of directly passing `node`, we pass a `SniffingConnectionPool` which will use our `node` to find out the rest of the available cluster nodes. + * Here instead of directly passing `node`, we pass a <> + * which will use our `node` to find out the rest of the available cluster nodes. * Be sure to read more about <>. * * === Configuration Options * - * Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: + *Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: */ public void SpecifyingClientOptions() @@ -69,9 +70,9 @@ public void SpecifyingClientOptions() var connectionPool = new SniffingConnectionPool(new[] { node }); var config = new ConnectionConfiguration(connectionPool) - .DisableDirectStreaming() - .BasicAuthentication("user", "pass") - .RequestTimeout(TimeSpan.FromSeconds(5)); + .DisableDirectStreaming() //<1> Additional options + .BasicAuthentication("user", "pass") //<1> + .RequestTimeout(TimeSpan.FromSeconds(5)); //<1> } /** * The following is a list of available connection configuration options: @@ -104,33 +105,35 @@ public void AvailableOptions() .ThrowExceptions() // <4> As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to <>. .PrettyJson() // <5> forces all serialization to be indented and appends `pretty=true` to all the requests so that the responses are indented as well .BasicAuthentication("username", "password"); // <6> sets the HTTP basic authentication credentials to specify with all requests. - /** - * NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: - */ + + /** + * NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: + */ var uri = new Uri("http://username:password@localhost:9200"); var settings = new ConnectionConfiguration(uri); - /** + /** *...but this may become tedious when using connection pooling with multiple nodes. - * + * * [[thrown-exceptions]] * === Exceptions * There are three category of exceptions that may be thrown: - * - * . `ElasticsearchClientException`: These are known exceptions, either an exception that occurred in the request pipeline - * (such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could - * not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property - * on the response will contain the the actual error that was returned. The inner exception will always contain the - * root causing exception. - * - * . `UnexpectedElasticsearchClientException`: These are unknown exceptions, for instance a response from Elasticsearch not + * + * `ElasticsearchClientException`:: These are known exceptions, either an exception that occurred in the request pipeline + * (such as max retries or timeout reached, bad authentication, etc...) or Elasticsearch itself returned an error (could + * not parse the request, bad query, missing field, etc...). If it is an Elasticsearch error, the `ServerError` property + * on the response will contain the the actual error that was returned. The inner exception will always contain the + * root causing exception. + * + * `UnexpectedElasticsearchClientException`:: These are unknown exceptions, for instance a response from Elasticsearch not * properly deserialized. These are usually bugs and {github}/issues[should be reported]. This exception also inherits from `ElasticsearchClientException` - * so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. - * - * . Development time exceptions: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException` etc... that are thrown - * when an API in the client is misused. These should not be handled as you want to know about them during development. - * - */ + * so an additional catch block isn't necessary, but can be helpful in distinguishing between the two. + * + * Development time exceptions:: These are CLR exceptions like `ArgumentException`, `ArgumentOutOfRangeException`, etc. and other exceptions like + * `ResolveException` that are thrown when an API in the client is misused. + * These should not be handled as you want to know about them during development. + * + */ } /** === OnRequestCompleted @@ -151,6 +154,9 @@ public void OnRequestCompletedIsCalled() counter.Should().Be(2); } + /** + *`OnRequestCompleted` is called even when an exception is thrown + */ [U] public void OnRequestCompletedIsCalledWhenExceptionIsThrown() { @@ -167,20 +173,19 @@ public void OnRequestCompletedIsCalledWhenExceptionIsThrown() /** [[complex-logging]] * Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like - * to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` - * to `true` + * to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` */ [U]public async Task UsingOnRequestCompletedForLogging() { var list = new List(); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); - var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) // <1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` to make the actual request + var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) // <1> Here we use `InMemoryConnection`; in reality you would use another type of `IConnection` that actually makes a request. .DefaultIndex("default-index") .DisableDirectStreaming() .OnRequestCompleted(response => { - // log out the request + // log out the request and the request body, if available if (response.RequestBodyInBytes != null) { list.Add( @@ -192,7 +197,7 @@ [U]public async Task UsingOnRequestCompletedForLogging() list.Add($"{response.HttpMethod} {response.Uri}"); } - // log out the response + // log out the response and the response body, if available if (response.ResponseBodyInBytes != null) { list.Add($"Status: {response.HttpStatusCode}\n" + @@ -252,7 +257,7 @@ public void ConfiguringSSL() */ #if !DOTNETCORE - ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; + ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; //<1> NOTE: This does not work on **Core CLR** as the request does not go through `ServicePointManager`; please file an {github}/issues[issue] if you need support for validation on Core CLR. #endif /** * However, this will accept **all** requests from the AppDomain to untrusted SSL sites, @@ -260,18 +265,15 @@ public void ConfiguringSSL() */ } - /** - * === Overriding default Json.NET behavior + /**=== Overriding default Json.NET behavior * - * Please be advised that this is an expert behavior but if you need to get to the nitty gritty this can be really useful - * - * Create a subclass of the `JsonNetSerializer` + * Overriding the default Json.NET behaviour in NEST is an expert behavior but if you need to get to the nitty gritty, this can be really useful. + * First, create a subclass of the `JsonNetSerializer` */ public class MyJsonNetSerializer : JsonNetSerializer { public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) { } - /** * Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSettings` */ @@ -280,7 +282,7 @@ public MyJsonNetSerializer(IConnectionSettingsValues settings) : base(settings) /** * You can inject contract resolved converters by implementing the ContractConverters property - * This can be much faster then registering them on JsonSerializerSettings.Converters + * This can be much faster then registering them on `JsonSerializerSettings.Converters` */ public int CallToContractConverter { get; set; } = 0; protected override IList> ContractConverters => new List> diff --git a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs index d10fa231fba..58852072c81 100644 --- a/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Lifetimes.doc.cs @@ -26,9 +26,9 @@ public class Lifetimes * In some applications it could make perfect sense to have multiple singleton `ElasticClient`'s registered with different * connection settings. e.g if you have 2 functionally isolated Elasticsearch clusters. * - * NOTE: Due to the semantic versioning of NEST and the alignment of versions to Elasticsearch, all instances of `ElasticClient` and thus - * Elasticsearch that are connected to must be on the same major version i.e. it is not possible to have both an `ElasticClient` to connect to - * Elasticsearch 1.x and 2.x in the same application as the former would require NEST 1.x and the latter, NEST 2.x. + * NOTE: Due to the semantic versioning of Elasticsearch.Net and NEST and their alignment to versions of Elasticsearch, all instances of `ElasticClient` and + * Elasticsearch clusters that are connected to must be on the **same major version** i.e. it is not possible to have both an `ElasticClient` to connect to + * Elasticsearch 1.x _and_ 2.x in the same application as the former would require NEST 1.x and the latter, NEST 2.x. * * Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types */ diff --git a/src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs b/src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs index 3e73b56ccec..1e021fc6a4c 100644 --- a/src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs +++ b/src/Tests/CommonOptions/DistanceUnit/DistanceUnits.doc.cs @@ -1,15 +1,16 @@ -using Tests.Framework; +using Nest; +using Tests.Framework; using static Tests.Framework.RoundTripper; namespace Tests.CommonOptions.DistanceUnit { public class DistanceUnits { - /** == Distance Units - * Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], - * the distance unit can be specified as a double number representing distance in meters, as a new instance of + /**== Distance Units + * Whenever distances need to be specified, e.g. for a {ref_current}/query-dsl-geo-distance-query.html[geo distance query], + * the distance unit can be specified as a double number representing distance in meters, as a new instance of * a `Distance`, or as a string of the form number and distance unit e.g. "`2.72km`" - * + * * === Using Distance units in NEST * NEST uses `Distance` to strongly type distance units and there are several ways to construct one. * @@ -19,11 +20,11 @@ public class DistanceUnits [U] public void Constructor() { - var unitComposed = new Nest.Distance(25); - var unitComposedWithUnits = new Nest.Distance(25, Nest.DistanceUnit.Meters); + var unitComposed = new Distance(25); + var unitComposedWithUnits = new Distance(25, Nest.DistanceUnit.Meters); /** - * `Distance` serializes to a string composed of a factor and distance unit. + * `Distance` serializes to a string composed of a factor and distance unit. * The factor is a double so always has at least one decimal place when serialized */ Expect("25.0m") @@ -33,16 +34,16 @@ public void Constructor() /** * ==== Implicit conversion - * Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. + * Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. * If no `DistanceUnit` is specified, the default distance unit is meters */ [U] public void ImplicitConversion() { - Nest.Distance distanceString = "25"; - Nest.Distance distanceStringWithUnits = "25m"; + Distance distanceString = "25"; + Distance distanceStringWithUnits = "25m"; - Expect(new Nest.Distance(25)) + Expect(new Distance(25)) .WhenSerializing(distanceString) .WhenSerializing(distanceStringWithUnits); } @@ -57,47 +58,47 @@ public void UsingDifferentUnits() /** ===== Metric *`mm` (Millimeters) */ - Expect("2.0mm").WhenSerializing(new Nest.Distance(2, Nest.DistanceUnit.Millimeters)); + Expect("2.0mm").WhenSerializing(new Distance(2, Nest.DistanceUnit.Millimeters)); /** *`cm` (Centimeters) */ - Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, Nest.DistanceUnit.Centimeters)); + Expect("123.456cm").WhenSerializing(new Distance(123.456, Nest.DistanceUnit.Centimeters)); /** *`m` (Meters) */ - Expect("400.0m").WhenSerializing(new Nest.Distance(400, Nest.DistanceUnit.Meters)); + Expect("400.0m").WhenSerializing(new Distance(400, Nest.DistanceUnit.Meters)); /** *`km` (Kilometers) */ - Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, Nest.DistanceUnit.Kilometers)); + Expect("0.1km").WhenSerializing(new Distance(0.1, Nest.DistanceUnit.Kilometers)); /** ===== Imperial *`in` (Inches) */ - Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, Nest.DistanceUnit.Inch)); + Expect("43.23in").WhenSerializing(new Distance(43.23, Nest.DistanceUnit.Inch)); /** *`ft` (Feet) */ - Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, Nest.DistanceUnit.Feet)); + Expect("3.33ft").WhenSerializing(new Distance(3.33, Nest.DistanceUnit.Feet)); /** *`yd` (Yards) */ - Expect("9.0yd").WhenSerializing(new Nest.Distance(9, Nest.DistanceUnit.Yards)); + Expect("9.0yd").WhenSerializing(new Distance(9, Nest.DistanceUnit.Yards)); /** *`mi` (Miles) */ - Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, Nest.DistanceUnit.Miles)); + Expect("0.62mi").WhenSerializing(new Distance(0.62, Nest.DistanceUnit.Miles)); /** *`nmi` or `NM` (Nautical Miles) */ - Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, Nest.DistanceUnit.NauticalMiles)); + Expect("45.5nmi").WhenSerializing(new Distance(45.5, Nest.DistanceUnit.NauticalMiles)); } } -} \ No newline at end of file +} diff --git a/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs b/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs index a5f1ce29c09..8e6d1cec232 100644 --- a/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs +++ b/src/Tests/CommonOptions/TimeUnit/TimeUnits.doc.cs @@ -7,12 +7,12 @@ namespace Tests.CommonOptions.TimeUnit { - public class TimeUnits + public class TimeUnits { - /** == Time units - * Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified - * as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. - * + /** == Time units + * Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified + * as a whole number representing time in milliseconds, or as a time value like `2d` for 2 days. + * * === Using Time units in NEST * NEST uses `Time` to strongly type this and there are several ways to construct one. * @@ -27,11 +27,11 @@ [U] public void Constructor() var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2); /** - * When serializing Time constructed from - * - a string - * - milliseconds (as a double) + * When serializing Time constructed from + * - a string + * - milliseconds (as a double) * - composition of factor and interval - * - a `TimeSpan` + * - a `TimeSpan` * * the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` */ @@ -51,7 +51,7 @@ [U] public void Constructor() } /** * ==== Implicit conversion - * Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` + * Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` */ [U] [SuppressMessage("ReSharper", "SuggestVarOrType_SimpleTypes")] public void ImplicitConversion() @@ -92,12 +92,12 @@ public void EqualityAndComparable() (oneAndHalfYear > twoWeeks).Should().BeTrue(); (oneAndHalfYear >= twoWeeks).Should().BeTrue(); (twoDays >= new Time("2d")).Should().BeTrue(); - + twoDays.Should().BeLessThan(twoWeeks); (twoDays < twoWeeks).Should().BeTrue(); (twoDays <= twoWeeks).Should().BeTrue(); (twoDays <= new Time("2d")).Should().BeTrue(); - + /** * And assert equality */ diff --git a/src/Tests/QueryDsl/TermLevel/Terms/TermsQueryUsageTests.cs b/src/Tests/QueryDsl/TermLevel/Terms/TermsQueryUsageTests.cs index 1984fba674b..32ed0aad48f 100644 --- a/src/Tests/QueryDsl/TermLevel/Terms/TermsQueryUsageTests.cs +++ b/src/Tests/QueryDsl/TermLevel/Terms/TermsQueryUsageTests.cs @@ -6,6 +6,11 @@ namespace Tests.QueryDsl.TermLevel.Terms { + /** + * Filters documents that have fields that match any of the provided terms (not analyzed). + * + * Be sure to read the Elasticsearch documentation on {ref_current}/query-dsl-terms-query.html[Terms query] for more information. + */ public class TermsQueryUsageTests : QueryDslUsageTestsBase { protected virtual string[] ExpectedTerms => new [] { "term1", "term2" }; @@ -53,6 +58,9 @@ protected override QueryContainer QueryFluent(QueryContainerDescriptor }; } + /**[float] + *== Single term Terms Query + */ public class SingleTermTermsQueryUsageTests : TermsQueryUsageTests { protected override string[] ExpectedTerms => new [] { "term1" }; diff --git a/src/Tests/common-options.asciidoc b/src/Tests/common-options.asciidoc index 5e99213dd2a..0da6edff8b3 100644 --- a/src/Tests/common-options.asciidoc +++ b/src/Tests/common-options.asciidoc @@ -5,7 +5,12 @@ [partintro] -- -Something about the convenience types for working with time and distance units and date math expressions +NEST has a number of types for working with Elasticsearch conventions for: + +- <> +- <> +- <> + -- include::{output-dir}/time-unit/time-units.asciidoc[] diff --git a/src/Tests/high-level.asciidoc b/src/Tests/high-level.asciidoc index 538b8230d3e..ce41681823f 100644 --- a/src/Tests/high-level.asciidoc +++ b/src/Tests/high-level.asciidoc @@ -1,7 +1,7 @@ :output-dir: client-concepts/high-level [[nest]] -= Client Concepts - High Level += Client Concepts - NEST [partintro] -- @@ -21,10 +21,11 @@ the `.LowLevel` property on `ElasticClient`. There are a number of conventions that NEST uses for inference of +- <> +- <> - <> and <> - <> - <> -- <> - <> In addition to features such as @@ -34,6 +35,10 @@ In addition to features such as -- +include::{output-dir}/inference/index-name-inference.asciidoc[] + +include::{output-dir}/inference/indices-paths.asciidoc[] + include::{output-dir}/inference/field-inference.asciidoc[] include::{output-dir}/inference/property-inference.asciidoc[] @@ -42,16 +47,12 @@ include::{output-dir}/inference/ids-inference.asciidoc[] include::{output-dir}/inference/document-paths.asciidoc[] -include::{output-dir}/inference/indices-paths.asciidoc[] - include::{output-dir}/inference/features-inference.asciidoc[] include::{output-dir}/mapping/auto-map.asciidoc[] include::{output-dir}/covariant-hits/covariant-search-results.asciidoc[] -include::connection-pooling.asciidoc[] - diff --git a/src/Tests/low-level.asciidoc b/src/Tests/low-level.asciidoc index 14ca78883e9..e4a56b277e5 100644 --- a/src/Tests/low-level.asciidoc +++ b/src/Tests/low-level.asciidoc @@ -1,7 +1,7 @@ :output-dir: client-concepts/low-level [[elasticsearch-net]] -= Client Concepts - Low Level += Client Concepts - Elasticsearch.Net [partintro] -- @@ -18,12 +18,11 @@ Install-Package Elasticsearch.Net Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. -- - include::{output-dir}/connecting.asciidoc[] include::{output-dir}/lifetimes.asciidoc[] include::{output-dir}/post-data.asciidoc[] - +include::connection-pooling.asciidoc[] diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index 1462a94be62966ab9631d4041fcc61996e5d17bf..704d08d1cc1890937e8e2b7e59c18426ac105427 100644 GIT binary patch literal 75776 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%0Djg< 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 literal 74752 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 literal 249344 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 Whqtl$4)|BF1-uLXFZ}N*f&T{5eFpFV From e4b0259382885f1d7af5574d10e8136c46e0f901 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Thu, 24 Mar 2016 15:38:33 +1100 Subject: [PATCH 17/18] fix the output of implicit links --- .../inference/field-inference.asciidoc | 2 +- .../high-level/mapping/auto-map.asciidoc | 2 +- .../low-level/connecting.asciidoc | 10 +++++++--- docs/asciidoc/high-level.asciidoc | 2 +- docs/asciidoc/intro.asciidoc | 10 +++++----- docs/asciidoc/low-level.asciidoc | 2 +- .../ClientConcepts/LowLevel/Connecting.doc.cs | 5 ++++- src/lib/dnx451/AsciiDoc.dll | Bin 75776 -> 75776 bytes src/lib/dnx451/AsciiDoc.pdb | Bin 253440 -> 253440 bytes 9 files changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index 14c505e6258..0243f5084f4 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -73,7 +73,7 @@ but for expressions this is still rather involved var fieldExpression = Infer.Field(p => p.Name); ---- -this can be even shortened even further using ahttps://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. +this can be even shortened even further using a https://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e. `using static Nest.Infer;` [source,csharp] diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index b56885dd165..51e533cb179 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -911,7 +911,7 @@ Expect(expectedWithMaxRecursion).WhenSerializing((IPutMappingRequest)withMaxRecu It is also possible to apply a transformation on all or specific properties. -AutoMap internally implements thehttps://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, +AutoMap internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. The default visitor, `NoopPropertyVisitor`, does nothing and acts as a blank canvas for you to implement your own visiting methods. For instance, lets create a custom visitor that disables doc values for numeric and boolean types diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 3d05528b918..2f4e6a0537f 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -121,7 +121,7 @@ config = config <2> Sets proxy information on the connection. -<3> Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts (seehttp://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). +<3> Sets the global maximum time a connection may take. Please note that this is the request timeout, the builtin .NET `WebRequest` has no way to set connection timeouts (see http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx[the MSDN documentation on `HttpWebRequest.Timeout` Property]). <4> As an alternative to the C/go like error checking on `response.IsValid`, you can instead tell the client to <>. @@ -205,6 +205,8 @@ counter.Should().Be(2); ---- [[complex-logging]] +=== Complex logging with OnRequestCompleted + Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` @@ -282,8 +284,8 @@ list.ShouldAllBeEquivalentTo(new [] [[configuring-ssl]] === Configuring SSL -SSL must be configured outside of the client using .NET's http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] -class and setting thehttp://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx[ServerCertificateValidationCallback] +SSL must be configured outside of the client using .NET's http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28v=vs.110%29.aspx[ServicePointManager] +class and setting the http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx[ServerCertificateValidationCallback] property. The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: @@ -296,6 +298,8 @@ ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, However, this will accept **all** requests from the AppDomain to untrusted SSL sites, therefore **we recommend doing some minimal introspection on the passed in certificate.** +IMPORTANT: Using `ServicePointManager` does not work on **Core CLR** as the request does not go through `ServicePointManager`; please file an {github}/issues[issue] if you need support for certificate validation on Core CLR. + === Overriding default Json.NET behavior Overriding the default Json.NET behaviour in NEST is an expert behavior but if you need to get to the nitty gritty, this can be really useful. diff --git a/docs/asciidoc/high-level.asciidoc b/docs/asciidoc/high-level.asciidoc index 3eee68fcd44..ff18811690f 100644 --- a/docs/asciidoc/high-level.asciidoc +++ b/docs/asciidoc/high-level.asciidoc @@ -16,7 +16,7 @@ Install-Package NEST ---- -Or by searching forhttps://www.nuget.org/packages/NEST[NEST] in the Package Manager GUI. +Or by searching for https://www.nuget.org/packages/NEST[NEST] in the Package Manager GUI. NEST internally uses and still exposes the low level client, `ElasticLowLevelClient`, from <> via the `.LowLevel` property on `ElasticClient`. diff --git a/docs/asciidoc/intro.asciidoc b/docs/asciidoc/intro.asciidoc index 0ff5442b350..ddc314e19bd 100644 --- a/docs/asciidoc/intro.asciidoc +++ b/docs/asciidoc/intro.asciidoc @@ -23,22 +23,22 @@ Please read the getting started guide for both. * https://www.rijksmuseum.nl/en[rijksmuseum.nl] (Elasticsearch is the only datastorage hit for each page). * http://www.fogcreek.com/kiln/[Kiln] FogCreek's version control & code review tooling. - They are so pleased with Elasticsearch thathttp://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] + They are so pleased with Elasticsearch that http://blog.fogcreek.com/kiln-powered-by-elasticsearch/[they made a video about how pleased they are!] === Other resources -http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a greathttp://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] +http://twitter.com/joelabrahamsson[@joelabrahamsson] wrote a great http://joelabrahamsson.com/entry/extending-aspnet-mvc-music-store-with-elasticsearch[intro into elasticsearch on .NET] using NEST. -Also checkout thehttps://searchbox.io/[searchbox.io guys] rocking NESThttp://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] -with theirhttps://github.com/searchbox-io/.net-sample[demo project] +Also checkout the https://searchbox.io/[searchbox.io guys] rocking NEST http://blog.appharbor.com/2012/06/19/searchbox-elasticsearch-is-now-an-add-on[on AppHarbor] +with their https://github.com/searchbox-io/.net-sample[demo project] === Questions, bugs, comments, requests All of these are more then welcome on the {github}/issues[github issues pages]! We try to at least reply within the same day. We also monitor question tagged with {stackoverflow}/questions/tagged/nest['nest' on stackoverflow] or -{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow], as well ashttps://discuss.elastic.co[discussions on our discourse site] +{stackoverflow}/questions/tagged/elasticsearch-net['elasticsearch-net' on stackoverflow], as well as https://discuss.elastic.co[discussions on our discourse site] === License diff --git a/docs/asciidoc/low-level.asciidoc b/docs/asciidoc/low-level.asciidoc index 39d361c5a09..4abee9ec908 100644 --- a/docs/asciidoc/low-level.asciidoc +++ b/docs/asciidoc/low-level.asciidoc @@ -17,7 +17,7 @@ Install-Package Elasticsearch.Net ---- -Or by searching forhttps://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. +Or by searching for https://www.nuget.org/packages/Elasticsearch.Net[Elasticsearch.Net] in the Package Manager GUI. -- diff --git a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs index 8e4a2318793..eb77c3e82bf 100644 --- a/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs +++ b/src/Tests/ClientConcepts/LowLevel/Connecting.doc.cs @@ -172,6 +172,7 @@ public void OnRequestCompletedIsCalledWhenExceptionIsThrown() } /** [[complex-logging]] + * === Complex logging with OnRequestCompleted * Here's an example of using `OnRequestCompleted()` for complex logging. Remember, if you would also like * to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` */ @@ -257,11 +258,13 @@ public void ConfiguringSSL() */ #if !DOTNETCORE - ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; //<1> NOTE: This does not work on **Core CLR** as the request does not go through `ServicePointManager`; please file an {github}/issues[issue] if you need support for validation on Core CLR. + ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; #endif /** * However, this will accept **all** requests from the AppDomain to untrusted SSL sites, * therefore **we recommend doing some minimal introspection on the passed in certificate.** + * + * IMPORTANT: Using `ServicePointManager` does not work on **Core CLR** as the request does not go through `ServicePointManager`; please file an {github}/issues[issue] if you need support for certificate validation on Core CLR. */ } diff --git a/src/lib/dnx451/AsciiDoc.dll b/src/lib/dnx451/AsciiDoc.dll index 704d08d1cc1890937e8e2b7e59c18426ac105427..7e19b8184846db91d27197ffc9251e96cd296d76 100644 GIT binary patch delta 13312 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 diff --git a/src/lib/dnx451/AsciiDoc.pdb b/src/lib/dnx451/AsciiDoc.pdb index 61f129ae7eb82e4cf89828526b2c6248d8021667..075c1d0b2d756baade265669868e66298b725e9a 100644 GIT binary patch delta 9019 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 Q=Fw`#hTwOfnl&o@A3Bqd{r~^~ delta 8893 zcmaKy32+ou8pmHxCxmb%AzXm~6K)7sI7C8#AhHBRkt0OzfG9|T$gZFw*x?32Bm`*{ zDG`)IPKhuAaYYflCh!E@Tn&*w4^%r2SH-%U>UI>|aEny}MfO*{S=9_-rIA}!I z72bqu_Ml>;p)uQ@UTh>9arVMuV`S129tt=b{va}LCw{Yie-#@AM%AeV-Vi17R>3Xy z){DmenjJ-~$l^DfUmU*&_&sS`myEgj58u1*veEi}PyTPdwrxELEse`|W{#(ZwSx%j zh`I}Y4tK+^;D1Z*sh_bf|^$E?8P39ufl4qL!P*cH~WQ$~2Y zSxLdi>cT{BC&OB>0c-#p!lqERra5ecEhkB1*bRE&AlMWRfh}MzYzZeq>GuR|jXe{# zfpcIhXbUkyq;c^+H#$H$KRUs0U}ty|$^fTeS8O>y(%~<#3ydM%9g+=h`XfgLDoQ>^aOPB+z z!53h4XxUXqd%jATFJ z6xi8gJbf)2Q$~9YCc(9^348;}X}1n`fN#R?a6Rk+--2?uHo{@>ZI}b!fpQgYhST5{ zD2H(?l+$h-TmrYlrE++7aKTntljx!jE7yy?h8(fQMm%VG427UN_dWE$LXan4iLP$GLwGJOTT{llHh= zPnXz#VajQI+I}n7)6V)KX#NQ0to{jl;aMnW^*PuJo`*g~+G0;>sW17mr}zm=h}GPV=O>F1K=68B)Z1Le z1nG*zLlO_+!n8;GclB-K8fNLb+eTYEv-%WTO4-46}N{tdo^|t7n)Us-{np8=}9+j&7Pvh@hP)BDF4PYPhAg zX1-b1Gb!IrhFX{hc~p(Q9wr-2jlR_Er|`GJs~Vj@g=d-vn^8l^oi9)fF*?5hEiGv4 z+NWq<2kktXYQFAw#c~mUMN`S>jyGNWjQY+MRzwSrDc>IcA~TFfR6Rt6zKsjaN6qx% zJwwm%;l`G#7J8D1)Fz>+Or>ULE@7nLr~rM>E-_abR@Uony`k<(7Fn-{D#&{MAv84; zbS)Q6RiJAV(Nt!-HZ9yQN2_qAi{lGusz>yoE5d^k(?0v6xyH&WImZ1aB2XHLtdig* zTV__tH8lA$kVV((rG%2xwMH&l%W%!oDr_GvYFZaG)nj^vJ<(L+ky=dDz%ajtB8CMX zCzrV<_Xzb$H%0)}lgNDWI>f)D)W;tb% z<>ENdrNSH+zcJRZ6@O$7pMsPy*eWZu<5W_)~&PDs7uZwsNO*KXjdL4~%@E581s=Q+M_h{>`R;SQ(Yp1Q>c4(@{q-L+Q1M7D? z)Z*OFv#JO6I0MjBBc-1a>(w`-6Q(*;T>{}@Z0f#5Q`id z({TVNtPa}Z0T$;?=G|L5=V4CV9ULbP;`q%$Yc`k@O$Y5=w0FXjpniXmlWic)>=G`9 zX^XPukyN1QU3v(use|7IjeMHam=Pmd7%b55Y> zS`nIhg9bI$9z|yV4dSVQU%8+gM{*bvrunYEVV;R%?e5}RL+uUSw57BUP3;A`_D?kR zp4YWwXlkE`)JjW#KvTy*84V*gs?yR6VU8Jcqnfb6{Hej6;PeW7M2sC9YE(~g$Fy@d zvbBdlbIW{&XX1j{W{O*3{4aIk%Krh2cAC5Z From c27606079590141674be780bb7b5b17bbcd52f1b Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Fri, 25 Mar 2016 15:32:10 +1100 Subject: [PATCH 18/18] Remove images directory Unnecessary for both viewing asciidocs and generating documentation --- .../children-aggregation-mapping.asciidoc | 2 -- .../children-aggregation-usage.asciidoc | 2 -- .../date-histogram-aggregation-usage.asciidoc | 2 -- .../date-range-aggregation-usage.asciidoc | 2 -- .../filter/filter-aggregation-usage.asciidoc | 2 -- .../filters/filters-aggregation-usage.asciidoc | 2 -- .../geo-distance-aggregation-usage.asciidoc | 2 -- .../geo-hash-grid-aggregation-usage.asciidoc | 2 -- .../global/global-aggregation-usage.asciidoc | 2 -- .../histogram-aggregation-usage.asciidoc | 2 -- .../ip-range-aggregation-usage.asciidoc | 2 -- .../missing/missing-aggregation-usage.asciidoc | 2 -- .../nested/nested-aggregation-usage.asciidoc | 2 -- .../range/range-aggregation-usage.asciidoc | 2 -- .../reverse-nested-aggregation-usage.asciidoc | 2 -- .../sampler/sampler-aggregation-usage.asciidoc | 2 -- ...ignificant-terms-aggregation-usage.asciidoc | 2 -- .../terms/terms-aggregation-usage.asciidoc | 2 -- .../average/average-aggregation-usage.asciidoc | 2 -- .../cardinality-aggregation-usage.asciidoc | 2 -- .../extended-stats-aggregation-usage.asciidoc | 2 -- .../geo-bounds-aggregation-usage.asciidoc | 2 -- .../metric/max/max-aggregation-usage.asciidoc | 2 -- .../metric/min/min-aggregation-usage.asciidoc | 2 -- ...percentile-ranks-aggregation-usage.asciidoc | 2 -- .../percentiles-aggregation-usage.asciidoc | 2 -- .../scripted-metric-aggregation-usage.asciidoc | 2 -- .../stats/stats-aggregation-usage.asciidoc | 2 -- .../metric/sum/sum-aggregation-usage.asciidoc | 2 -- .../top-hits-aggregation-usage.asciidoc | 2 -- .../value-count-aggregation-usage.asciidoc | 2 -- .../average-bucket-aggregation-usage.asciidoc | 2 -- .../bucket-script-aggregation-usage.asciidoc | 2 -- .../bucket-selector-aggregation-usage.asciidoc | 2 -- .../cumulative-sum-aggregation-usage.asciidoc | 2 -- .../derivative-aggregation-usage.asciidoc | 2 -- .../max-bucket-aggregation-usage.asciidoc | 2 -- .../min-bucket-aggregation-usage.asciidoc | 2 -- ...ing-average-ewma-aggregation-usage.asciidoc | 2 -- ...rage-holt-linear-aggregation-usage.asciidoc | 2 -- ...age-holt-winters-aggregation-usage.asciidoc | 2 -- ...g-average-linear-aggregation-usage.asciidoc | 2 -- ...g-average-simple-aggregation-usage.asciidoc | 2 -- ...ial-differencing-aggregation-usage.asciidoc | 2 -- .../sum-bucket-aggregation-usage.asciidoc | 2 -- .../aggregations/writing-aggregations.asciidoc | 2 -- .../analysis/analyzers/analyzer-usage.asciidoc | 2 -- .../char-filters/char-filter-usage.asciidoc | 2 -- .../token-filters/token-filter-usage.asciidoc | 2 -- .../tokenizers/tokenizer-usage.asciidoc | 2 -- docs/asciidoc/{images => }/class.png | Bin .../connection-pooling.asciidoc | 2 -- .../date-time-providers.asciidoc | 4 +--- .../keeping-track-of-nodes.asciidoc | 2 -- .../building-blocks/request-pipelines.asciidoc | 2 -- .../building-blocks}/timeoutplot.png | Bin .../building-blocks/transports.asciidoc | 2 -- .../exceptions/unexpected-exceptions.asciidoc | 2 -- .../unrecoverable-exceptions.asciidoc | 2 -- .../failover/falling-over.asciidoc | 10 ++++------ .../max-retries/respects-max-retry.asciidoc | 2 -- .../pinging/first-usage.asciidoc | 2 -- .../pinging/revival.asciidoc | 2 -- .../disable-sniff-ping-per-request.asciidoc | 2 -- .../request-timeouts-overrides.asciidoc | 2 -- .../respects-allowed-status-code.asciidoc | 2 -- .../respects-force-node.asciidoc | 2 -- .../respects-max-retry-overrides.asciidoc | 2 -- .../round-robin/round-robin.asciidoc | 2 -- .../round-robin/skip-dead-nodes.asciidoc | 2 -- .../round-robin/volatile-updates.asciidoc | 2 -- .../sniffing/on-connection-failure.asciidoc | 2 -- .../sniffing/on-stale-cluster-state.asciidoc | 2 -- .../sniffing/on-startup.asciidoc | 2 -- .../sniffing/role-detection.asciidoc | 2 -- .../sticky/skip-dead-nodes.asciidoc | 2 -- .../connection-pooling/sticky/sticky.asciidoc | 2 -- .../covariant-search-results.asciidoc | 2 -- .../inference/document-paths.asciidoc | 2 -- .../inference/features-inference.asciidoc | 2 -- .../inference/field-inference.asciidoc | 2 -- .../inference/ids-inference.asciidoc | 2 -- .../inference/index-name-inference.asciidoc | 2 -- .../inference/indices-paths.asciidoc | 2 -- .../inference/property-inference.asciidoc | 2 -- .../high-level/mapping/auto-map.asciidoc | 2 -- .../client-concepts/low-level/class.png | Bin 0 -> 66942 bytes .../low-level/connecting.asciidoc | 2 -- .../low-level/lifetimes.asciidoc | 2 -- .../low-level}/pipeline.png | Bin .../low-level/post-data.asciidoc | 2 -- .../code-standards/descriptors.asciidoc | 2 -- .../code-standards/elastic-client.asciidoc | 2 -- .../code-standards/naming-conventions.asciidoc | 2 -- docs/asciidoc/code-standards/queries.asciidoc | 2 -- .../serialization/properties.asciidoc | 2 -- .../date-math/date-math-expressions.asciidoc | 2 -- .../distance-unit/distance-units.asciidoc | 2 -- .../time-unit/time-units.asciidoc | 2 -- docs/asciidoc/connection-pooling.asciidoc | 2 +- .../{images => }/hadouken-indentation.jpg | Bin docs/asciidoc/pipeline.png | Bin 0 -> 204561 bytes .../query-dsl/bool-dsl/bool-dsl.asciidoc | 6 ++---- .../bool-dsl/hadouken-indentation.jpg | Bin 0 -> 43939 bytes .../operators/and-operator-usage.asciidoc | 2 -- .../operators/not-operator-usage.asciidoc | 2 -- .../operators/or-operator-usage.asciidoc | 2 -- .../unary-add-operator-usage.asciidoc | 2 -- .../compound/and/and-query-usage.asciidoc | 2 -- .../bool/bool-dsl-complex-query-usage.asciidoc | 2 -- .../compound/bool/bool-query-usage.asciidoc | 2 -- .../boosting/boosting-query-usage.asciidoc | 2 -- .../constant-score-query-usage.asciidoc | 2 -- .../dismax/dismax-query-usage.asciidoc | 2 -- .../filtered/filtered-query-usage.asciidoc | 2 -- .../function-score-query-usage.asciidoc | 2 -- .../indices-no-match-query-usage.asciidoc | 2 -- .../indices/indices-query-usage.asciidoc | 2 -- .../compound/limit/limit-query-usage.asciidoc | 2 -- .../compound/not/not-query-usage.asciidoc | 2 -- .../compound/or/or-query-usage.asciidoc | 2 -- .../common-terms/common-terms-usage.asciidoc | 2 -- .../match/match-phrase-prefix-usage.asciidoc | 2 -- .../match/match-phrase-usage.asciidoc | 2 -- .../full-text/match/match-usage.asciidoc | 2 -- .../multi-match/multi-match-usage.asciidoc | 2 -- .../query-string/query-string-usage.asciidoc | 2 -- .../simple-query-string-usage.asciidoc | 2 -- .../geo-bounding-box-query-usage.asciidoc | 2 -- .../geo-distance-range-query-usage.asciidoc | 2 -- .../distance/geo-distance-query-usage.asciidoc | 2 -- .../geo-hash-cell-query-usage.asciidoc | 2 -- .../polygon/geo-polygon-query-usage.asciidoc | 2 -- .../circle/geo-shape-circle-usage.asciidoc | 2 -- .../shape/envelope/geo-envelope-usage.asciidoc | 2 -- .../geo-indexed-shape-usage.asciidoc | 2 -- .../line-string/geo-line-string-usage.asciidoc | 2 -- .../geo-multi-line-string-usage.asciidoc | 2 -- .../multi-point/geo-multi-point-usage.asciidoc | 2 -- .../geo/shape/point/geo-point-usage.asciidoc | 2 -- .../shape/polygon/geo-polygon-usage.asciidoc | 2 -- .../has-child/has-child-query-usage.asciidoc | 2 -- .../has-parent/has-parent-query-usage.asciidoc | 2 -- .../joining/nested/nested-query-usage.asciidoc | 2 -- .../raw/raw-combine-usage.asciidoc | 2 -- .../nest-specific/raw/raw-query-usage.asciidoc | 2 -- .../span-containing-query-usage.asciidoc | 2 -- .../span/first/span-first-query-usage.asciidoc | 2 -- .../span-multi-term-query-usage.asciidoc | 2 -- .../span/near/span-near-query-usage.asciidoc | 2 -- .../span/not/span-not-query-usage.asciidoc | 2 -- .../span/or/span-or-query-usage.asciidoc | 2 -- .../span/term/span-term-query-usage.asciidoc | 2 -- .../within/span-within-query-usage.asciidoc | 2 -- .../more-like-this-query-usage.asciidoc | 2 -- .../script/script-query-usage.asciidoc | 2 -- .../template/template-query-usage.asciidoc | 2 -- .../exists/exists-query-usage.asciidoc | 2 -- .../fuzzy/fuzzy-date-query-usage.asciidoc | 2 -- .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 2 -- .../fuzzy/fuzzy-query-usage.asciidoc | 2 -- .../term-level/ids/ids-query-usage.asciidoc | 2 -- .../missing/missing-query-usage.asciidoc | 2 -- .../prefix/prefix-query-usage.asciidoc | 2 -- .../range/date-range-query-usage.asciidoc | 2 -- .../range/numeric-range-query-usage.asciidoc | 2 -- .../range/term-range-query-usage.asciidoc | 2 -- .../regexp/regexp-query-usage.asciidoc | 2 -- .../term-level/term/term-query-usage.asciidoc | 2 -- .../terms/terms-list-query-usage.asciidoc | 2 -- .../terms/terms-lookup-query-usage.asciidoc | 2 -- .../terms/terms-query-usage.asciidoc | 2 -- .../term-level/type/type-query-usage.asciidoc | 2 -- .../wildcard/wildcard-query-usage.asciidoc | 2 -- .../search/request/explain-usage.asciidoc | 2 -- .../request/fielddata-fields-usage.asciidoc | 2 -- .../search/request/fields-usage.asciidoc | 2 -- .../request/from-and-size-usage.asciidoc | 2 -- .../search/request/highlighting-usage.asciidoc | 2 -- .../search/request/index-boost-usage.asciidoc | 2 -- .../search/request/inner-hits-usage.asciidoc | 2 -- .../search/request/min-score-usage.asciidoc | 2 -- .../search/request/post-filter-usage.asciidoc | 2 -- .../search/request/profile-usage.asciidoc | 2 -- .../search/request/query-usage.asciidoc | 2 -- .../request/script-fields-usage.asciidoc | 2 -- .../search/request/sort-usage.asciidoc | 2 -- .../request/source-filtering-usage.asciidoc | 2 -- .../search/request/suggest-usage.asciidoc | 2 -- .../search/suggesters/suggest-api.asciidoc | 2 -- docs/asciidoc/timeoutplot.png | Bin 0 -> 10018 bytes .../AsciiDoc/GeneratedAsciidocVisitor.cs | 11 ----------- .../Files/ImageDocumentationFile.cs | 17 +++++++++++++---- src/CodeGeneration/Nest.Litterateur/Program.cs | 4 ---- .../BuildingBlocks/DateTimeProviders.Doc.cs | 2 +- .../Failover/FallingOver.doc.cs | 9 +++++---- src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs | 4 ++-- src/Tests/connection-pooling.asciidoc | 2 +- 198 files changed, 30 insertions(+), 399 deletions(-) rename docs/asciidoc/{images => }/class.png (100%) rename docs/asciidoc/{images => client-concepts/connection-pooling/building-blocks}/timeoutplot.png (100%) create mode 100644 docs/asciidoc/client-concepts/low-level/class.png rename docs/asciidoc/{images => client-concepts/low-level}/pipeline.png (100%) rename docs/asciidoc/{images => }/hadouken-indentation.jpg (100%) create mode 100644 docs/asciidoc/pipeline.png create mode 100644 docs/asciidoc/query-dsl/bool-dsl/hadouken-indentation.jpg create mode 100644 docs/asciidoc/timeoutplot.png diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index 227fa6c5495..e4ef930dedb 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[child-aggregation-mapping]] == Child Aggregation Mapping diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index 6afb38f8ff4..03824b12ad6 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[children-aggregation-usage]] == Children Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index 566299b3bba..de2e9bc9005 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[date-histogram-aggregation-usage]] == Date Histogram Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index 655dc315bea..35c323fe27b 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[date-range-aggregation-usage]] == Date Range Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index 6f01eb49406..39c76950f61 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[filter-aggregation-usage]] == Filter Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index 3668fd5139b..c533f4de65e 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[filters-aggregation-usage]] == Filters Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index d9162e623fa..c02be78bf43 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-distance-aggregation-usage]] == Geo Distance Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index 563ff562bc6..9eb3bdafbf6 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-hash-grid-aggregation-usage]] == Geo Hash Grid Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index 1965601fe08..6bfd96b6823 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[global-aggregation-usage]] == Global Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index 839dc1200b5..eecbd9d2b7d 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[histogram-aggregation-usage]] == Histogram Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index 7966d7965bd..56904224efd 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[ip-range-aggregation-usage]] == Ip Range Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index b2c1325173e..e4f735ab277 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[missing-aggregation-usage]] == Missing Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index 90bf74c6d73..d9d2836935d 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[nested-aggregation-usage]] == Nested Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index c69d8f05c9d..54bbe77c892 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[range-aggregation-usage]] == Range Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index 729d393ae18..f51fd140d5a 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[reverse-nested-aggregation-usage]] == Reverse Nested Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index b2599904fa2..685d639ab54 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sampler-aggregation-usage]] == Sampler Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 8e24eecc122..33b6cc3225a 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[significant-terms-aggregation-usage]] == Significant Terms Aggregation Usage diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index 14eb8a70b6b..d0ad32dd1af 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[terms-aggregation-usage]] == Terms Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index ac327c453b1..734b5e8cba7 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[average-aggregation-usage]] == Average Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index 93f380ba8d8..fb0810351cc 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[cardinality-aggregation-usage]] == Cardinality Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 0545ef2d91e..fa6c851ad10 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[extended-stats-aggregation-usage]] == Extended Stats Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index fc4165515ac..dcc46cf5830 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-bounds-aggregation-usage]] == Geo Bounds Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index 6ef21ffde76..d015404711c 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[max-aggregation-usage]] == Max Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index b4df7cccfcb..4212daf58f2 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[min-aggregation-usage]] == Min Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index 7b0912b4a2b..537a99e3ec5 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[percentile-ranks-aggregation-usage]] == Percentile Ranks Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index 712d5ea3d79..34d361d36f5 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[percentiles-aggregation-usage]] == Percentiles Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index f0071a8ae18..b84ed678d92 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[scripted-metric-aggregation-usage]] == Scripted Metric Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index 201336fdc24..a74cb818864 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[stats-aggregation-usage]] == Stats Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index 35e2b978162..2fbce89b3bb 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sum-aggregation-usage]] == Sum Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index 6b607cd99b4..df0b796d11c 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[top-hits-aggregation-usage]] == Top Hits Aggregation Usage diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index 3101a4be5af..543960f3202 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[value-count-aggregation-usage]] == Value Count Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index 0609a89f8c9..5627246d18e 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[average-bucket-aggregation-usage]] == Average Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index 1f39b46e9af..5667d998671 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[bucket-script-aggregation-usage]] == Bucket Script Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 11078eee6fa..bf611810360 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[bucket-selector-aggregation-usage]] == Bucket Selector Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index 8c7a1b14cc2..c3e67635a82 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[cumulative-sum-aggregation-usage]] == Cumulative Sum Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index 6792dc03690..4731cc39da5 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[derivative-aggregation-usage]] == Derivative Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index b4b0d9a2dab..fcfa9117d4d 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[max-bucket-aggregation-usage]] == Max Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index 1c42f828b75..ac8d91496e8 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[min-bucket-aggregation-usage]] == Min Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index cc2812d7b4d..74a76fe555a 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[moving-average-ewma-aggregation-usage]] == Moving Average Ewma Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index f54486acfb8..0d93a7c0880 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[moving-average-holt-linear-aggregation-usage]] == Moving Average Holt Linear Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index 5a01ed41876..21eeddf84d0 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[moving-average-holt-winters-aggregation-usage]] == Moving Average Holt Winters Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index 6a314695bb7..0e0a76591ff 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[moving-average-linear-aggregation-usage]] == Moving Average Linear Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index f65a4547172..0081d2d43a7 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[moving-average-simple-aggregation-usage]] == Moving Average Simple Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index abd6323b1bc..9970836ed9f 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[serial-differencing-aggregation-usage]] == Serial Differencing Aggregation Usage diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index f4c5bc51cc0..be50897a8cf 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sum-bucket-aggregation-usage]] == Sum Bucket Aggregation Usage diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 84470d77b8d..489f5ae7f32 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../images/ - [[writing-aggregations]] == Writing Aggregations diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc index 451a42d2158..223b62e0370 100644 --- a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[analyzer-usage]] == Analyzer Usage diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc index 7cd72547a9f..430437db32b 100644 --- a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[char-filter-usage]] == Char Filter Usage diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc index 123b5bec790..9b8870f4a3b 100644 --- a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[token-filter-usage]] == Token Filter Usage diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc index 2109522962a..61048a3a42e 100644 --- a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[tokenizer-usage]] == Tokenizer Usage diff --git a/docs/asciidoc/images/class.png b/docs/asciidoc/class.png similarity index 100% rename from docs/asciidoc/images/class.png rename to docs/asciidoc/class.png diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index b2a857d1839..20dd5810a89 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[connection-pooling]] == Connection Pooling diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 21b974474ea..78a65cb7c73 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[date-time-providers]] == Date time providers @@ -50,7 +48,7 @@ Plotting these defaults looks as followed: [[timeout]] .Default formula, x-axis time in minutes, y-axis number of attempts to revive -image::{imagesdir}timeoutplot.png[dead timeout] +image::timeoutplot.png[dead timeout] The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 3959adfe0b2..2bbeb6c13a1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[keeping-track-of-nodes]] == Keeping track of nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index e103179846a..9f6a863b999 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[request-pipeline]] == Request Pipeline diff --git a/docs/asciidoc/images/timeoutplot.png b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/timeoutplot.png similarity index 100% rename from docs/asciidoc/images/timeoutplot.png rename to docs/asciidoc/client-concepts/connection-pooling/building-blocks/timeoutplot.png diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index 9b5a068640f..97e299baa27 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[transports]] == Transports diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index 500db6ac62c..a49b874df69 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[unexpected-exceptions]] == Unexpected exceptions diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index ca926a265d4..3a1f5c3a497 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[unrecoverable-exceptions]] == Unrecoverable exceptions diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index 2292c45ff15..981bec1cebc 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -4,12 +4,10 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - -[[fail-over]] +[[falling-over]] == Fail over -When using connection pooling and the pool has sufficient nodes a request will be retried if +When using connection pooling and the pool has sufficient nodes a request will be retried if the call to a node throws an exception or returns a 502 or 503 [source,csharp] @@ -31,7 +29,7 @@ audit = await audit.TraceCall( === 502 Bad Gateway -Will be treated as an error that requires retrying +Will be treated as an error that requires retrying [source,csharp] ---- @@ -53,7 +51,7 @@ audit = await audit.TraceCall( === 503 Service Unavailable -Will be treated as an error that requires retrying +Will be treated as an error that requires retrying [source,csharp] ---- diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index 4c36843adcc..a932cc42591 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[max-retries]] == Max Retries diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index d3cfd035c18..c7e6c2b5185 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[pinging---first-usage]] == Pinging - First Usage diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 7343f05bbca..719b0640b90 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[pinging---revival]] == Pinging - Revival diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 7e8a733e2c2..1acbda22755 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[disabling-sniffing-and-pinging-on-a-request-basis]] == Disabling sniffing and pinging on a request basis diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 8e24f08e9e5..4b3bc518683 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[request-timeouts]] == Request Timeouts diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 765b2ab630f..7be5c5fa646 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[allowed-status-codes]] == Allowed status codes diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index 460e50b2ddb..8c1de860882 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[forcing-nodes]] == Forcing nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index 54afcfaff38..2e555807e06 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[maximum-retries]] == Maximum Retries diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index 14de1602a14..2d799c95193 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[round-robin]] == Round Robin diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 19871482cfa..8f043369d3b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[round-robin---skipping-dead-nodes]] == Round Robin - Skipping Dead Nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index 7a033a704b8..dd0712a75da 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[volatile-updates]] == Volatile Updates diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index 08006671d02..bed35b29570 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sniffing-on-connection-failure]] == Sniffing on connection failure diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index 439ddbc04f9..c34a3eb86d0 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sniffing-periodically]] == Sniffing periodically diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index 852b9f1a0a2..016137b20ce 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sniffing-on-startup]] == Sniffing on startup diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index ef4d656fd15..ee85b93a568 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -6,8 +6,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sniffing-role-detection]] == Sniffing role detection diff --git a/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc index 4830ed2159d..87de87660d1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sticky/skip-dead-nodes.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[skip-dead-nodes]] == Skip Dead Nodes diff --git a/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc index c2f48b87e4a..9b00ac69774 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sticky/sticky.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[sticky]] == Sticky diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index e6207bba61d..703b26da5d5 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[covariant-search-results]] == Covariant Search Results diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index af595ad36cf..16fa15261b9 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[document-paths]] == Document Paths diff --git a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc index 86653650bef..131c375530e 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/features-inference.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[features-inference]] == Features Inference diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index 0243f5084f4..cd12d888522 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[field-inference]] == Field Inference diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index 49301f29934..ad6a0278ee1 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[ids-inference]] == Ids Inference diff --git a/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc index 579a34df096..c9d8bc16ff3 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/index-name-inference.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[index-name-inference]] == Index Name Inference diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index 3b40b15a455..d396901414e 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[indices-paths]] == Indices paths diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index 7a4da607b78..287bc88d940 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[property-inference]] == Property Name Inference diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index 51e533cb179..8aaa7ca2280 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[auto-map]] == Auto mapping properties diff --git a/docs/asciidoc/client-concepts/low-level/class.png b/docs/asciidoc/client-concepts/low-level/class.png new file mode 100644 index 0000000000000000000000000000000000000000..bbc981cfe7a051af0152d2d83baaf219f33f60dd GIT binary patch literal 66942 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

B!o{oqhzUmEI=OF53x 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

im|0LnTy6JLiD3PxM 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 literal 0 HcmV?d00001 diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index 2f4e6a0537f..506b142afd3 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[connecting]] == Connecting diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index ce97ddf0f78..a7808a47ab8 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[lifetimes]] == Lifetimes diff --git a/docs/asciidoc/images/pipeline.png b/docs/asciidoc/client-concepts/low-level/pipeline.png similarity index 100% rename from docs/asciidoc/images/pipeline.png rename to docs/asciidoc/client-concepts/low-level/pipeline.png diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index 24fdc246c4b..0f47a863d7d 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[post-data]] == Post data diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 6edaf28a066..9ac9cf21d9a 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../images/ - [[descriptors]] == Descriptors diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index d833454b09c..7da07cba572 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../images/ - [[elastic-client]] == Elastic Client diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 11a2fc316a0..a4a0ea64bf0 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../images/ - [[naming-conventions]] == Naming Conventions diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index fb5312d5fb1..b78f193173f 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../images/ - [[queries]] == Queries diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index 06f69b8a55e..1bfc7353ec6 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[properties]] == Properties diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index fa5f88e32d9..bed4875f759 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[date-math-expressions]] == Date Math Expressions diff --git a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc index f81f3185a82..c455d46b1ae 100644 --- a/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc +++ b/docs/asciidoc/common-options/distance-unit/distance-units.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[distance-units]] == Distance Units diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index bc38db8c699..8a968a9c5b3 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[time-units]] == Time units diff --git a/docs/asciidoc/connection-pooling.asciidoc b/docs/asciidoc/connection-pooling.asciidoc index a62280ab5cc..58bc6ae0e48 100644 --- a/docs/asciidoc/connection-pooling.asciidoc +++ b/docs/asciidoc/connection-pooling.asciidoc @@ -44,7 +44,7 @@ include::{round-robin}/skip-dead-nodes.asciidoc[] include::{round-robin}/volatile-updates.asciidoc[] -include::{failover}/failing-over.asciidoc[] +include::{failover}/falling-over.asciidoc[] include::{max-retries}/respects-max-retry.asciidoc[] diff --git a/docs/asciidoc/images/hadouken-indentation.jpg b/docs/asciidoc/hadouken-indentation.jpg similarity index 100% rename from docs/asciidoc/images/hadouken-indentation.jpg rename to docs/asciidoc/hadouken-indentation.jpg diff --git a/docs/asciidoc/pipeline.png b/docs/asciidoc/pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..b15d2f0f8b6be04f79ff34091ceffcfad81c0525 GIT binary patch literal 204561 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 z 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%0AO|ykB#d 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�M}w)fj3bA|kUHi9ch~ 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

0lMKZW$PG;}MOT!&uRTnk@bUydL^u*_`Ect`dN z$q>qB+X-J!4txvAS!$a(+aEeZ2O35cZTRY1XOKmJzev9g>~W%@R%eW?(haNOH@eei zzR*_irj-@;F(kOk`12xv83=)XU;agcAw7}!lgU5i(+_n+jvA2QIHqz@efT#PU>Gd+ z6vSBnx&H*nNLw?w#=9EOFXKc)q77pNZIBGqG6a8UT;Q+EP_waN0jFGs0Aw1_!HlRT zf;ptRE%qFwC-`%-SOnzF*Pkc}d3eR9=EQ$~BJhb5(S=hN6oUL61Pm~CZs=;CXXv9K zZ5d$gOkC%T?#P3ShLkCl_{WE|FMzuRpLh>md?%@MRnZS^sA*wki4@&#+rsZdC3Mcl z63DW+h&y4y4F6fb0k<9g^2UgZ3@+#YdbvN@vPcMT5B%16|2|#(Fd8J{sB!e)DHkBE zB7S_3en3ZUbd~n&R)RLC9ThC?MY{se_56;%SA8E+7_w-;DcG@Oz=A^@(4sN?Zyej8 zSG!%$mU#iqmLU)bXMlX-zkmF?uT_%qzg5!Cjc;mOIb1ZjV0V#-Ij+a(5I{7G$c)4A zKh?hgr2Z*>Yh!*wBuWV~NE@LdPdC%FFTA?mBxG<0l;`Nu`L%wf#JspGrOb6*gRm}_kQvujR3P1>qtNShb|L-5Bq(Ea~{Vi>_ zcbNRKt@j*n4G5OV*)H@gct_UQbxMhdt=KE;*OI*2Lc=PzdxNsY6`Ej(y1EbQDpk8PuU`E z58+TrbNK1|wVQF`D~Ok|Q$^F1OZQu%P)($bM>i2qMgxkH+#a}J{>TIab9ATpW=UNa14cwLj6!E37pWPi2xIEzYw5wD<<0%2Mi9)Kjn5dt9=a zU7uAlm{EZYNd51xt^zvtkz6+FRIobZ`-BB&58NH_H(~yK)d2eL^#f=w63$u%==SwP z%>(g)!oh^Y)BluF;JC~IvB!u>Y$~-pP_Q+)=Zuf6V_16IzjBzd_1^np0t5Xn1?hjd z7ePPgjPnsB&iF7L!^+$K*MH87^b~mhPfrq;f?W9kBVSc2=wrV#E$;Q7og8r(vHgKQ z{tvbP|99Q+Ljunt#GZUrAW@r?;YaqC$>v;x^N-st;6fky546$~fyOsK31l;a08^(E z{g58C7$;{eMx1}TfWkn}>jk`!m{ie57QJ48_8Yssf4l&p#^&noa^uhDyHAD*BJDuqi3NG|jDmy_a&2~-=kPN(li}CX zgQraauS0=NR|so&6ND@P38eS~g~OKrFw=fmK$3>%p3-ONJK-%4X2;&VO>8_2!(<}0 zt1bJC+L-O^a-(P*4r~yE7l>kkUJrqsJUjMW$v<_xFu30xPH(SrCOKX>U0iX7KI6w9 z3chjtntej>IVv!%;nd35GS@yiWF&5==3xB!3ml^AW_%}XdGdFpt zp%HxW8?ex8Q-lJ!demk^gn!)nYGz=8X@uT!_!m@-OJ~HSCQ4{x9Ml_~d5D(w*xTX% z)6>Qe2n-aJ$3AMpEnI#@hii}gerv?IDzed^JnsKMfzGMn#7Vb`$#c8i!+-}#6rXW_ zU8gmnL!(eCW#6MPOD|7wh&W{%FyyA8P;^2jt$g83iV+f%#hF%;8^ z3$}MxjV&YuLrqlmN3pvOf|=3az-!`Pztsdgs0aBoxA`68|2ztFa1x!r3 z_;?o3sTUadXZ@F z=+|$c-JqI#A&Rt%!A?i_Ha;oM?`zc4f@6gAU#g_Fdk=Jp8w4&`+Ct`qvT@8#zY_M9t@+x&Wj)!#1X1V{iU zvd6?8`PS)Ff%gS}BMt18L&!0}6ba(ZqM z0g)Dd$#NjRS`0;ke2S2!Hbu8zt{@YocG$vhFj#WbS7q|+QA6_7%Fv}k{b2K7dx8h< zFx`!3<=6qHyofFr473OI{yLklbp}io8Hav~VQfsR1rKCzwa-QblISD_W}I8m11Lni zrjiGL=gK}a(kqW`^^K}>S)b>WvMQ`SLp3+OzYYGYYLN$(eVrN|Ao==_AOAU^15Pru z%5nTmMU8g!0kpo z6K!Rr31U{$_c})r_q)l3x3MZSA=x_zGG@o|_jdmN!%r~$7~@7Ow$EXj_O{B0lYAwK zD(_e0EyJ(+hG|udXF~O=moHR$DdS4kqU9~v^Z683>7BJ>D2v}0yp}WVcuX5@!LoTB zjr2pRMljXkzZ9Jia>HH3f!NNdr_acy4(T*2QtNTz?7pKXNvgz2siN2EvPZ$QSH?SG zl52?9b*H9S6RplvOM}mi$YbXpMtm|6+PrqFN1#!)y5qxk|FK5^&~*n%FOpGK@F#Bs zMatwTpFx=VQM~#_^(r6dbZsm}dG{CXv7Fon44M4>_{`KN0%U=_KYza0)wKB*nG{9$ zsmTq$R=Fj`c>L2kbPFXo!0{iz2HpQFm^??dV$CAi^cy!n+F>(cN0yxu2L(3$*}9ne z^;E0wTJ7;1rw&{~Y%24Y!JEwAVVX;!)jFQ;9Lv z?^1GL>e$9bfuUg2UlD)%djCbCcq~zD<8$ zTiwnyl;qIet+v$M@9oNj(ad!{c^;3uKVx}nN}f2j@e-g!oa*_s>Qh5kvMa(bxjQi= z|?VsnL$@?1NyQ7Y{p7y6pF-$j1>sHkt>P1NHOAX9M$+QjXD4$B-#qTOY)0roS~(1K+n7zdG8@ zqya_$^(5J(b>HwQ%(&qKRKm{|2FDTf)lVk*%Du|&&=wKXwi=~v;*L_3d`KB|nXB9H zd9v~8NrRsF-D?vc&j1ETEX4?KwWq#2pifFkktHSja67;cp5e7f_Psp}uUwB9l^x2k z;nE}b+njJI{xu-Gj4S3vMBmkleKskc-Ck^2DRVSo@1Z;>2)0WZ-cAg*3&&=_;!XHb z8?y@U`a90DnZjv0Ed*&OjKpb_PvGhNgS&In>Oazn+y-W zY@7kKM7nud*C)+zfyeuo49TUeT=X=5?UOp^0gZ2EsP5ml67vK#LOm1S3~m|t4W$cx zfHezeX?fY?Xk)T)CvY^%Yp;(HpousgmgMW}K;a{bQuLce|B?rI;Erm}hW}aIl2e}X zN6kPz3zdDo)?J~PXUBn-3r~HBbw;}Ni7?!4-e)9jZHH9FGR{CyMI~fzr!*!d_eRnktAgB_}bJ2Nw-HVgtw`k zpP%eQJU=&O3mT8-G2^v-NqO}qm)qC(B zX;Mi|3sS6-ojlG-Wfb7RcoFJH4>phTldiMDvU~GS(-N%2kk7UYfRA$Jyz*6TxZ=g8vy^u z{4_jJzI_iu`&@aGB)0jy{4s9Pb#qKp>&bosy`3SLMJ9WIV+}*f$FELuGf559X)Yfr zwoTKSe0EoS>RD#ZH~!%)v(7ILR{D?ppCm@+i6%em`F`;HrfkNeppnlMwl8_@X&|2h z*BZ>&KoqEXxw!BxwP&#%p#q{N!LIJ^8a1ztVMke@lWriFsJ9vpJ+!J38x(D*j(06d2~(^$o_ojx+IWwI$}v8norpG z{JsrIIf8UOy=FJjx^bgzP|n3hwtB{m0@CIaX@1FF1irby^lV#+K((>qsEjhw*21DA z({&aA1U=eUGQeUpQO|=H%zUoU?C5t4S;q7_N4`WoyE-Ph-Ti@7WQ7*Y$gU1@GZ_!m zZmyg{-flKbHP&wX<~;M)w?SL6cc|8Ely}HKBLB=iwZ8gn!SjZ1ex2VC*FxLy8cowc zXAIidF}rQQzoSUicL-1?Vciv z^s{BHb$vX4?WcNI=2ZMUaIu7hgGLhl!qHzCiqxF>m(7gZ0xC?k!f!L#E=Im;>F}aR z7u(rT93!3Z_#&e9r~W5JGmTzkJ=xrM5(i1lF1zh+UZ2V{nX>c(fn(r`-0$N+8^NF|wVdNMV_lPv#A@V5IXh_vgoh$?kT=m!7P$~G z@eh5Q_jVZi#m*`3dK!N=Nv&6-$DL*Li}*`zLVWUvx`*?ps}t{a$*1+A`)%Gzh^}_Y zUgtN5xRJ`j7&VwKp+4REaYH57bqQm@(BlRsfj<7%(aX=FLeQ)#oF`wpjTne2(7$d> zg|e}xbh@7;XTDa#dH_^;ATN*+`F1N*W!9{noRg&rS<1gW*N1&u-J{MXbIvxh8A%7D5YEXF#Uf_Q4fYY=misZ|prVld5 zyI*-i8f8PX2n}RR_2&09Ml1*%wj43(gbrV4ncF7vNu_m~d1COD2E>6>+uv zW=>I_I*o*2r>@TUB=HK2_8@UwaRQQtTu1tz;D9d5GNbwA8M&d5zcMbOM~2&ceWxn2Z$r+UzcKpn zWdM>m8Fh6lN(lj%4HBR8MXE(W;VE*nX36CWG}QUM9uy<9x3_=aIG1FZmYxoEiI)SM zJdWrAF3`puq>PU;FOPk%?k;|al`}M?1e22Yqyh4!yl_PXx&=At_nS{-38U`?Mj@fd z!_knl*>q92U;eFo%B9+Q7BFzsq^BH~h)An+j8v|IWHVZ%7K!@Gs9FyNlaxsUexVYN zL=uiS5aTpdOolV30`Bc3=6KSSMJU+tdxieOKxFrB1ZV_kqvCE0b8{F`;df@u3d3V& zX8v{d{R$gTqvJU&D~!6%LKuBb_azeY4Xj(|q>=pYn;r z?b!4b!)CtCYp>n7OMDR^7CVb9jw>{shV_$hC zrA`2KGg;PebAu7g`d(f1e*CE6=qW-8@eln1Lx}f(=LOQd!IELJ5}4hLJiIX9rQ)#YKK}s5>Srg6#rIweO6|U;lyv{xN zyl(e){TuOT+HI0Ab6tKMdgBVzR^4Kol~qpTM+O~I)Ew8Lhd(>&r~6sIZg+q8+8^Lz zBji{B-~nqe9V>G|!P2s;#bap%Tfxftagz%+bE{ydDx`Gz7 z&&Vb4a;RXh@p`!)kO$uTVRW@mwS=`A8}!s?5+_8PX}pf7!DO((o8&SW>4m7L3zLES zb=7hr!0%-@0W%@TG0k0lJ4t14`h`A-bIR*rSZ?OC=K$|`adG0((o?`9h%SDyil8}` z^slI^)5Kr_#88UnCoAGt?jLpXWurTwmb%UeMpo_0pn^?&E_q!O6O)zirfayWK!+P! z0;_%gg`VkInxVnb`*(X46H^nPq;{KzR)7j%Lk=NAAmhkGy~PV}+Abq#mJw0DV_;yr3>HI3xU_CXq>Gt55!}ml9>fRX;2F!}npgH%2 zkh4XsW8Xt9(dZ8-D|54r6}(t>W`(G(_UPL2zUb8fjY%Sbey9@tK4OL=VP@OzDBT2@ zf$34&!OF%{X^MB!g>Nh}MAztlHSOgDP!Vtq0NVJq8%$<&P-I{E&b%13_h?c1mMDE?a8EhyWM9sg}g%Vpc+78G33 z@&Sh?Hh}OH1mRVUm+c)Iy8lRKVq#K5s9g+RoyX#97og__B}A&#SdLfPbQ54mUk%6l z1VwVZBQZMrHlD;pGrwjq;u7vhV=@4^c|9{cx85oW#J{aKLl3l|^-tDcgh`X-ha*CKk zAnm%C$3ZcvQBd~Qasp$QP0MbN%_f1c+uZc=)bVE3bhuAq1lLw!BrQW;oaguH&bI;j zXN85&#J8EsIwJVTp0p2LdLz16J78+{n>T7B2)L{?@E*Db%fw}Z9V%CDFJB0s78e11 zfe@1xf#dP7Zi1J;z`Uq+<%grQvz1%U@UH+GsZsUJ%uL#+4fIMvT+sLxyMU3Y_$<>b z%UyPo{g}gHoA&rFcBr&yJ3X?}rvkg$WDZSb$lzss^w1&e26BBU_LKe|EIWf;Yae1eGhimn8H@!$CnJiwfh(uPzp(&# zQcDUYAnYg8C|7%T-cNwIILj88NaQ#Gcf~hJfQJ9(-jBD@I!^JI#iJDNWud+E|f*sHi*6uW1lQ3g%~^_jDIz5Ej7@6D@vv z*pPf87ZfV+_J9LS&Y|U}frW(i;+uy?FB3&(&&n?*8yDb3wB>yx#jCoI(*@VhmZqD+7 zoN*gSv5JYkn|fQ|XNowwNldrw@3?KdsJ(Jd3L#wBzrgb19IY_%4>PL860DGp$6FN zQ(XP}ApUh?5B?ZYQCg}v${J6W05Et&&tV8NpnKvO9TH)9JOFIkDw}mc zmqkZU@2pB8pslB;rv?Z$jotK|M~>^+eGe4ooO2_XhL_g&PpHK&e-^$QGff)Lf9}fT zP8Mv`=n~YNo!xqjMOVZK;|fMQov+<4Gjf!^jZGy`x|Y?uB5h3f%*gvh2#OzdGX3s# z6O@EE0wD6IbbiF$<1jav`UcGJ;Oi1nm96jDl%jGxS`&O{m%n5fcFcmm$&M4&CmK6_ z=46dON>g~9P9i0OaWv-$8Xihx!qCYzI1RDWmLjhpdceagd{y>g=7f<) zdpjRfSGK;m^oeJ|%mEd^o7ZFV2wnv8%{$Db9Q*wvkIgcjQ#@Fdz62>WRRQAyhUaal z?JHU1yR#@|o#X4#8C9b*Yjnap&U$hbJ~3P_C; z79e9k?i1`l!yf4F9f_Ea5LY*Es2B~L(K~t~H<=ZuOy%vtym#yPLrSu6weL#q=XWy$ zG#q?id2_u+RppylS$Pm;Xr6DVx~e&rN}OVA*za524AF<85oe4S>LT$x?c8RcHJPgq z%mK;KhMD;KBawTc#fbgw628|DRwH#Z1^iaPLNHi%MgoRNZn<)K{j#Gk?u|Y7H89A; zN6S&4`f`7hxd?2;V^ z_w2epxMHtcTFb02N1GeG;VUS?H~So5*{fDp{tMMwxFP%NxTwdS>HH5JG&tD(C>bg$ z<}j>VfOCnUiTLX`1 zgxqCqqaB$HT)ceYU3k~saO3#At-YXxFmjDwYVa4cFho!>yrh>v4g}my4LK#ekD>s+ zc0(!e;yT;Gh5Q!*VyU@VgwDB}NE;r7goc^rC&F_Ks9ylX;7+d_xMmWB=pb>3BkE^g zlua2tEF2QW!7Q_I@N!3U3qDdyAEu-#`Q@b}Zfcf);VY{5uivoze4F^!=a4dUrZnyQ z(o;tfpM5IdOULo-->IV#E;LMJa1=T_lzW4Fb;JemLUt7ca z2gR4UhMJyB=pWytbRMb@N8lt=R51d^=a+t!3*i*lLY}2XCIu?1$DI$q>-#k^igPDC z4|zkc26s1GHKC7T)2)+#mAqb|fXVvyJ%PU!m_G`l0KUuf74gM`5yZB-z}dyNZ&i?R zcx{3vCXDpsh@Zxa?4GU?yM;TZT2NDEMVY+oN~S9`G8iLTgGnQech z+uxxS(W$7aLN1>koNu#6KHk5YIbjKj85DoUiN^;@f!+QFqZ7aS_zpc*gJ_t@xp4Kw zr~IWoV~h_DG?s{uLPv-~U1GImlEa2z)?c5~_i_vb(z0W#9ID96tF|vASXJ>5O`mDJ zi!%8scQJN#PCv5nKI;4Rp5y@w)vnE5-89`AYis(WN91r9!&|bdtdbV8avt5^IuAcS z!ZW@VOA^+zI3Pc$8eCLC(ag8qeRS9i7-h%!-Il29`08PTq8PI-RG`r7H;`?!ZC|-q zA1(UrF1quFQ59gBzIGKMfX4-w)bKlKnOJd{;y+u}#!oxXALCk?{_E589_QNJic|3CV zyIz#B__ArK&IL}&BHp(altMe_ojUXYHJJlun)qXn1UJ|)?N-g=aMN>I-AAq&c-?og zHgUy|HXg;(ZVl&a@kE62y*qNLvu2gs-+PwXP?usG++3#_&7rb^>se5rY`a+}nvnCc ze=OgnR}ENkI?WhRIJ#lbO%R?G*ZEjbqQQbY&<(cHjaEi163p==NXr0k)cF;5Uw5pl zXfWCG)&1g&`zHnT&KYo;=zH9^{>?*6AJA(lDnp@=Nv`l}&UY~ECr!5qNAt!5`gihm z$zd!uZ<-xj6KuA6$ZRzcQi@I~=(zY8Fjz1cU;a@a1R#p{HS%%sd}jNg3yZi~GC zqTIT<-={L2A4U2vEa7K4=LsV8G33SNvXiwAMD7pfKgEO0z3CwuS-jp5PWK|FI*1Wi z_&2)?1oJg#lIp3fB~5C{Obb)%%I1~AkhTd_2EOACWjTI)+CTAP(RT@i47yi0p2FUh&N|h z@!KyGd_dB0^BqB>5B^Z9A1LiSU&*+wEumN;uSaAgR4&~$@s>hGNlZ##5i?;qqvDGt z@4J0I{XjI@CmnQk)-wTP(a%_{Q)ualR3g7WRA)&jExYK&t1CAQE_iI#9-meil-v*z z6FO5M=;#>FvqCOFH?Vklv7@>9sOs$7x3B9MiAAs{=csPjl<OJM4Xs)8vEY1CbnURUPu&q z&>n9x%fi$4xXa?{7DO~_@Z>A3Y|WtD{QVloeZ!=xO8D-CR8ka2SLMK25(&OJ$Vu=x z;IfQut6Q=q_>h%WThFj37v5(SSE^80UbU&5-AFt+w;u1o-h~Ij!zE0ifECyuYGa07 zc%B)*^|v69UrpZ{@o)cDZ%Ol=nLa>|G!kWf4pmhFXbmkUpWQR2d-rD0H0Ukp?8i0| zEwkjE`j%BPnH$cx?63fHbO)UP_v@j9`7=8rY}xajc*O~G*6#sbtK34DMlb}+N5ozp zH$To6*CMs4Kth7%Qdq%v3&T^q=|#p4Q5SOE@ha*5G%ZCDdm_S8!3-3%_o5b25mKwT zh|ib$B9mh$$A$EfwC_xhw!a0p8nz3@f*x_~RFnk20gRud?ywE!oS)4oeQlnX-eY0t zxGHp`@ohKzAHu{aJvX@Mox{#Cr7fWTw%UkDGwPEcg6R$wWI0{wxhv9ZFg zq$iyr^P%GBxlPKa5OExftE(|Z4iFI^|0C2f!Bqtjyc#;YtXYdDRN5@mexvWM1{-EL zX5vZ%iTZt%#;S*4Bv>8kK26aX=iu*gy?1bq&SwHgp8-# zHxU*XU7G;H;LUuZwc=M?E@@PpaO71|_l0cJks=}z!FnAG`sDQE(lDau59H=|kQm=5 zk-`!Jl=75iRoG;Y{FJ){7ww+IQ(ooS+~ZNvw{BlB!@kuP3`R7WXP?Y*~em0pRjm%lb?6NHMW01KGp_p%FQ5ye4; zHMukiD%*LiF>3`T1TUBlW^sdBK?Zg8LE$==+Z^@Nr)F|QO6S${@*<1MZVlQwtNGoE za0LNxh6N?Xp(YosZ!TJ;q)eYP^xNmv^3Zhkh7aC*#uXE3D=?>tU&_ClRD2$czD)Bu>8h7HN;;cg6_TSWDXcuF+C+EjpI2cPhL}kX`lPv zZKjusCR%J{_9e2Gj63atvVOk#U{ zz&r~cImGA&vF)=CFM%T9d(hK1#GEB>O%UD~*Bhs8=zbHLE96mO`K{8pD-mQN%f2yv zF>;V}wWjjh?nct-W>IeJw(rSQ}!?IgB>;0yKy=x`z!9# zuf9?2!IE7Kde4#v|Kj3YZ~e2_%S!K!9tNCZK_N7AagZc8&-|%M=yCQ7VY|vk0lDm> z`Zx9Y9)oyy&ZM$x0VBhA&zIUjUM52Q9(NI(T+*(pfJ9N%)Ca*^x+MS&0+P;vl9W0d zz%i?7k(deFR^Oj-vEOp8S_qAm_;SxI*ZPc)$NQIm2b(%opW~p+)RtmSE5&Z7Y|gVy z3nHQfuPqS)v^!EGXxmbl@0;bKr1tk-fhg);c#%q|C*V=`-m58~tS>mSJQ#H~9PeOK z=b!|jCi68@m67fu#jE-|D3BCaR`wjfI~Jv{lt)@MI$yZE*BH!x!so+qu-bT5^YA>6Y>h^ zjESKldcUhc_}a5bQGYNh2?tctKw#{7kOA6!sQn}+y^pEiol@T-CYH^NESOXj+P`0? zrCBV*5aY&=pM?HE_tkI$q24Zir=|tF+mx0C`&$}IuWbrycGd9vn;&BGe!ND+yY)N{ zQ$k3O$WfK@7+x+@3X+C%|JCu@*Y|@!0>1s}okmQ|q1rWWqRjAY_Oh;__l!mx8FUa(9XFKuJbe*MJ+#) z@zFea#j*X|!_(Xd27kW8p2wJxicehelnTO{37_Acm&%i->mGF+6fJ^B*)R6Yvl^XX zKC09&F(jy&2c_YTevY>Chyn54E`n0(W_aj9%9!F8Qw5%WP?QQ%Vt zUNF%z!Q`#0tLsrGY?lRIMt(hS#JK$iuOa6G#SPRWXs|+-lCe!Enf2D|*kEK0}E%~nSHRP+zJudg+QeId*Wqs(n7MHui z6g{un`GEL`cNAz^7WaJ#YNYd|8!9R^SDWE4?g=&B0AOF<@hs~zt)~%T6s8EOLW_zp zV~653rblgUc&`>ii+c$a>glWcvhitNw_3eP>#$9a8lRrXgA+1)h&w3Ol)BeGIpKR& zgf8*+=0&x~E<-XgFo;14h@+G75zX;CIJ)YbypgaM(1GO$t{{yfcr^(dDBSgwuooh9I1f(t7VIs7Ih3Z z4Yk>Mm;Bb#I2MNQ_v0D$5Yw)GjTi)souc-&Eb<%!sn69s{|bR(utWBF*syvNPRWiG-!*DYxof7Raz^+0IU0zu`CTFQt%Qcg-tA2=I}V z#2S5?*ijHXLJi~fnAGttKnlNDjN=x;+TGoKA?R3WSZHSmd7qr*(01?n^@U)O*)6{` z3mHIkB?8dSA>nS9c#gb^C%s{<`sSeaXB=Vep;Cgdq&^F(tVyjn(4~z=iw-C3L#g>i{k@SRt+hd5o}MK~=?F zMsra&Z5}*l>Re(dB3=J*dtJ|x6vmK-S{Zy!yZ(6ZPE1kCg;z@<-r)3wQ0=}jw*3SQ zk>hc!PMDn>_=~Pcv6bItW1<()fp^`!S%4bF4#l=gNlhsX$9QcQo3^94uG98%MQ*UG zHbB*^Wu}_rpSBAu z?X&x}^The}B4UK-7wWq(`h+5Z>OK{~c`FhK#)))2bzFPT#c-Q@lI}qIDYCmlPD)sP2F}Zh(r{B=?&`tp<&XrRB!fop!;;U%ZSM^kG-yN zo@jTeVan#=A%3$Zz;CEmMfS2ElR)?gt)SpA5(ir_xz@Hgv~la*nGKZU97Qm*v1x%A z9(Us0vCn&8(C3I70#^!n956vS*fM#7d(uI~c(QbgKkl~uy2+rL5q5EQTqb|YYdKbI z849YQ&tHe}0fdIXqT~Hz@h@~0HFdLAtCno9%?7u2E2v@d@bA@XB3Jc5DGnt55V1+8!oHDx*q!i2v7beN|m>0ny2u|em)(UzLFFlz2c@dRummWmyzGIKg<{75XGr!nNkr-0f0teF>lh@$uNaT_bN0DDL zI>}=Q4Fi)13(KuP8M$&HLeM>s?m{Yg!!%6&1*AwTRQ>bTTgLSrqf2Xk0klu4E;Fn= zZ07-pGqr{cgNX3p@VU4;eORLtg|>!`0v6uAbpWufRQ&Oy>h&I&xwGinc1B?Xc-QGu zdIj*qIh=Lr95i4mbh^*>mj~8d-@bj@`fcxM%J#S^1t1j8MDu1E?P*KP$^a5#ec99( z$e#)-C{)I~&UOt2Age4^JG!A_lMDD=ge!mzr4%~?odxLre#~72j}iBAROxl$S#=3y zv~Qos5A6fzh)8DP>f%SLQKb#_Qjcuf6)&Fdl0sE&?St!hzYQXA7kvA!R1g*(0$z?6U&yFOw`p%= z86F$E?NYHv4eqt&r1ORns7hfVEBSg+V15~i&&r|G+vIvz|&zOJd@ zMoPfW-cCxv9R3q2nD{#YLt=T7Z>d{ZdCR@kumuc)VSz2RU9Puj&bz-f?T#R_P!0z) zC{F=$Fs^CvbR_#S2nSXP(FA;g20SHyD=Qm-Wle*44@_p21{7=N z2yHz&7(-J1uMY`?CfPox%(uJc{y+BK`mM^S>lzgV5s>a~Hb_Z>G}1_?APv&3umMSf z?rtQM?(R+j=?)1A3F(HjHu}8pbI!TGf8bo_7xY48-}hQ`%{61pF-*@K0dbnI1M*wk zpcV|1px_QNzZ)*h+=3Em$#>kZmoDu#7_ia$k1dHaV3>N*aDIt z_rI7;!;vfsN^XI^&96z_&Gj8<41z4Evajq;5WUxWBcIAe{^hm;SlO%~0H|HuI5Ilk z9Kmvo4}f4dQ7K5EVku=$OidMBQt!9i3DZ(bs5;4Z20SLC4nW|!coNwR(x?2PfB-UI z1y!i5L}LIsN4!MVTNXmLtxv!$q!&PP!7EvED^1aF1=5j~Wp8d2U zn3$AQgJxUxRMpEwjvU=)&;%+orcF;BrFEAYjV^;>(nXn(WxhbCishd44u-B*ru=q> z$J5ZrC1DTxv{FX{@;YPj*0(Ex%0GRb&pbZ7Ha<)XJf{VyS?5k(jgLt0f8N&oaA-u{ zqs12=52~)}d&oA+ejF0E@+V3^rzW#jXXE}@V?SepqX~jV>hXFmuR6EYL434Tnk{Q( z0F3#LEzdg#+Q5Y+Nt+Wl&f*3lOG@q+60}&6VyZT>#7ve^a@v`iw9j7@#{!c&DJeLP zpzb~2z-E_HMe#nJF;Cz$NB8>kfg<-g-6-v$qy&na=S02+z-nsd`P1pe2e2;8Ft7B% z0CRX`I0=Wf5Z$$-lA0<$(lE8^;_n9l&;@zq=`rTXE(GBV4x27qJnB4%7;?3)rV-8(EM_)o+Y>s#^0$I{{CyM;LP zCr015QPu1yi4|b*SJ3dZZ~mOwD2P4c+uGLQUnW9_H+00RTyaz(iUe_x!!9L)8w-Nq zDl6`&lQ-(F>dA|^oJW#|)TRI5xINu-i)J2D%&NS96Gq&=_0||DdoXhlu_~W}i?);t zwkxU|FH|Mg6OUV8cH+q9(J4^te5X%qyuJJl(<)wJOaB7+$p8+m^!Umr82qPa!=h^-x?!fgM)TY0sO; zS?Li%^Rr)`(5od18ulg{V?UO+@CtzOl#BggULDyJH8nMj=Xn3TsTwljeGBgn+}B_} zNN}uv;QLBn+XtjFfW^fR;@#cL`bleu2E#eFd$89VMsVYsmTQc2a~XOlkiCWxHTS)i zc9v}&M|jDWHvLNUr&vYal7|qn{lBSzF1EW9J<=J2hptYIiQjoX78Qls%E-LSbkM0T zmj;TugzVyY^=5yAk!Q^?2)Yn?_+?EpD7FG2$gsjfW>6~-avuVqa7@vRoyCTqvnsxg zJ7N3BHf40mj+>a<(xFBG`)drt{(8X2VJdY7y9hwRbj0qdVpXy?n3$;8+o-4MIas40 zpknU`@Ef6I4H9OmIdpwW5<`d36Ey%0Kgp7wEFuE-; zxOqBnSMv%}r+a8}QWNGjft3=4J5kXZD#C-4h9fTzLl_dseL1hf!vl(M4?RF{zy)GR zbkL~?kAji3dr(~!oW5JGSg0@ zB`Xyo21iT*k1-wL6A7z6voU5dxc{!e8WKe$}pC=mB%nfpo9y^T@au3G(Nd40A0M&1~-@|LXxDY1;P|A+%JidD5UUW#+G^<61~Q zJb(0v)DfL;HLl3r8e_VegcnFI1II=bU$E5KVvBuuMtrTum386NObSV{n41?D2; zwYEf;0k}=O#*U1&cG+)e2F$YMWb)m!3Q=mp5cyYo-MOTbOd)tjt!~@NNu^C?$i+-0 zE9SoB=*uazhR*PDxJrc#8GkZn7WdT)E|#o*m#ywG>(&ubh&13I^s#pGletLz_?^_W zD_qI#uFO>-5>+8^xH=%Fq@sd#cy!cvPYWuOfdP9eFwg@e>_L()mA)lvxZWQN*rh1| z3am9v?Qd@YFzPPP*CVUSrRE4~_;KdKVjB zX8Q^+1=;Z_%BP|aJ`%~5HBfek_w*cx0_~S{E3`~Z!CUpUFetnXr3{Qw2&@cS{U$X) zPK??|HoipZV$-P%08Jp|SeQ`6$Cv-ZnjBJ(L6p&rPF_Or`&1pwuSkW#NSZN);p9Qx zjnCn$1NQB&YG4ujNELJTT|zl#3gqEP_JTLUr}l!6q#GZiZ$tiEJTOSc;HMdTj@pT8 zQZpAirYI0ZM;Nu9CzB9wN z3*El$$CSmSr;%pEi?fI(_wmWel^cTi%=$)h2Y7T6k&yKxcnc(_&)=vT&exI)fJ6{A zQ1{SJ{!joOjS>zGXgdRz7!eAfA=}&6H&Tl2f)?M3MDgAS@B@RUN$rD~f3<=CFfT`7 zMjr6VSRn9_3O!nCJbJ|-%w^M<1eVb*3hj0#+ z66>fHZh#+}2BA98+iln7ib5!q7sU%|Ib#ixk+0gLMr$npFIr~a(qs!_WbHH`+fE!# zWClTt>gy|3YE-TPVfNruEXSZwq?sCfib>`fpM`WX-wv~q$GBLE@5wU^o$yDI-i`A` z(znYxIrdA1K`70RTCiNK+U zhuxPX0};vXF?#McA*nqi$|6Rfy7C(?-5D7DTkO(UsPQAXPe_CBT|bMrZeDe5o_=ai znmSd;$j?Vf*0k>`R>H_ySVdfU@9D~Mg{O~{Qp|_@a!|@CuECj`It3RG?@LBT>kd=) zJ!&Zf6;7xN%&bB6@X1$Yg&fHX2Xv?Se}DXdvwT=@Y$JI#rsuwulm8}RV7(nE#YQA1 zT0U;D09@ccLXSb+WX`0Dtl*gI0qch?31lq;RB2;s5!9VZtU68XXM}Kbfspp4T%>w1 zd2Q$s_vt3w?i27KNi@kthm-wM@E7698>Q|DB=!)eK z5tW@!Sdftg6H+i`-%5^f3}j1?r^d%~k5$OSd&-wLY*NSSs=H|LN$gUY(QWwRe^6qV zlEDeQ$A^a3WE^gLXKs${Q?gD#PxQ`T83M{!FjV}R%258GGXQpJpdF<>%c1%^avr0| zT{fcn5SHBW)n~yW@l3RD{Au4PRm2VI06dli{%~2Gii}U#>`1t+aII4kpm(Ehfz6v> zJ_~}D|6_uFC>K-stQ^`dGsM83+5vXzqeLruI-);?!DpIqZ$B@sLD9Q{H=jEpvjhMJ zJo}Mf7}$gT{RF%$Fm=wQ>_|$(7*A7N0qV9GlaERn#l?z3c^=mmIHyG-pMTZ!Km~Wd z;;Tq-Io74fybSMYbxf3z5r~}Z1hSaI!umOQvPw!A6r>)o%k=>=1I%^N&YEtG=ER)^ zM0Vl$ih%x8Z1Jair+-Xo=sye}_qCPfwvR^~u%cuR4_;O=Q$4-*Ez0M1i9g_Ko*xJ9scWQ*r{y?7R;%_x)FM>f1b|;UMDqMe?PjgA-Ho$g#k^# z3}=CzHwpj+P4ExKTxc2g?`lbS=!D%5Hh!fv^f-`Ef<4ezXn4YqOw(zs{!!A97!MZ| zsB`7!<|;FZl;7~>5B!dWj{Z6z)RDj%pmPvhu8Z&$U0CO~O*a39DlSz*R`H!u7({Fzby=>!k6-K#;zF)Q-!0Fbv zAwW5a)KZom_Vy47u(ZB~RHeJ1x>Og}}Gm0qp^{sIVqdYgv+Xi9(lKs2HW@6|?3M;fJS1 zKjfB|+dfQ#Y24Ylxe28k-#4T)Zlns*x*9?;)jZ*>;z5t;4-Qym^rEwEcrVcuBxij( z)#8}CP}aZI))In=Vjag)5ttQ4h++V4i%vUhK$}BmJ#cPpuMg zYlU79L23sq*M=TJzX(G_ zD^K+*ySWL4lW@%7RWZ!Y_7?u+iyxA6Cr_=uc<~N3Op7<`rvs`E$y{v0%E_gAKU@0n z)B%m;#)S7b{F>P3bYyq@%MNd^YghCFf}I)4I#YKf%H}X|m5h6mIAM9JkILg?{C6ugK(9dR0Dt$s@&*W4 z$Ty`g4f#e_x9TkUYAzm2xZg>-3m#$RbVbs`Dz*U;s=B%bohX4)2fXQ1{=c4M=xopZ zaG(G1>yoFEyDF<`qTnOGK|=uJX0H6oLsIG_zB>^Qdw7VXThU$m48fZOB16Mze@_Dm zWrsjxnZ2gSfH?z|W2tfLVgadDa;!7Gc|2}oT*)UvoeA@;22=sH2oatX)kfxqh6$cm zo@w#wx?^uo)Zb}oX}JoWI0}c1Y3zF}?(PUt>B0A*mR{(XR?54gLeCf44FT=%IAhVSa(GkXoPK8Gop0qoYGK>baq1Vz4AK44!yFP8V#l@08TL_ z@O_B*QY2H>z~NFpdj0-h{W7BI(f9(SZNpr4&vJVLq(6M_HPZBpCQL!lDJ5QRYbhE(|d z^qJbLSB#ka5#{nN99{Wnn5Gfkr~oJ<^%<}{UwHi?;)NY$O5aVuR=ARa!H~w+lO%M% z{Ul&o^Ihgl{{+PD53w!G<=_K@rSJ8BZbZ86NdIz$l@^o3S9z6Vd{vw$1}Vyi0xp0) z;bj4EaUuXIt*WQTqFn^fj+j?n8eT0%DTeawF}1d2R9qZAKT0)>+g8uZitB=_&@ za|PDVaR>rl+GH>dw(OL%2-jMvl_J&|Dc8$phZmby@4trLY^(UTmYe^yI^iuA4y>M< z2FG8N3lN{M%PwtqmQCC!B(*KbwBo~Su8wWrRulF~{oO(ERS?G6?Ogore>ZW2KBMUQ zh(t8HIfg2|f;``_`Ruz;=ZXCWg2KZwhMCxk+qi*qSoIy6NxO%mj)DY#f zi}1ZWZ|25^Hv;YNH3obTG!F2EZM;@G=;WW=350ooOxXtoiukX&H6AHGSK=CxsDMO3 zGd&++nVpQ+Ih`KMTH&GGFa95Fu&($`3-c0A&gr^4VGYru63AQxC4-*iDy!3c_v-^Y zkLKV#9fwZ-cZphy5c~omc2$Wk_Zx--e9lMF84K}5oI$GAH7XTID>SSg)#Co5g?UM^ zL%^OsA%N%9u7JSy-GK>w$L{0_jKL>>2mGDNz16!tv0XNR(k+4M@v}6&pO1(^|MuR4 z(f)yHDWsqx{+Cf|g73_46U_qTEVvf|dD0&ro}YpM9i7Nw7W5uajW~f3zRx4n7<9gy zScZbq;X)q&!%t%&2ip-WvHxAMdDwS!g;K;@6QgHh+u{-?En9N z|JxA$zq?jt(lD*m0#N4F6bAZr{6Lh`#Qs5L0>VoeM-?`%D=1?9Aq5s;RG)%DVg$eT zvzWRS>Jlqp@#NoG{^u)(uSCE>{5DOUfeZnC{5VFnugao?1d zjmu6j2sq|j;D?aMdfrbz#-YS;#e?gvaNhHQu5|Z3-FRGj?^Y<`crhJ*pMdhK^GMtM zOG3_YEEFj%_ngndfwqRIA#fFhME7wAOnw9>QbkAYsTNDE96eeJt+^{-LmyTfIS>Ah zKBbzLQtXzwQvCe*YaAg*0_*@mxNhe)qU5c%qG*jbHXFi!ebd2<)}kp;T0QM1+`j{T zr^%IQpI1hmJ6;E}fmuOX;Nw;%Do6>yZBYxBHi7nhc@)X4f0R*9Fj3H^TuB0%HcgZ( zvD_wTd8rTV1d@{14^y`JP=pjJuydcCOZDfUzryq6sJsvDWLjn6?V89{1j|HFpm*jX zYSn}y2!$xrnrGn@s-&`wFqw^#wDnrxbJ}6F=CopsMH=T~Ur6)#GsAvJ#EhhepH}^u zm@avriF}(7okTOoy40-!p(k?Y-2h%G)x>r@S{DL3(Vy{QZu9Z$4fNZ6%s)Z$Upq4R(c+zC7>jNg8N3TBxl0X!0Ij7ZGp0qZeZ+?b`Sm}|G^*|yFT=>0qfMlr zW*=%-0dYnd+jps4tU6Rtl+>Zr$mZygF_osW12VB8gS-diN>9>m8=a?=e4Z!5mOr$PhXme@TAGV)^h-;=!sMg(Oeh2Culr8{>j zAWO(?2B8DXVEP0e*>SJ)qf`mibV%yhhz=t}>=@{$*dUT>ST)C$jdDUpuh^ zX!{stqY}=e2}ghYpnO+#BB$Tf@c=1>Q*Qh7ON?<)s{6{PpLKQIvgJ+G%MSq zze~$4)Rmt&f3L4%><11w=KT2loX%^&+N(~E%?);XGsE?_sm5E2Qmwynodp)`ATlXY zlVE{;W;Uqa(}$15=c8U|_UIcex4_9|D2U38709ueP@HKv@mX`VqN}@Lp)0Ws!&V&6 z$8M;WQi1RPd86Iuq>heD5#?uhG3u#oz9n2+VfyCV+yu@XjNQ&R7etTPeyDy;unnbp zuui2y2i6ST3ubcuk38-xZ?O3BuYK@P1N(T@Y_pJxkb=#VvfYy!V;MV!P+iO#_il-x z4*>SFJ&l^zTy1hb;=Eo;oh2qAiS=Skq9nVfbGcF+#gM`5UV%x>p);|BiY%L8#W>XUy;O z*iD^37mK6cgU%og1ABE5nfQrj>*mV+#YvU6PK%UMTcr`NnTi`9O3&#GPWJ)|NEa#O zeXB4q&qkPM4roR{uEy6&{rEWAUo!Q<>Wmvf?Yr`RH|(9iJnNK62=nejnNaMD+~pgC zHKGb6SImI82&^Kn1+i33iJ;b?PruDB;;nNu#ESEI{l;J0Ekul>zSBbAWr>X*+G2Y# zwEbIC%@TMn07Hj47Ac4G7T78qwXS`EMR+cgh~N}D#ld_0?VW%y?tYc|aEKc3oIi7V z1d{t&pc0PkiMX%LR4gFyurAOq-FfDiZd66EdOpwfHZfxoc+D!nvx9%_(eI5Ow+JEV z4%(``=iB=TLNKumZ`es_f6(_rPYlF8g(Scit}`Q^{vEIeVc)$kbfo71$Ki?jDK;6r z9Tw}nvGm)c}@_FJ+XjfND5 zY@d6uxdV0*Kf8H)pd~Zxfe&G6~1g|-S27Ar02OjT_!-m(`tMOnyj;wOV?&~$E2eg&(G{A6xE8KyKHm|mAiGh@b6AR z`j$DbYWsQqhJv@?Xn!Qaf$Casru+AY6WlS><<%KgcX!BA*26B&18}}#oe} zv;}Yn-7Wrl{MS1k!wf5^8rpu3BzQr=BGuUW1BjSHpHmo{i{HLl$$v*&I2! z>zv~tx>1W%4koHJl)b)x9LvrqRhSQte+Z^|1BBqQ06h{Xu}7QXq;ZX~X>!%lwwFFh ziH2}lvv=h+NuJl)K67NpRhXRQtDNyE9vM}+Ow%{!GWrd1qt%=-`u`zI{e$BxqZi(8 zw)5!V<1pt>_mQTa2JXEDd1fBwU_2vg&7BamlAie3Wbb*_BXj1+W*T>yIo3rtm${ZK ziOIWC$?lhgbVB|vp={rrxWI{J2SO;a-y42hz(IG7I;>aU31?=`nN(g|o3{w??!}%g z5#+6S@E29kGJX4${U%$+ST&PtoL5G{tcX-Vl~r0UERXtwr_vT{st17t!TZNeCfKMV zfq{Wkq_%fdcBMUNJkv^XEVBwej>fzr=T^f*zavvk8PcX@qirv607cxG+83MvZZYb~ z9kc~b!BJ-4i6xsTid*~GW3oj(o$4VT5AFFK*UIddlXnF&QrA6{L{OcQS|S1@7|Y`o zu%XUo3^EGeDRQ1h9{rw&Py5NF23lN>8|<&dE>45-V4fcFlWmS(JWo_gl&MT*akc*G zE+2zO&2IcLz9q+@){AUCt*bbxsi~=f7)CV!ZlF0FS5uPJ(MdAfXVq`iCiglwN@O?r zOezRfCV&4&%nh)=Xy}Fu9tONj;ZwOhW@mj`Yt->*iM>dd*Hf2i+FTQ@D?5$I<9jtp zkgYq(kMQn(@A)^jkE;zBPA_V{*}vGIlbI&5V0Hzx5yFINtGMrrn=mSZ9xin0hadr;g2^Dv(}d!u5KLL zp1-=Cc)lfET7irEOZRKJ>l_@TPLrA<@q*Gq%50hKQnOwfbOpKX99AQ9K&xsx!}_?EdvA;EH-fRAPr$pYB99R1bDY+o=yii)jlB9l ze#uk3jfAy(4TBsu-yal<9=JbqxTamk2JY(hN`N*;$NlTrGk0Z@RfFCBd3-fEzg}*A zB)r96sjNDtCf*GT4!{ARC-bO|9vc#1Tyv>>C~~oe1Ng0C03(TSgwvdDOwJeT!}R;TmA}R4Gtdgs!3y0ifph6n-^8 zyi(NZCmD?22mUQjvp$5BU-je!sA2aKnWs<<3ttsJA>nxmLpyFw6igwz*vwYS0=;b3 zL=o?1ppC2#Yx(pI+dq{s5@c)q;|IeeM5Uz_cf+WK24EaF=|U8q$B}Y$__;-fr<=Z4 zCH+3_I z1YoTidJ+{0ig~nkTX(w%4TuUi{7SMm9f)I5*x?yq(7xWAF3SqEFvA_VWl|FVxk14O zdd>}iFti`kpfyqe#cCSn2SCgL>4cHN7HB%R(cjbslx@y6-rZhJxS8Slw_O{@eV{+* zCU|J%&0pr5fzVz@E{V+oqr5hovkUcb?I7=9qyJ}45@B;TPgMR z9_|I<+*#xbYSLLZFVKoK7}g#O268JytHC8K5f8$y&BO4%#irBJpH&Clrplj<-U2^q z)iTihnu&pSdSh+RD5QStOE1gZ@9biZos?Uunn2{=ebEq9`n-yYigg%YksqL7(^o#o z28Y5XjNWYTRY7=f>yTrE7?A7fVJTzASund>>|0uR6gG7rd)e}{?p$| zQsLdZs-%==fZoh8=?N3|n60+8o}L8cPfvC&M>0Q!*R+&AGipaLyQ7PLok?GcLH0b` zMn*y5glx6tuyZp3bPd!@KB2vtHp-l{Xh}*+%3wZ@UcX%GsM4dTl@k77@ZsbGAE|&# zVNeHXre3bV36Ga-9}tjM4r8iGmF=*leQZ~vi2sAv?RWI#0QD!rhC~Lm8==x=&qu8k z?A?5=V-}3l7jE^L_Dc+(Bspwyr$gvUOkL__Y=H|^B zkd4T2r*{yovboYfNh{x9TWakx1Gz`q5(tw(WWPFL-YSvtOc8z3qDe z0yh~-m@MU!Cj$tL_gkog9zZBUsdI~#vm_*WwSISdT;&@AAqWEXAj=#8xP|e2i~!2qWWT$q zsjeTvkjqLvOk3fr9ZtFkLps#Ov>u5AFo{Czd3CD6q)r)S81+iTF$CE$fTg7AG-+*Z ztrv(buLEMxNHBOO`TXtXvPtRNEmb!_2DuIhnxX;l(xA+}$-%eJGON13zdvdEp(9fC zJf_6)>K_6n$`r#V+GIalRHZqG3vAJ*j&CjQVZek z6e%jrL8nFI8`~+QqR8QA!ZcF1jseix)i42dLD6MSnzWtSs)1*5H(fYcglOGh^9X~} zh`McXKVa&84}x6s++6+WF?!ZQDI79nnKjGC*ZuOl|M7a~ha@`8{*&ApDcfmZCM6r6 zUiv45@bs$&Y{c2O-;XAjSwc>ii#y7#2lR>VuAJ#u zR=>sfGIO=*!NQ$?I%=CukN$3%J4+_GFqAKEj&t0iB2%e~P@HUB$G$X4XCE8pg|wL1 z$k@_&j^Ewx-|_I{8zX3@+blNDI2;mfc~-(7BxrNX?SA}Rg}h8I+v}Kx2@+P+e!#bU+pvn*^`!$OgK$Wl$6Xmhgzl^yhJLPk8RIuzEPCCnmh60IwTr( zK{Uw@?=U?pIYN#rW==3zRw^L%>w2Ji zK%h=o(AkWBSi5v0Ix_vZayZ--sHyPUr+rTonuDYnnjvW#8kQ3kKTUo4E#yY0vE=`%ui+VZh&gR`OK#$70CCTMR8 z(#Wojx#-{HhkP38$DvW_DBP7oAHRBXA`)_GX}2Dza=mSxc3vXrn~>R6-U7u&5xF6} z`Gl7JlyhZ|4Iz;zxFurCfPyZ;pw#_k%ONeHzv#j853(8|>Ar`5ex_U8o6^<*Wq{8#eesI~SNEi7&Fv)O%K`E;yL9LC=d z+{5N!&IJ^Qzy@WLK|I~=1J}^#XWT*|78g@iEqB*z22K`Ad6jz+*6uc%uFNxfPq~pb z4k>Vk)bk3z+kv^srhKd~Ij!xEm@g^0GU$=5IAGBnGCAOHRDSn@n3y=m!PlETQqcX_ z!k`E_D+vPQg-D8#RQLp=0>qP70+Skf2~p9}8b)WS0gwI%o5a>QbGq zUhGFQD!9jW2BUvX10*c`E@127`Xs5rmt|a#G=wA6(Nm(-v9?hc zqKnUfUfh1=$61BD5K0roS{g)f-N7EZG|Q8zI-V zi}SDVku{6%@T~d$jgJrL>%Z=duM6(m#-Fb?VO_7pkpYj|_<+LfRn>yx=UA7Boo z-+5kA=M@!4pDrAlxDl$9c@9rLRMk*pyjvP<36i_p0Sa!d4InvyPMuMO&;O04dwsF8 zkU%u8d6nvN#=OOo8{Mlk`|+leL^4QoFT!`@ohFkMWq<=}xKE2Aj=puI&}?DRo3r4; zs!R#A0OwqdhmIkj#VBflP^cd+{=4f^<+Yn}DpB||CD`fqLRg#``wj0m)kC2a*=(|4 z_loZdX-go}LlA9Xq^$75CHl#&8yk_!=PItTFyg);aK2ZSzhY`KQCc5h3(hgfUH z9hZGF{&Yr}Bjl4U^ zj9X&VRG8&A@srJ;p3N&oxAbCC~q>Wx1R%bm`y z>+AxBtiQf(GMQ4X0IvN!v@kc z5?^VBwhTss!+_n2EDMdY_g7OCIakYH^E^yE)JMv^R?CY<*R$XAU(JtYnLL1%`tExl zY0hrv4^L-1K2LR%czx{DME!f(poh+~gEDbz<7)wM#RYlMS^i+|0ynHPgS31b0c8lU8B@(lEWN@zVwc24 zUTUD1MX6X&hmMg2C;KLYGzh{PWRh*$p=4~F8C;mj2zC`c>(q=n)} zDD9-uT~){TE-mTNHhsqHPCH<&g5F>x=UiDLI-Po_{8UA?1mcpSf-oSA(&AeS=D)Wt z84AtR+rK+=7I(w3f72DU$iZ#A(~qtp(-ZAPSMe_YTNln_yl|n@gcLA|=5)C=qK6*V z*8!U_1oKn5*SBC^s2>a;GXs%_Fm2LOBk;oZSf%blPC@8hINxMEDky5Yn|PZJ#&Q{- zBm_Tj;^^sP@nAVW_uy~5%dOmPzjAGOU+yg(I4&2P;=CneIrcSFZ?K#UR#AHll(3K= zc5uM`UAMT0)ZG{Xao#Vs2qYhc$HvOb)!*bbSQTtbU=!!eCHB}0H@!ZBl_;Ema~Kdh zo2Mar{x-nsV|+|ZuLAEvwnVhB=cU91z6%U!nvNh|N6s(iw-SgG(=_L=ySmswZlvZ@SL8A;;5)Mcbu<}rSKNgtP6gdjvW>`9d-$=gHivmV)h+?wWHjF zHN*phO&D2%|JGRq6p_1~k8ocE7Qo{8qZ)h}xnR>Oj?QAV+kAdarc~)l)dI!RD*GjU z_p?3Q{9rT^o?Z~kvw}G(CxBf^1h7<)TK4O?F3|n+hXYyR!cQ+QE>r=C;y)R&Tn3CG zZY{~WIFd!Tx)+epQkthYeij6TOdK}TfLON=lA~3k-~U-5nFrAZ!*j{=Y=OhH7jwcs zo>gzHZX+!kB(Wr?u_-Aw)8v;rbxt`jVh9eV5wyCR)jJ$Ch?D;&yqmf+iQ{Rj zTcI|4Y)SR)?oi!wCaTI*@aJ3fD1=N2%Iy_o`exRqV^tzR11|`!y{O2@FUm3T@dY)u z@oWag^ks#Oj=?-8j8%ccEWxpkNuh~=)p!6flrsZ@(^9&LU|ovx!Nbz}^wb_V_~Y0>WvBV!`admH&O_4&lqBFKEzm-v1~$+Jd&OLLb)2l?)-LAA}R*5>D~ zd(6B`@0~@j43V0d$^hMP3&%W0J94)Npv+?^LlDt2@T^i-SI;f$m^>O1Py&?To+mSC zyz_>=2qw>nJv208?bnfQMvHB8y|GcE$H#kfJUMZg=0Upxl)uEA$R*ur%V^X7+=icd zM+#G{)On&j_~{mZ-M&h&l~om^S0s?&Q5;k$bTIDKx2KwCmm3l7HPbWt-bj#rSsUzZ z3e_^o0RoN!0KsvX_2VwZlaq@-yLh+U3U`8Ej;BI3*%>YK&Fl*ld$G^dOck!I2O4IR z^aUDd&g8gG(U#tL!OJ+~qE3uMEZP3b$FG9~C)>>b2_s>`>TiHY8W=q^?-c3`j@NgW zbwAx<1ia%KOLPB~oNAyH!ctQp-a=E-e3?HF>`ql%dy~m8jE6EIE4113Dj$!6FP`$V zsA-#A7;r3k6HFHSKp;nXSM2qVv(R%W7#)uxYynxRk0)XU2EVf-i(i6@uC6s7diIe{ zja}*`X`>-Uv59t7W{t)N;=*AtQ`k|~LC#_uuP-=LWvwOivXTI|{YrCf1m>V6C{uo` z(DHXCfnvA_XcZp5516XvKd=us?;9Zxi?mp8k`|73(VLUep*JurPqv4JdGnRJ?su7@ zLx6_5A=%sm{2JP28rY)RkDmUXQhJ0=%0QqG{lbB6f4jHTV$ghd>v8gxWwhr#NW-_! zK#47nP5NcNQCE<6KjB)w_dyrI1j#@`ZHMl#jJID+#z~$Xe2!)t$-t!s(`8^Spcmzm zRruibhrTLNom(o;?2k(gI3`}P3Z-wk3{7Lo5z~K${ubD8RAWaNvv0YX1jl&V@y!q# ztRP<|6ysSKqJ^_ZINUS#ggq^kW=QV!MU7t)se#vF=+2UZ#5M_udJ*=3u8AKl9j%<# zzK!L=>Uj{34G{O>08#46f~Ct5LE%AD;IZzdLa;wbdwb{WoMUr+_rC#>Z>^jL@mbaz z*AjhoVSoyZo^ZY#{^393>H=f~TAM-1LEyzzIjCD5^iXI?&H~qFTT6l98Nh`3DMDul z#%E4k99c^c5_m^=yvm8KL`k`&g_~q1e$Z*7?ks}+2i?~JB(B-G)+@;A=3a7~eOE0q zX+%RcdZ6cDmv`F2J&f$_;VGMTdN{6w3b_rB)$A=azoTF9e;XF!XrsZyvP9n`MbMiO z{b)MM?32uWIRF!GDgXi_EsEju>&pO{B=?t7z;>>)`2I+NoBi|rIW!9uM+cMik89)4 z;2N)k&*j2q-@8LeCXzd3b`Jrg`YQ!^eXoo4X5JJyc*{1}R?(7&efl$6|IV5l>uXcj zlY`C{ifkM9=zMx@E27;ZlRLjwou?_HTNZ{bD*gD`p>5_eL?3W@F~jj$U*~q>WV?fe zz5Bc6%A~&yXSIKMc?aTx)8L{ zA2tCHxlGz`wDMNLrj{blq&W_~+)+`s>LW%`-n}Taxm`i-oCTxQ(nYtu-@kL&AKmf=AyupW*8?^!6=THa?Akkp4N@g6Ye)9Bz?K>Xa!IqQ;#8Gx&39l>nXlb^ zHHX5uIoa*iF`Y@R+-O;{_D(5YAA+aTulWMTkxXm&$;Y}g+MnEA2AK*PT=V6N7&1kI za>w0OFiJx1B^V7HMv)J}Fu|z2) z9US*dY&v#E72@AGv`iuj6TFs@>66*7-b+_oPbuasl-FN)+hDUYOpQGEb z011Sk*U~lsk={Cn@R}x#a`*<^r>x-G%y$naV0?Xh)p9onc}h7k0GboK$ub{$e}KkQ zIy5t#VRX@<=PCAe*u+!d1#MO=vc{hd210Ic&Xtsja`MGCq@rK7b>d{1JR>rXDen^L z3iWy^b7E|oHB--F=h+)Jo@is%NNnBhyzFn@eWavfMOWyuu673`u;5aDzwgRK#VyTJh7~zt|^NWl18uB$DUu=B0U;b=()PC|U-RmigXaKv? zADt{;^F|0rE#y}tH^;M&aDmLaEl8|ToJbH_s&nD*_xpTr(&kW!H((VYbjMvARbGn) zV2l$?Bb8%J5ltgUVhENZ&SEh3Mz}oLx)|c$AhooyiGhh{_~Ggj1}|#ba?^AhbxO#O z5L)cyp82tVPvn$7fSxV5dNR?xFlw*V`y#;?PUU+}Z#Z?*YbRI6@HZfENk_7?+}~+Q zVL?4(R{!;pCey)qi6}g(qABG?=v|AF0j&n!MASn5r=~|`+!Vg$FVYVKh%g+1>I=b3Q%fd}KMy_;(Mzht zg|9b&AD18iSq3Sq#ML-P2QgYZ;ZH{g#-gH>o!4}BkpnV)8drQ=m*PQZfAVEQX@~BB zq5tal>@j3~3$RJmS8G3JD>(FTBv@B3+UVuYKPWhPu%{JuYB-m99&f6&J;i-Itc_*l z(qV=1@~cUeEa>zMlH*6-z#~7y+Uorj>h89~`W8un8g3Y?^vK;5(g>W+xuA)H;K9mG zdg?|%w5_H6((kLvr&Pb;))tRRy|MKBT8?MFUG#Bff6`W-VetX#pE zE&RG=!u>;S$E+>6XBOY4oL`%mE2f=ZeN zj|qo;v%sC67^?do2~c?I=5(~XQfNvnU!mS*id>`Jt=JdoRH?$3%^WQjqJ7!hFoSCw zFu~x~hmwMNt|tPuqfmKAy*A#xpB52VSqin?Txy=0GnbNZ?2u@_^+G*sORyKc)c7u9 znD&4v@8fUYybc&WUc6)^a@Q>a>uQ#B zIkB|gcoe9X=4w7mYvMovs?MT3%nS5LLGq@X zGdBQ4B%fE98&{wIybAtnd83Xds}7sAd{|yJrPVR9Cc|!hWn|2_silQQ3_ut3e$LU& zxt93^`al)$yq&+M|8YwWa~pMqy3SOb_y94;j>CgNGG#3_NJI5bw0?`lw{0b>nTJUN zVd?i|8+h==AoNHQ-4yk8EsSAcVL1teq&|PA%FBT%56Yi3uz zPMJv~;!vU`giYBB@AwD=H%tOx2#yx0*EIv_A&jq`I6fG0aa}TkZ6CkJ#UZ-gRvp6} zRU?ZX2-jRJ(v40YZX*L#47orh216U*uUZ|!P4nuiXwTfN(LJ3#Z6miHFJz+?%bc#b zu$%c*nhZS~p%7$rj7^l!SH&<9=Rq^@g=JI^tSS#QHmQ7N48p}F@e5V}023gjtiCtg z)QSSLx8=cBndkEjpP2PN@1Rf*eQw(D!%KQWK!Dd%Z+a)&ZzavF`3?+>5e-BKm-+wu36vL^*K`jfcZLWr4dmuJ5vJ+ zAMG1#GhfY;b5<(e78GV?P#oEQn|jOAYZJR5IoTDB zzAz`39^KG46zXAi6tw%*rluUHGi}$}MSjTuFSm}hVk0qDxRwp}auRxiUr>$1eLxOK zBROil8j34jQ%%BhCskljbLo4JUk5+r55pvav`C`Id54=69=Syk^Wq&J%O7nTFi2!} z(Abq9wg9$=73kL#+y0=GTh5Uif2p9P6hCLzpio@*i&%pfk4Z*39i2(|zuVDTkbPLI zyy`{d2t3L51gNH%Z=V4|OC3d#o44tyw`@$pK*}g8J-uX>V_RB)kf)usC><8z$0z*} zr}Gj4q18GdhKY)#k><(!X}-~qGl;JsT6f(su>K*7V)_>n&s%CZ&+FmF{ryo}hq2j) zLG}(gjK}!kaKtHykP|#dsjrT_{dTHaAY1B`Ex&}Ws`iQ|k%dz|bO4|P`|I~>WQM8q za-7po%dN-sEti^7v(3p3#54@F*kt=;x6f7vJD8y+o#)eME97 zP!%;OVi!Mu9hX0dcK0+2pbMAwF;yRhY}463uZ+?N<_+NDc^U~}f~avjuNfxd+Rrix z`QtwopmYLaA8JL}ZTZB7PI<+JDkk$)Zt3M@Om<;YJ1^C5+B7+JNBWJoM5;fy%VN%$ z)ZPymEP&GNw8Hqq-MSMh0oBbWo<$kQx7H0KhxV11?+Pd^?m=o1qHq5~qG+EVEXV3I zrb#T0=~dMCpXyc*tR>SkwY3hRRY{3l|9KIcm2?o8XU7_|rdaF*#}s#Ir;JVzc7ccf;FrX4>gg zaqb_r*^kXV>F8J_(RT%?k%BP#_A)&|h+ZXgZB zP^&oWV#T6&Ssi~Of}1CP@?m(B2FaBy4v@B7c^RAxN~H^7GS{PR(#}op9U^nzc4vwd zDFi@f_hn)ce^N7D zKcZ!0r}Nk*>Dc;>Pvu4)_A`|{-VP@|`EWct`xU4_w?DZJn_va?7{0b@nE=RZH|#p- znf)t@J8id7Gf||0)EA)$GCYV))Afp=>6Mt$=O$}L)#Ta1;J)xLAxBA z$BR)*>`I!Z>gjoooJ83-#NFE8JZ97g+(EKd%Z#<;JA{j?9;{Stw1{NYO56QjBa*6?tXo!4e%& z_z|kVfYZ&+4_fZ;tmhjNy`8x!j-$I}^s;RubL&*Jv>-szPXoRmC=jg!v`;LMmeS7I z<;dr(H|ar_XHueUq--Lv;>(PK*Gz@Mo0>Jaq;3cUA+V^s5eUQqFvz)IeZ)fjyWm#!K^*U^3MbB-D<4I_St?9=;%$;CJojALkg@SD;aSyxv&9p{@m-d+=jejrchKr?Yh(QYlN2bKvtRlV_zU6nXeNCBW zVJj}kzD>eddx^Hsnp@>psY~Y}XSREmO!w_w^|45fzl}kQ?kMM&`VH>Q=ePPgRBoPg zZ*Hcie=s!g?8P>>Se2mjgFNXwdH>CQx0K7b7E38Y083<67xER^LHhp*$_UkLVc%m- zx}UD4HRSw@^qk(Y;FU*L z9Hk^(H)9P!G26JS{T2gcVN8WzgUJv;EEbjv#g^T(3!9Lc25SZjb^2H=7-boIeupN^ zd=A|!LGa(-D2h6y!P~|xWF~TdBQm4)ntB3{`wssZkNm+e&!=QsbBaZ4Jpk|a&OGUh=Ca)1iGEi}0=7;q=4L^y#4uC*w#rJ*y{)2p8z7QVf z)rqCG%`?=~M7#{UY2Hzj1JIipTdf-KzO|RHqvH86V>ne?6gFmgXLTxBU{LVB_TOaf zdmI2D@3jWg&}U+ecbu-x_1t@dulBF?eHZI_X_7Wss+_4Q3dDkfg4TfcoI1BcMDuUJ zI2I2?_2xRGe_5r0uoMgrufd8(h-(J|HvUZv?^{4Ad(Jv-x^M0xz*#H&OZOeD;v<_U z8@KS3UK8*2?O6FlQTgg2iPh(fwBD~2H3gUSn9m|EQ4lAnyhIVi262EdHP?1? z8hv#W1NFmuI=hd_dQ5V=*sR-(ZCrYZU@O*}n_n17=dD+)`PITU^N)b4?e2n$GBORw ztO$M5dU;5ScVx?B)xs(w>k`$h+9gXGsuWhdpQg9dDHTC(aGFP7tKWxrsPXLesCq!T_{S z_=NNuu6z8=ok#X6y&2OIj!@73p_V_3Ru+F43=Lb6b^ZwNJ#;1FJP#lpzY1Nw*lu*s zG$nDGs$3K{|f$v&dpFK<&sa`nunF0 zO{ZsW%)A`~v85`PA{XUbs3ZwAOK{%~YW-h~y#-X2>()JfKtMpHm5`L!lypjmbO=%+ z-JMb*DM+`ZbV#Q(NQa=(jS`!ZcGJ!OdGXwP?*0DXZ;bB@$IzjNz2EoAwdR_0uI|}~ zBqVC=XEpP-8rK`=vrXH+cPTh!N(01@&Z{JPQJyXj^QyYsBb}BHp|rS_{k@8HQpQ#9 z4)NJ1Z~yoDA2hdcWO3FfTH}g*RA1`C1bDYG_*g!*F-B>~rj5zuFM5=C7(F1l8G8jv z5UdkubbjxFFbS=r(7c93eeZ?~&}UTB-T`zOl>F(t1=6aYZQx(b zYks%Mqd5ooB!JuF3t}FdB&Z|aNU>%)zMb!d{d`n*fs*?tNI34ZwXpk|eoZK>ONu@} z?zqGH9)flg^EE|8S$j%j-liRun@Lxn)$D#VkpFXMAVeX_3u`D$YLKD%`qQ<7v-OWz zk&)jo$L1QbrMZS*wufB)_QESc-K$Bo=R;hV`;;Uc%7@W3x!m!LFtQd#Hlpzd!uly#Sdlx1%r0r*Piv-I0pn?pHZEbB6y4H6szI3IO=u{D-Ys(tlNB% z_5g(tb1z<;8C0X1bbzVGhWSXYEQj?3^NR`tzvhd*ul_oPDGR=h3?RVz1odm&D8&gT z*ZPUP_~`L={aI9LLtZmJox-zA9j888xwiI)v=u_!+~bpIbo~)FMTLbi|FaNdF8%ar z;G#L`vb)re|4{jUJ_SH{Q062#LhXaYf)k|kc7s9Zr}k#7%Vm|6 zBB2(kKo3g}!dcB+i6AUt7?-9bRtLt}#`LFrqQ@)Uk_~fo=z>Y4K~u!)46@%D2!n?VJ7ex%f0K$hy@XC1>4hKZdE9xmA#|^c`G@Vx zvHM2#(zUG@yRIuoFi(Fav*xPzrhXyn)mUkZlo+`zc>~1rs?OxMZe!8h|7T>Na;4jj z4s9mohmuWp5 zmZsolklD?6K2;#}Cge80a=1;$OEYYdiwgS{-5^46Zt+*AV&d!2QxX{nsTq zb4yH>JO!&%>lGIs)abGc*H%zc-O&+xj`_r>$oCbRr@A-&cb+V@dOaH*^m~B@A}4 zjiBbA>14+%y;xu5k4;ab>noIvv6vgRofsecIvi^}Vy*D98;MoRZF^>XRDsVO2%Ns) zfbAn0^_OMsv*#!-%D-s~LtyShjeu<&--bMFGS}?E;dx|};qI?a1~tpZ6RYTl`bow^ z?K3tuH@%9vf1_Q4@=i`<`-n(RX+u2h>~^LBJS0X@=6iQMEC%BZQ|XgS2LRgB(@_$T zbk|+?;|Kc&Q>5O}&`9sH{sCA}c!v-w55@INH4?a5p;T zQ@RLR6WY5IrJoyhWi{cZ+U!woqRmV~Vc7)Fx(v-xk4>c=F_bBzfx(LTTX<||x;lsW z(7;qC;(}K+0Z@smnp!TVQI0qIh}%!^^KI2<&nRzLX7ukCexEEw6(jF~vXYhlo0#mO zi-9x&buV0WmI7)2qXgy`P8~%A0PT7lZ(aUbW8ldqv${FzdTaC*JuBI{mSJRQolznk z<2sxP_c9~h9F8a;6nV(KdJK-o4-{f=wq=nhxqM>(UDK{|IKqxi{;*?Gm;P(>SG)0u zt7xrBoxG;APk~!@xylv>Iw>T#p++&16J%gzO$4B@_BgIs%n4MO0A(T=eMw~NAV6!O zHdZwwC`K5epY^>C$2pu=6=0 z$dtL%ddgNP{hy%WWRPCT5laww*dr}HbaAY97sF&l4=dIvRju5~X!#!I2n>SC?Ek9$ zqhH5S{<9{)1_x`Rey?lm6gTQz1-)WbeXpvADaEtZWw$prErTIMHe{HKy6nsjXeUR! zOh=AeXNn#3K7K6n5WW%e0NYY_+H^@|(dyao>LJ_^1eELJ89)61bQ;8wl|*1pzPTry z|ADOBfdpjNxtT7#OZ*4oiuFM=!7Ps|4%?c@AFc_N%VgxeCR%EN?~m!ao5|u$$72)X z=(mHGiz*jT&2qQ@WK%JKvqXcZ_PClj44VqVl6`-UltJId_rHD{kdCn8d0ejvXLRK} zB|!7{jDKUqx^ZmF8Z$V5CRe3x+67T?PJXpJtqVR<=GaqJPq_jG>GWvZ&b*JK%wR7Q z(SR>ROM74&_wy{8jDh8!#CS5&yEWB4Z;V{POkl=&&O=!hBoOwAf15niNBNRX=E#JH z{-^xqiIOj}*n$jY;*^ktS?g~fRqqm2RnAyrHyoDA=8siMB)NKxX^zc&f>sYQfYByP zWuzH|^-+V=9Pw)$J*w{y%PpX@*X6r3(2N{;S{yRI;N9ltKdr*3Wq+(!tH!vwX*%?{ zZhC_5;op%Xub)G?bPNd@P&34sHcGV!yXG)|?MWtZZxuE*45@^J^^**2kuP{J?H#niig7R5;wChmxQ)l>u>OZxzUF%JYv zSv-A9&=HsU0&r+ko_3L4VAMlcQ~KUNIriegOV1L8meiAZj*U<;UdbWYOgz)=_b%6$>RmP`G!zzEu<(a`e5P=pdmit^ z1D=GYS4OSHa7X2EfU{6&ZVbR%WD{+HPHsIJAH!Xj@Auis(t7GtrCr^HanEGz+}=qj zhTQ~)8hK$XmV`4+@wVeTAbW8F6r-2+!P3w!^hE_j#oPuj>&5sZlsnW;g%;95)8&4H zlY5`hx=VjyZG-h?tbJ~^m$WST6NQ@Oj0{%bzs)<|@~|8KQ{2FC#m|Dl{(iaBPKql^ zOy6&fLUL-iV;<|eeJv;cy0H~$k%`QVKXOL_cj?Jc(Ovn5|_EDGTgja)!PL#w_g z9{3_*hN#+jfN$xp2f(dOfz9$BpujQuoR*V_&H5clyp$pZIs$|H{Xh>_>Taw6gjg{E zA6I&ZO;M(BXVv<<#Hb#Zhm*8ILb}}(+><&>0=wdf{FwRh zGpn5++|I(NB%gW&k}|>vBu?CbLnp*$i$_L94m|S0V@|l0b_4E*p%elcW>1jXE-HGqN0vKNvIw&8E`xAji30#!*?+q zdOB19(9bb%^{f+3z4z_Z($i9=ZYnWbMdgXP`WN|D_;IEA=~mwAVXf{?kj6^38+412 zRNRoLaNjJg%LQZw#j6(3W?NNXpVjQBa~T2L~L2bJfTi+u4Z<*2@jFU}7mA zF+Pv2%HHKrrm|;o)h7+0549<1a@-P+Wk5>*J((^Og26ZLF`~0s+*#_OIR$JpN+9D> zHx6{qbc7n$FeKohSKo^pS%~^CaTvS~h{Md8y0CICDY1wheHCZ=vAkwjE+QSXl)G+A zmViX0u+QkEqd-W=r`i!{_`U$aDU_bb>2Mear3-jtcVmUi?-Hi=p0qy*XRzT36+8J! z9|=T3*GZxu{01UGKd`TW17A?Dp{dCe5A+b(}9&k#0f`5;(VqLqzF7K$|vOw z-ZlH8g97jOaps8)-m$|ymoAUzHP`3|9#bdGoZkPXQ&?2Am-aOn>G3L62M_N@(Y3!u z4i=kmEAJWh7IG0}=|$Nzp%ZgSB4|beKL2b1_}{FarT2jzErA)S{mm`VXBySQV?QV|iW)areS!rJEuN#*@yAkzZN4#%mMzsb^fr!yr& z0n2sUZG6m}c4Yy{ay~E2w(JaXzME%wKqR|0_Tv6eCT3=WW_4S@r&4BPI2n;=#h}}~ zKFAl5RZ)p~J^C)A7?Nrjt+1WGr2rFw1Qv6YwD@EC=TsF@-R69^hZgr zx~?CNPq#@PnrC=@3_vakZ#OA2dtTAPCJXAOi7edJ80Uc5tK=0)+FXHcAGN7z^b3Zl z+>o5T=*AbK2v-!*a1ga6aA-p*BThJLF~IJ*Cvvzwt66J5Uq%;2W%di^*FJ2~YS0W6 zVt2doKbIElA^^tBpbwnydFVAG@NI&kD*a)gkA?rKggrFPy`g!3YsHE-!jmd*ZLe=n zW>8-#xIv=QTM8HF=PxMUYGoM^^j^V3T6PVVdNu+9$e~_(&~X~x_r|9E0xPE5Cj4|C zb4=5DEu?2a&SuktchWm^f2fs}bB*hb-7757aWM7bGK&GniOd_}ZQN>^ z&;8mu>azG(Fx^|U0GD%ve{lisSsiKZ+<@?|H~_1^{WPj(@sIMuc#*V*L^!KUeY?_l zZ>5WAWmzRh;l2~^($}24ysAR?L>lE2`}rL+;NyQArI^-l>^Y9|v#-?eFWEez2qexF z;h<|`X!WQ!rOcp*M0(h;%TG<_KOz@AO=19ocss@)wb*+br z+Sd5RCvTHM;+H~t^|VXE5NKh3&GK3e>IaPM5{47@SXA$I`RJrr_}#zTUT?)-0c^KV zL6y2dgTk!4=7*hMzZxJPm#48uQgOb+=zYK}q{u;d5k3Oza%|r7L zv(MN6y(?%3RxU>o^vXlZ`&cByzdI>i^WTKN=U3Huv#;l}QiHC%EVq**s7@pXL8aTT zzVNv4MFQYL>?+z2C`V#+G1-0{7|_VBe*Thv(lX!1SY#1D)2Gv%==%e>x&ct~J>}H+ zF>^fJX}UN3$tNzL3q@AW@Qj68WE>a;7)#_F@CnTKV$9FW%!k=v{Ec|xIFO!6gE0O}vh2QQk9`xsPX&Nc``O5GSR*62 zhDCC*&Oy@*b+R}pJ^g%2(ch1MN#o{hzqWbIZ3O1SAP+-BZ($c;%HX&!N@13Hm`f-e zess&28mrwZ9TZ-eG)mC>)%X3b`{N9**x)-9KCjs+lgO@+Lxfp=C*u}F2u)8W$lVp1 ztsO}f1T9&xxM!o^-Q(tomczy$l;Sb^L(%gdrMno;XkiTwZXdw^F3eO(w&PKtpZ3vw zR_87;duLG%()2pjQ(Ng zlhfA|QL(Yf%ptP9qis&-A)*pqIb#}QvWu3sG@sOq&i-0&{B1Kn+_PrL0lEM9t%BI! zG7?8b#LxE+alSn84Nx%4wT9U@h&?egk&*u}*IZg$p15K?5uih_7ZxuQ3M-KC*S?2C zb(7VvC~SSfgo~hv$|c(r0id_Hb}uOIMkxC-xW^wdZ*yhkju~3Rp+eF zt-5qv5TgszKV0Q*c2ctnDS(vxyBERfmZkBA>L{88d%fwIJ-Va)vRk--RvH$yUIviF zx3w%h{InJ~?R_|z|7<`4T~a2`bzEJuaQEJrV0%AB3Bmc#U2nqQo@kXeT|h9sRweu~ zrPu>cLD2AfTt@S^YF)i1YG>DGFiZT_RGyp?lzJ#Z?!-aF8IBnrQCd>ZYi!OwYQ>J= zjWZJ1^CFLqY(@+!w(EooZu76-y>YC-I6ppG)vB|Ve%FEm0u zz#Cu@MV{!?Niw}C^mIX*rP_IPg@;VaY%Bx=@3j2koAe78%%4_`vS{256S4AUg_nkpNa2tOxB5%lzy%B1G|Is~1XFk975e;BHQEdJzY#x%p zmK75di&KA`WW(FEhf<77IhQFTh-o3R_k~(cbWfk#sG7otV^5KuNx8zGDyf|NYT=2? zhMMX5pwE@_p*bfw=8Q{rTh7Z!ntW!;3|zVD_E0K0t;Xo@zYXRdixyLi2Qu_dBFWF> zIeb`j=_n6*&m_XLKHi)ACQ*|4*D1vDWqdE{U596U7XRely?aRK9d4<_KHBS(*XQ3h zJkZfdtW%|BOy50`4L&zuH|e_TVpQ!sE%Nc;5=B7&kQvvrK=bV`(;NL?PbFqsPHu5Q zqEOkF2e$vE{#lH8G7%W0RVO02i?C>RKdejE?@#9rqNSo0!z;*;G0u@Ow#`{S{(f{n zSUPv1y8(2pno4L%8NSgXngQ7gyL{;RDf+(>wgQl_X`Jhx{uqs|_D-v|PPY9Jra{3+ zAJKYI9u3T^&Cnk@rHZoQirR-yU#61(rLmW(fvKUf5aDCDie5jSv04%}pr^$7Rwg{2 z3Fmd{43N5|RspE@dG6=wC=eulm_zp&t7H`ID*CzT8UFYe2Ic3?#0(IZKl~~gD~Ttl zgPd0>Cb{txsu~pUJWfHu)JvCmEPn$C{XZ9Do_^`G<~+aTDSmctb=C5w_PYFWaRgoC z0t*YRfvfn`mbVf%ezEdR|EFr*;FtgTs2mcZ73-t<#jngCYjdTs1uy?91;!$lK|ZsP zbawl53#4t{5AdRn9=Kj;%+jog5fgY*0_G=G>gaF%0Wy-Nl zm0amnG!XR~o172RF66Bx|B7|3b*sCBZ&x??!oHH%2N`twt8$%2o4&df1H=g&*@L!b zc?lo~fXU@AmeO!y$KmzzqQe3M14jyW~Dmhgx<8aDC%NJ@9?A$H~cmnE)|uPFT_HSFDeTSQj~dlfdgRKDOi z6pJouG(B2EttDYZDiNKoHvF`8vY4rsFd^e5@mWT&WpJ84_I(l!aYNyVqgFai-i6v$ zAd`}K1UWg_7yx+$wokeJeXDFpdk&hwEmU9)3mAy;OZ(m!(t?c6?~iBQ4;->;KNO=x z-`N1nx@r8T^uu>61%6ea3m(6k8jI&7c}!0Lnx#T;MxqNo2|i60y9(ynTIw?*a`GL} zm%%#KoqCL44lnrT`(EM0K6L)e(lb>6vbG{c`eX77S?>O^wvu=?goYOkjIMB*fv=T~ z=cwldh0trY@kT+{0#(;?L1uMn>%6iu;g3%Vg6aDDWPz0L=?r#%eD#(|hOwgvD1T>< z$ky3Rk9cCO1p{i14)CG{o{ozq&i`^EO>+(cj(@4tZ8zSxVA5~ufWVtI7;8opxl);O zrsHY#d6XCSYfluJ+3=J^Q&Usbs#1lcQlUqO_wMyRB?w82r^j&8;gXe8c<*}YOp`yV z{B&{AaBSh*z(4}PFN)_IZb)1oz}=5A`Y_c7>mT<fW%}Lm5h8bV>QPV2xJ9 zB6p;?vcY7TZk5Nr*2STea;9$>dZr0hb+FTy0b>gpYPyl2W z09kYP7T+hkDnS%x4z#lNVmsCWi$UV@DZ55OV@CX>K5UN-3q|1>F` zDEST}a=7{0kHv}q&D8T@_FJB4(KmR(@7r(-U6)4hkjCqxJi|5xoe)PdG5aP9%^q%$ z9gyG)32*wpnW8)2au>PC>qN?W%{FBxxhfhu zI{Hc)ZcbV4YT3Awi&sErK^M}8ffN*QpaYD%M)KqdC%7xWuG>HwIu&R=b$$Oo&tanP zPw}9i+uf`lk<6+n0R5%MQ3W7Zb{A%e)NpOjJE_7a+OToc8dc{KrJ{bTyxJ;i(YiP{sd`>1$_XUs03ZOXmCPHMI{fmk;yh&0dFYZ&!)^tHf5Z^qL?< zMMW?KMZH!Q>|13@oki*&OY69J!8Az0#Gq5-(WRP(2Bsud?$$`Tg5N!jE_`&3dLLi< zxR@9!phj$=c++zuMTds~ojlv;zWIk>R(z}GcNO9 zPY>4eOyfWcG1|B3MtL;$3j%7#!+>@nyDoq_r)!uoqtneIrIK4HTid?;yn;lpEUYq za(JD+Y5;aU%e<|p5m2$Pte@J3kV#->xXv$iQ0l5?G{`0l#VB5s57cHNlR@Qby~-9W zNe2`HOjvk^J55`IuloUGFL1RtxDB00s>`T!|Ew44)V`wfg!^BkUdowTT#L`%)oZj0 zTc(SbE3fVS@NIA~5nL>@6D=PeI=ywzUVE;p`iS@EtGE=<8X5LQoni)DExC-O7q33M>U_neYH6vroCo5Yvf>Sn|86Z8SgZ=fFi5-pk~GdFj-Z{ar(0VE@9BYe6e&_r7!9_tP;6?+@cq{&!m0z`l}nE!u5=Zq1Wj*gYe z%%YdLIaie477tNqaxU4t9sDnec)iP7&a9?^Wm!2zwQ=tpx$4`jV48pmP%;{Z?O8Ak0BDyw zlAgJ69*5H`Nn(p_1{?mI?b=k%F-`y@oKXcCe~+J^ zzsmdaHSja=Tn4X>tDt8*-Ura_H%ux+xB+)B=N<1_c`gvyoRAfB6crVj^uK4=1FA^I z;m(2#K+L7%S-<^O{eFhmQ8J!P^?iICCIg@O7B8sfi4`8%quV^Tc;t@)RD6Jw#BUc| zn~N!Xa1s`!fj)rTtIf^LbWA!!(ZmSJK|vxBw$a`5e3468z(G};$H78A3}kNx#S<%a zOt=`6&TcDSuf8BVyg*sx9U_bDvgJ3eBzG|J>(yXFFqxGk->!jTHa&3e3bIGrD__Td zD-bIhj)M;J{`Ez0(sLQs0`lvyAb}42!dk}yz}f2!;4fDqu9UJkc~!cxj;X# zHYDhr3i$7Hiat&q+_g@V)?q8T?UywC41EubqY~o3rt1nUCtixP5>Qx(lQC2rd`R%e zj9ZkE4}Aap48E1rHF2%0e|#(M7%cRB?RezHTjEG`hpnfp596(vo{5}cxF5W|PXW%g zT0D75Is=Z@mvwf+2+52T`T4pQGV~`>m+Rd~;j~lUH8nMI3gTxa^H)c8{cnUME?U8u z**mj&Uop3l!!bs(h{rXN%5TigOs}sloq#UC=)mYZAfdy9#|5 zkIL!@Gm;Ul0N(Vm)1IjW_4?$!^2adphg3*}xacddmjg~AX!jdrj+{cx=G-B{vGkUh zV{s3I!@CFJNo+@h6NSP@h!dr^k_7&jEhtY{2yJc)_$Mq1;CK-zj?gdXr$u4K}Ua%bC3yG zM7C82?7wN!ndGZ$_<72Y(Z!53fZA2EX#tvlhz3A*`}l0EZ2#^gFhG{2pdrL{=_xyC z<>gO_TQrV?_RK+OOdO%zdL@o(<((;v7U1`3;EDYBfM^OcI^9$>-sV5zVfQ5pCiZA0 z2H?pxhX3M|S%ek7|DDi}63ZA9*c$S`V0}~;g1`W3Lo1iAQ!WAUxYY^BT%@a0C<}s+ z91Q^=3oDTm+hELbq&iHfMg4S#>B+Nja?3B#+ILZx4ezM>TOMVnZI(4D<&Bd79c{U8 zsYSEKzNCoo0aQS~y_|3V@ZuYwZVOl3EBstBa=S)_GX2KnOa(GIt9kZ}_o=*(SrQ)Gwl7$F7)6a#hX<{^E-lF8B-smuk6h9q zk8ut-@o2_b&=LI)$N4z6kiGwm$P8VoFazQF*S2q~?aW&q$U5inzs^rIHWdO=KqH&Vkr4>Eqi`lc>RSpl)vCyMgr&FdmAE79 zVN>-7&9}CL#!R(NN6Pg@_}5aMb1N%Vu1`%t`L> zLG{5wpSxyV_`m({X&H`G8cVN)IWF}SQh8q>dgXo-b6G^E`dppv0gIHAE^xVARib~W zNI`|;gbqq@c`nCDtC60Rld#VWmRx@ih2gk=JF9DO4$FuWWxlZzvI140)JNaF!FKfr z4n`d(zcInmbnhM|g}Se)gA=a=Z+|v}FzG)qo8mZipNmcH>8e&SZIiVrv*pFh*_HP! zhg5{2b>DG#midwWQ0hc+zU{2>`;xL@Ovym@Nu4KVdTcq9gbn_iz3NK*hUXg z|NPoOVxc_oBknPeE5m{bPoZuG4d8#e*(g8Ol9i z)E#4P^YJ!QoVs=vkhRYxi%P36TVKdGetPBlr3X)jGT`x66ACKseX{#rX9V35!@Nr@ z8+?%hcFsLs4-AMGLDMSyojSw>mt7Gn=en}n!@9V@T z-@#F7^lV2TUXCe^61|uYf(eIr;}Z(-VSb45HAi<4@qD-6C*^ol0q$D4GavNbyWAA! z;qYEoEDPkHWeyN+;hr7fU?FfH<#(L;U6HH=Ur#u*H@1C#||sotNT zP(Gzc9sfRF6{IN1f4Mm-@Tf%4-ZaSKk#IOxq}1a5z>+79(d-{QBL6!6w5B!tuy4Av zXlu&`G6Z^pq+$zfgCmoOG`zVbyCnv~EbSxUe2k#+-3m^0f1T+x+7qSCy!9zeTiU@GF&ulN_ zTujG9kSlC9?j!#g)N7w(FVMg)Zk7+sfyBh1n^TIf#yn_`A@~`ej~pDrZr~Xm^iS@9 z551}yNre`_D)d=+&Ihw+B~Mh)6TW{I_dTCxnp(-!7An~z$Bk6DVO}rXL)P}90FTvU zw~z#0P#2u$i|M}!!4F@U=J6|o$IkrS9;BOEwPU2hRvFq?1F>1rg-0|NfLA zkWAy--G<(^0>D=oZbAQZwMa6s|0U%0GD97vBx*`nj=SJ}g!Q_VT*D&>O&S6rfGyht zq|%lsEf07pS-T?`|0e*I=(t>9g+~9YoO3#OI63feDsp$*`dUf{i|}E-RbiSKVDN9Z zLSrNGHs?>XEBCNJW7Awi&Bp=;s~dj@$p>&MyC^i%oIxJv5CHy4n%-r!XAXKLIL$NH zeMY1m^TDOb4a4{~SqI5Kb7qe>v~do4#PGVI_JSX)xY-8&|Nj@O)Sq=bw)N6T?%su3J5r)o>;;^+=|i8C z7{4kAKIuJZ$B_MAEB`316&fx=(W+uPXsx;uSHIR;d4WlKgM-Ml&7xGF31_>*x6|68 zbq^L2_6f8)uc~KKLAQHf$Upr3(8kBoZD=Vu;?gu(`$L;5L994PJ)OEO=Fk4E78Nbt z1ubs0r^vqffejrG`*G_EG*t;{E#X=NSWV`8Fzk6W{02 z5lQ5}>>bknEs}Ogsvx$gEidnOst#;$Hc64AIbmGqaQ-w z91%5OJXFw0!~f9NH=*&^GezWP4f}iQeLXmvIrl_Xo=ftp7^3v)Z96>{1uMKR_`erI zrU1f3qTOlh@q7e=;ZyuT{I)t}w0Ej1FTvx}8lE%T=<*nl5N2NsG0}TN{UmL_@ zD=Fd3DK+mJ)GMvIRI#ysJ?AGS|8}F{IjK4s!!2kr`@-f zKlq<~xhm>3XiLW^892rE=3SM`?ZVn@V1IcaWAHPrj*5Fpt&0YBJe6>73|4V^dCUgK z=FL1V7~Z(OOO*{~I#Bv}VY39=apQNG+E*|AbtRPQ8dXyD2>M$$xcw1E{h6@SvOCDB1Z2pE1#3&yLI3C zz@}Qf`X6WFE82AC*&`kt15qnDQQp3Z=Y4dW$0r!=_i%qv{Lq7wQ&2?3P>&1Lt5ZGI z4gB(Y-6QEP8jWIVZgI00?ex}eOLyg5C0pc&h4{;@e#7|h=av%%VYnvf8m6+0n{t); z77yu?1{Mwd870Z?j7&_RAu`(9M0=l9+=ov80)@8twCNAI9u%6)pKqW3PVeRTO(R#sLL;I0yKAR?&pR4yhI ziClYmiUh_)@=wN^gv?`CfLx3*8$|)%6yP4q0!rOX4>|_T#gC_nWszm~TFC~#g}mJ)Ni0^?ZxwfainlHj|GKNR7V&QZxBdE{Bzd+jqvMQ$W;->qN5(sBFgQlZ5Rd&44`4nV|* z*C1^%X%XK#-TTTaP$d6k%^jE%Hr>ZRayp%Cy+SP>4@JH6AhV(2#j1NBZK9~!2lPs) zp+!vm6Qc`2_kqVL3&$XbCcXXAWCy8dldaqjnj0sLm^LgnFbEh|w`UJ{XXIEz76v^Q& z2(D1K)OC5iC&&y`~Q zLy~gb8#O3iJ)qNm`EteY%401p2;{AQLBdZ0#RreI1Asx-Wx$|)<2v2+6_}h}z=U7+ zYbsd4fp-Bbjo(11{dKcWQc2vP;dJ%G@X*lE_L?{)j(E4arfy(;Jzo=Yln_EPm{^>2 zgN2YP_2RJHryGJk*Ql@d!9hX}ia=yb=saM6pRCcM5aG&y(?o~)`z^Qti$wYMex7U4 zzW`E=Iw=8v$wC6vi89?VpR4^0oK#?9#?lOSArZ%NoxNaK4X#(056ZsJ_4&M3ja58B z4Djb1iz&tt*s8&YM+;#+g3ZR8rg2?$d47m|U8M^Y|lRv~TxM0UUt3OogA7tGdR`R5Br#62a#Sj6Xof-1k z;(MIG{;9#VTr0Au-o2c-yXjH-RC9*Z$H<`e%mLkXmwVjw0;>KYANQY32vSoo)o-9k z^Ss4jf*2`Ga+0Vaza{a4R)G}l%+cTP_uX~o^kB?eDlU6~PyNLTfA$mbim(%zuQClQ ziN<*(`sx)IFecBd10EaA{;{!m5aOx&1$W$$2j6u#ziH4`oqQk^2K$<)-|GFPuP>%S zN>cJm!@T)@QNBQVBxC*B!9gRIwal1 zBXE?v*0Q4tNEjIzW8v>{IJ-t)oK#FIkvh!0jGLL!Zi36M=?LtGfXuH6fuad@W88qk zVisl3;Q*C4nZp4wg(ca?cM(g{FPiwVaWhq#d8anL6hdLI^~F|q=|LDA8EYf}ZUP_b zObfo zZ&HBbJ%E$d_4H}WK5p3bu*^)I>*$b;pH}L6#;2q(me1jd%f5I)d{bLdPjGJp|GKs! zw-WMYSdRsc$%3noE|A^vRBbsp-}!#z$$X?*`YY4PWO?&>0^D-vm+fl7u#U;@^j5ja zB1%t0W6EbYJD9gwl*C$UqegnFjdE&uF_UMU7f1$_puFj_sl$vwi+F3(M62AcBo zxmF{0`YXqDj?&N7sDlsb;dqjFax zhH?VdNM?D_2A&)odUYav1i6L1$`l~yudqZ0*yC|s{{YGUFeKVHi#+eEg|!5RGs z%OzFr-f0TF{%KABoV*~gUa-Tq-|?#oI^I%yH%0?iU5d^FI-rftL_$s>RMvZ0L-h76 zH^)sf8_nTVA9K^GrJJ%7CI2(dMbuQEdGk)>%NPzjL8G(6HBGUeNc^elgXh)hPezNS z5Vbb(e`Gc;_A@#za$ubn`rfBc%M{lYuM(i2)YG~f~%1)B9hDnv}z0)co4o0U5(+s zAG`4#wNBJ0&XZzY6MB6eGUw6NCgLB}IWW;BSrC->v_wlG%3J*rgx{W1lN!_0Jaai= zbK)%tGQ5f>6G}rIJ>x6+xhe-z5<9P3LEk)rgE2LkP}NAwIw~^ns&}av2D30KC$Q); zmKUc8xRsUgK;9V_Qu|=!C>Y4Y$%ROO#~&3a_tIehQlyJ35ytiJ-&^^*!u>KE4pop{ zMF@o{9vuM@n8WZ>LRsTi?2&9FK4EbqmZ&U#Crvad%J6%Ebnvyo$mPb6pqV8G2%}|+=K|8n~85Zdfs!?CK& zyr#cGl;Ej8HFTON5mPs!D1X>J8>``@WxDUJ%4K+)sW*mlv4eeV+3xncQqBooHY~t@gPLooj8@txz-mCK|z;F~_5z zz;?8SQQ$d1hz0}!&H-F%_#BhN2iy~GxI-oGMgq)&wqsAxIZ&FcufnZ^eDm^%tz92G zPv7zLoy7pDRK9NIUp>({MhG?}>*x3rKGl-=V6PT}P#FY}fj^tvBy{fNt>(N_X-+w1 zOE5?0V+`e+8Q^^3OaQ)u8-wp$Sd}wq$LQ4G-H0=^)nWhzuph;T#`jzz6jrOl}Z zNw>3ky(C!6@+VU-q`~6;Wl@>L2ts>l3=55$q#*AlJC~)uw4XzTEAs8H`_G)K(K^MU zHJuLD^yVbh_Iua#H-hq+e4f0a#n!m)ACDv8ww!K96^sG`4?Bz{zxP^jJ-W#c*{$B0 z0^u@*;*sGv9C3H`tJ zorwCngxNind;KK){C7W^J@eXXd8^c>idy}#$frqYIax9 z#Rcbas6!5yfQ(ucd015lHO#g?TnHj1j9l8tP;nz1xk5E9@1W>teZMvQoj0~~uvx$4l2Wt_4-(G14o@TRJ)DP9v7Sr80*!6Cag7HX5f(m){~J1)>D z1xyz?ER!G61)>A5Wq!61`njct9Wx{0F4ObF^m?>=An7h7)JHaUsE|`3?omOWST(cJ zIxGAb4hMZR8eiMo(9LNUAfoG7z71!ni1{iX*v?UPy}=+7ZW^DpB$%gW;Q1S{t&CuW zN)S-60nYXMx4x@g_=W_nn_uX1k0`byPdUu6Q9`30WVU4cNg)`w2`mXR8Xic{DXB3$ z>ZGS~;IqdLeMrJ>N}!C8?8B^j3;`(+l?y=185L}y^C|j)?45Dr*aN{rcvEhf1TOKk zNvR4sfLmQD_WuCaQt*{Q5IKJ$7K|08?p1Yniqp^5!#c()RWj!!U4?(_k@N6l8QF)S zzXDK#W*mEH047>|;=~!PhZeE^veqiHk5Ha$6T11hG z>q%4LD)FG_=u`c7`j(OlHaz(GVbbk~Cum?MS}G$`pALc@bnq?sF<1x}alRjK@;Enk ztKVGLI`>!y8yj1Y&#`yfCBc|h;eiD?p2+UH%B&7&59UA~H#Pn8^YfjaujL!Rl44?z za)t|-qd#a{A6E1$j+$!y*)b6i1TItl4$(pH-52G-XWHQqQC4rCukKj#fZqd^Z}grN zLY&Lv_vLK#cyxpdw%Iw4%s|;&a4g!P`9Sp(eT|fT(8Tqboal3Cm0pFMB|JF@Q&f3^ zU90IQdezP>$wT{!sJpkjn+hm*1HW7mKiUjj!_j#e;Vm(8f$y7W{@Hx-*3oyyZq`kS%#~^jjmL({zP^lBb}tlU^@k{@NzHFQ}({ z$iS*6U)FvR?(DN0vF@mFvyxDMk&ZBd5p+itxD7I?Ata>l!4Oc?*J<8qfj)xtWL|D~ z#;E<{j|^}uj#SNnWBX#q4eY9r!dNyiB1^pU7GTZuV1qga!{WDEuphv$GZ=uaW5~Pl zKd4*~kM>f2u^75u9h$z&Jn^7JtL`~>&PiEzNE>^R4P_NM{RlDf$4yKyon=GD`a+3-ju{J1$-v z{3p-HVn6F5E5tGx>tg6j7O}G~!?JguW_>iTq;g4Mqu|WwNUodr2Q_`k-tIyIL>-&h z+vm6(hXgWy@X7qr2IBAhO~cK`P1y+XeDk&>L3G83-hO!o^B7*Ya z6tD%C-hj3f9SjC48v-Ct@I`5aWnw^+?o+u>c2_xhq1MH!fO9GD_FPwP@{+?DDzQ^) zyuO*y3Zb>*HMU;yU?<4qr#8yFz|L1Q%qUV%J5w9bCg2iSQPwHmjNuG# zhw2TNl;l#< zrPLxVEh(V_E=mYWBMs6ZNOwvLq9CAj{_ifI|L5mf&$;LBvisim&YgK?=9!s`#7LZ+ z$a-55{3yJxDT~fzvin=hDn4271dfhmEtTVMC=Qn{s~9h6>x~&Fz5G$@J0ccAs0I0% z2DWs5lEM1jIZa_ndsFDSCROJlOZwD9kSU!he4F44U}L#v-w0xUps8IqHu&Kt6&Vr) zY%Hy!legMNan13s{f2FBc1Cb<)N+S1aYiftp2ci1#m@k=-z8!<1vxK{yZ1Hm*dz3*VFX5>6?x?g-hmQ93HVP%{1`Jdv0?yWKmGiwa#hHjs(5tz}-15^pHx!N$J* z=Aw5{i&CpY*ftZ_T9-K8XIswwgoBEtxY(YPTOL|!{*XrA+4M0ltj>O}ww1>jGSpb~ zsz8%2_kND=YzHDeRvm5$y|M`!NSolc+|#hI_WEs4Fv|JdyjNJMp+g@!iV|Ce5>he*1~?_7b`NA@#wrV1+Ba*DiBvO8QAQ=czNR-`1O46PM>RT8 zT3md6U!yomkV;!`9{tgyj7@g*gngJ7rQ{Hc!cBQ-@aFSJ1v=F~B)lgnBe`z9ctMT% zw5pidr|ME*b(04oryR$WW`^4rp(dU-2fstaZakAB;=<|>`AHF{HPVHcOT`72XwX2FHX zbP&0y5ea%r+LV}}|Ig5;b9nw92 zTW%p8HXwRE?aaUOPCAjq1LxCylha>Bf|kUgO0kff+MnD(eCqjdOb@f?uzgj|%rH$! zjDE3cLG$hx*HPkrhR_&Hm>`P(P&eH^Fk6PB!+s;V_T?6U8Aj4fynA9MJx?9wfi2v)N&tXp3JT&!d&*)30$oy5L)PPuirLS77Y<3A68}FQt`VYvTz!B^EwpXlQ9GTgkkHRBZK< zJeBS$>}P&hjBIUDgw~I}y1UN& zI+QRheJ{1g(oJ^SLp+@EldweJo2oqJYD-*)H@Kt1*5Qfz>1@fr-CdkTW}O+MS`kO+lBiK^sCCkF@F z`FK?SowNMfr8k8{_V^u2d_3)OH!RKzeJd!qr7x*2eJ)W~w|U!|&5vn(qTCYVnc6vX&^QDGR%=0IE7fD+zB{PGBsrk)`OmKN4oPq1!KMA#}UFL!( zM%V3UIOZ|+fQ#!oTZ?~1GkUFp1OO@$u+5Je%IfM6^^_BU5;T%&=tHBQv=0r9#cbCY z_9iq03R}8U>XOLYdVOB{{J?>O@3M<9m3>$df7?wC7Kc&jGx^!69+Nc!8stFICWn?+ z`^?0-s|0OrCGbIYrT5-#3=Af&KKHZj2$#fjE9N+FYv&omgz20dZ9CT_x%ipEgCf(| zZ8upt7AQYu;u%F~HReTAf>`9}mBc9J-dHm|tkvgJ3>emm$h zo2rw-GUTnN42h5tGf%Fga+A1VTss?l7xkSs;6UwkL%&?2Ng zJn!h}>!3$330?w;7Ve`P-lxa#tJT;(ZHTn7sl9p83W^kb$1Uc7$O4ow#z zNeg)V_0IieB7J(x{K1f~GK@nbp|2|~?Pr?EG-j(AoCogn?`^PiE5@QF6G=FuQ%~Bd z%KKPu(n&ld?Q1^6SDS~&qbPVi-4RH#K5JAAq?2$Il4IAD9Ua&jQDYSi5TX`wllfh8 zE9_N338_;DCFrvKN)WAox?$$jE52+#!PS~g%wPk%;;7mlvzAV7P!n9db zXJ1_Sq{?1ej!iS9s!Zm>v_tk9)O2YbnrM=>6V}!t_K^%+xvFPTI9o; zF1t2vKk4*tXpT4PG{%(!0-xT=dJF%Rfw+tGOU)4m!ordO(%d0hQ&LN+stY{(o*I+F zRU?-80<#0la7Ek^mlBC@m+;twi`{A z)VOwgxGgNd1c~Hy&V=IR$8}xK?}+153lO@vxOAVnekej$p-T^Y_lOPZHW3I^fj@dA zX7BgpL-@rF@1owWy}D%gP8SNM5;wPoEIbgtgPX7KLC$5^6YWWps|XGBi7~;-8@xAcrI<-i&sDbEoYgY#XZ2SO z8)Cx$iWd50Sl67bGhR^#R*`Q8tZQ44kJQX9gE78SQkS%~c#pQhhHDW=kQb9hDP*k6 z?|FA0S<28;l41P*MbGe%h;2XO8)aomDpQ#u-~EqF%Nd$kXx0xaob4n%wOLPsK@2YQ zirvD^l|rjNFl~k%-TGb|6qg_+JG$U5jvzX8_5w2u6N@Q8reO!POt}8` zdR(wQU+hB7X5sToaZX;!Vi%W!+civVa|}UjCD%Uen=o@3jI`N`TSFVNR0rNDuF?qh zdTe%b6jyi8h2KBtd;HxU!n)hx=+e4II}K1|YLS``LON0iZA`8_CFFXgQIL84z}cm& zVUgjF3nP=4#C3L{532cz#`I;wgS^s1Nlw1G|E?p z7-@tlEk%FOeA%?)p)oK!Y7eKR7pJR9XnMsIbF*gu28C3})b103lLI`C?AoN;@*p%O zsw9KAo%2(0QvNIOeJ@$_QPGm;3^{+!y+2VZWws@=zx|w3IL1&lzc8xpJ4qh;KQR4D zC#$tME%y`_(n0jp`5<8m8_(hKw+H$9WYaykfL1YX@0)e)3a&MRbncj(aWU$XJ~)l1 zwa*B6%Nx7wLNeNBIsU%A(EVgGUv0@|_?rT$4(Zn2PdDk!Q^QNOnk{hIb12MYh&nwy zoe|Z$D5%E1^c(sB6nxS6MwSs=plm?l2Q7s2Lo{9K*jU8eNK1w6GNPVc#TL1@1`e+D z!#`SrWf3ISLA0c4g@@$^WwyM{iB?_H8}dA*c<8f@#`qrlX(N*#9biY*_@HCmM8;a< z?7s`&m2}N7xAXH3Md~!Bb&w?W7L`7*^y+bZNv=S8cusQcI1#{c|DzfKSY<#a6__U{ zBL*by^UG*DV5QE1l``fkjDN-a&A4=?-Y8UwL!(Dl&-(Enma= zmKbcwbQn6^zG z4w?SMH}wKBH5!`Sk^0r&lLv;z$#sm4jd$iA4ZeB*9ydYa7j~>-4$XkG@CwLfcL3U$ z02q{}@S~)r3-NJSgFNJ2K|xC>2A(^p!dwJwqbE~#%l9j6a6sk94j9V({W|S$5bkup zjZ)m0P_KFK$E5ei-!2579nlgA>3^(|SsnevrV(`~JZ~Sr6T|NCuPg(%`kQLY3dq26 z1Wqju^Ha__6?K1=N(vV3n7fy#02~nENbuHjt_m$y8&~)PN-S)nVgu*t#`}f<>p3`V zl)VSdRqZw%V>p!JX@++(lEh?XtwS;s7zm=&Kyy-3R_?}Gj+UIzJeRj&2lv5@WN746nGX@sx`g>) zoE&Twf}%~QUtg8Dq4r###!`eYBy%PeZ07%cOkR_q(g6a&{e1?e>~^9DF+(^^3#uOq z3a&ZGjv}Ml59Yl|o@Hkfl9A;h6GTuYSKgTcQ8jSON}|{koMGso%EKU3dAzzLhC`0O z4sh9$($ixAw+3)^@Fp#SJ~kSEpDMSm-JdY=01a!cL7nffbUsFOY!q8i%vuq%>=tyI zL24G(^6+=Rh&3pieLpZr?%c~vZ{53`@P&9b>2---_Ebl*^!bLCZb3bmOep|5Z?1HZ zw4MNFQ3v3Mu?Jm%a$(OhaydLiCJ&LugB<%wpZsKlbagN>Wh(A|-l&_mUTE@HSFd1V zB(C_y&dQ3Ra>kVW14@OUqW^gaQ3b#nz4;5r z1uXZ*Tb%+`WwP*h?}`-yVPdg(B^%$KgHC`Mj_7s-g^fJ$DH(Pp7VGij!bIYi+4lVq zYn|OP_a!-4HzSvJSTGYD4BcKt40XyAEaOtvvL6y-n9XgSKZfOu)%Yi@d41Bes&2~0Sdq+z|c2e zFcHDVHUY}hLEd^-Ozb`m7m@;of;!NcAR*vVY(C2xyS#83cmtD-I|$1!G@~>@$HF2Z zC$CfVF{F?;=<@ge{?ggM8`3g~?W>0f%6{#~8s<*#ikY8M&dXCGv{QKl0#G~QI*sK8 zgaO1f(o=d4_7NzFLEi`+BjSc$=`_0RW{MU4s`e$OrHNC>q3F4c;v%(!S62%=P)qyn zKutk2a#}{f-4w9yid~TdjaJA(3$y4VJp|n{FId;WfUWeTe)XB!99s&^L;@$Cp#7V| zZ+^dF3_^VlRrtVi^dj4PFJcmsy!<{;!=Go_2tA*&PUvw=0X*RQUQ8t?#G$=qmhCC{ zpAcymDVdg+he_;ji}eu(fxg61-r3nr3%W>YhMhvg+Z7yjH~0MHhmWZ#&B*9zPxK#o zKnlj3T#GeQr479nqC|Bd-A)^qP#H>_Am3bQehwg0NDWnI0=*=zBHG~xRU=vgYZr&s z>LRmxK!#F~@Ssd=i;#rD3mDTqHC1Tl@OEulLosOSOD&q|Ko462IB4q|79KwRsufH- z*?Hc4rf`BRCR|egINPW+NJ0T2neD5`WdwbXYJoCHOiPQ{*>UHDm;LH!I1SE84xRwq za}R$7py1?3M*vSqRCwGNH|MDF<6{TXQfi$mLi;}|`df7HCuC6NoiD53r}FQ)`3fGN z1`7)l7|XgKKszt0<{WJ|%c@#ss}fNu;)IOkDCrQ>p|nr0e|Bwy_sx zgy?$*8l$BTzC=D7Z_r%aRLxVFgnrRaio#6>6hPtxsgnXyt#7d9{h$kVpotY^)V6a5 zpp`~2kWQbpp;d79r`ITc)6DW{(}-2BND15sKD+@$vDuX|O$^4w_60N)#a+fES^k%s zK{-Zf68^&B?O0C*gua211cj9#cQhY%@m3o$%%R7c{kd)P)-A|v<_9kaQn!qE1_Xum zg?Bxk+dmZCg`BDTxSP6c{Cq``o%afn}rIrpMK8N0=hKj z4mX;^f46JRl%-?& zI*nkY`hY(BPjZcvq7S82Tc%#i1j8MZz8(n9BOLTv=@6Iz2J$m07 z=9nG`YgWhCQc+R4{+7OX2Zo90J^SZ1#DkI$#jaM<6v7-A9u*Tm!NVcRZmwekiM5>d*-14>U1U4sT#!dO)`$wR8;B%6 z6?^GA%D9|LK>2i*X$Vx84ErIM1YN#<^3E|Fl{bWwCj>SP&|E{%IfOZ z_LovXx>Qq3lcwX z!^t_yS@4fenLnF&qsH)R)6}mBSINq61H{OLy#S)uzhkH)cV*1Ae7=5)(GN^%?Eg)#e zT}T%!z;uoA4P#*ZjQA*+9T{UOI|`Hq@kO7B8zkrnN)lW0)$?EUjJWcZnBgSyW~G$b z{o}SQ0M2Lbx>vyJt2k_-eMNhYpvxaG(@uCk-=MJiB?GoXD~;%HQ02$8Xn@4w)#umu zR9C(DC3(Wc1Lw!4!s>J4UO3-vW|oK}d&Ld}I4cN~d3h!CMjKp{q~K0Qd1)*DO6ufE z2Qn=^iq{c;buIOXa=9b}F2t3KFMQ25^nb=XX}GN-awmOQTR*gp8C=a_mCeQfubkzz z5~?eb22c*;W6EaQ>sCAzGo&w8$i5Q?G32Zr$qVcR)H4Z>%1tUcX; zW~cOQ%D&TpMYSEZ^ zRbM@4JLtf>IN$^yKHa15Xtt9mr)r30yo7VkYvuUzm8~cKdyz7zTj+Cah&04LR*;PE zwsyq*D)@({0f~7Ffz&}anyaU@hF0Vj!M}rL+|6Z?I6?tI06Ag z?is$n4)t#^F!Y5k4nYHmc9WbFQpcc1+L#D8aj?(C71C_L%_J|U7t_tJioN+>BBJ`k zz%C9*C^mwGVxEoJR2owE$y_3{LrB7yN$fB-0e~JN-hN)kDC#P%e+6n;{04okc|_U% z*n?|0N8Bhih~Q!1Mzsjx%a->fZq7w(ig?uA#sXroio1?Gzo;;Ry60CvJn;K1ayew1r{9O!-Pc z7YBSfI{T}g^_6NB0i~@Yl2A+1ET0bCd%l$!hQUh>%tP8{5tZ}TmDTJo9j=fH&eaIa zKRQQ3RR)>F+#bH~UPgkgo=}V46%3_}Q#_7TR9DC66q9XvK)MYv^wvp|>E0J%U=SM1 zKlp$Mt(gi(T#e=c92Zbz+X!=c-p^r<)w@2*Y0l4ftyS@8Y&%HmBQz7)Y3<739x3sBB4m3!}`;g@CAdTP)O;=e;UtL%LA~)Qfv5a#G zAD%Ej$XmFqR7jit$ABX(`5vUDcv;2UTljNt@8i!Q(mo_8)ZFj!(oXN2!BumPuP8nv zUY3vl`9cx|0f~DV2SC@K7Y9`fmyK%4Ie$CZ9IT7NfZm;9^WXtjf8>@vTOw%mrS|0* zaH>wH?*uyTALO0iA}B;qff27@a_q{gDhI~6m4`#2zHMNEaU}9oAOT%K<{Ljy_EW*Gl zB?dE@|JL6B|I@z@>|cN#yv|2(?{6gZ*IoMeDt9D8F0o8Rb@7E)^t`Tte<})^kPGt0X{m?+ literal 0 HcmV?d00001 diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index 9c03b085a64..743350b69eb 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[bool-queries]] == Bool Queries @@ -29,8 +27,8 @@ var searchResults = this.Client.Search(s => s Now, imagine multiple nested bools; you'll realise that this quickly becomes an exercise in _hadouken indenting_ [[indent]] -.hadouken indenting example -image::{imagesdir}hadouken-indentation.jpg[dead indent] +.hadouken indenting +image::hadouken-indentation.jpg[hadouken indenting] === Operator Overloading diff --git a/docs/asciidoc/query-dsl/bool-dsl/hadouken-indentation.jpg b/docs/asciidoc/query-dsl/bool-dsl/hadouken-indentation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..afe03b960d1203610f217e1045a22142c0acc720 GIT binary patch literal 43939 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 literal 0 HcmV?d00001 diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc index 4fa321b6646..26f7525fe1e 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[and-operator-usage]] == And Operator Usage diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc index 0aa593da19d..141d422d7f0 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[not-operator-usage]] == Not Operator Usage diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc index 74ce4dfd929..db7a5e887ff 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[or-operator-usage]] == Or Operator Usage diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc index 613ee8fc3fc..7f8ac00ce55 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[unary-add-operator-usage]] == Unary Add Operator Usage diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index 7183af22e9a..936a2d2d602 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[and-query-usage]] == And Query Usage diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc index 2d8759668d0..3989690781a 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[bool-dsl-complex-query-usage]] == Bool Dsl Complex Query Usage diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc index a06025b5b0c..6fd39a3da8b 100644 --- a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[bool-query-usage]] == Bool Query Usage diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc index cd724fb85e5..8f9932976ef 100644 --- a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[boosting-query-usage]] == Boosting Query Usage diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc index 602ac8f2072..e06551baddb 100644 --- a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[constant-score-query-usage]] == Constant Score Query Usage diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc index cf1b38a5fe5..54466b1a0cb 100644 --- a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[dismax-query-usage]] == Dismax Query Usage diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc index 15bcc1b8f97..73c5c33fc59 100644 --- a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[filtered-query-usage]] == Filtered Query Usage diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc index a73c5495f59..af7aa2e4e3a 100644 --- a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[function-score-query-usage]] == Function Score Query Usage diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc index 8b1ec531a4b..0625dd68a8f 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[indices-no-match-query-usage]] == Indices No Match Query Usage diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc index 49c5f5fe8ef..18fb2e392f5 100644 --- a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[indices-query-usage]] == Indices Query Usage diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc index e2a4be7de4f..ee23aba47d8 100644 --- a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[limit-query-usage]] == Limit Query Usage diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc index 6b4eee5f44e..efa03beffc0 100644 --- a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[not-query-usage]] == Not Query Usage diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc index 14aae89dc50..202ede1811c 100644 --- a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[or-query-usage]] == Or Query Usage diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc index e2c8fe6b994..52f8c6fd1cb 100644 --- a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[common-terms-usage]] == Common Terms Usage diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc index a156ccfe256..cadfeba1b29 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[match-phrase-prefix-usage]] == Match Phrase Prefix Usage diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc index dd8e390cd11..850077abb54 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[match-phrase-usage]] == Match Phrase Usage diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc index 8af0f92c08d..174b2c7f7dc 100644 --- a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[match-usage]] == Match Usage diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc index bb01742e0eb..af365d8a1a7 100644 --- a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[multi-match-usage]] == Multi Match Usage diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc index e6dde3f8b94..165e0db6a4d 100644 --- a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[query-string-usage]] == Query String Usage diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc index f12b8d531ae..b3236c9c12a 100644 --- a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[simple-query-string-usage]] == Simple Query String Usage diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc index efe5bbcbb06..75eb66470bd 100644 --- a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-bounding-box-query-usage]] == Geo Bounding Box Query Usage diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc index 7e12f55372d..55f572f3208 100644 --- a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-distance-range-query-usage]] == Geo Distance Range Query Usage diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc index e92f71df069..d4cc505c60d 100644 --- a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-distance-query-usage]] == Geo Distance Query Usage diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc index 24b04a0d652..9db82c4a816 100644 --- a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-hash-cell-query-usage]] == Geo Hash Cell Query Usage diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc index 140a59b156f..15f49d76c2d 100644 --- a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[geo-polygon-query-usage]] == Geo Polygon Query Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc index 76fe2be6538..a3185ee4299 100644 --- a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-shape-circle-usage]] == Geo Shape Circle Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc index 47d198fa1c0..67a68dca84f 100644 --- a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-envelope-usage]] == Geo Envelope Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc index 447f86c7beb..935d4062bc7 100644 --- a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-indexed-shape-usage]] == Geo Indexed Shape Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc index a960f4bdd71..1d47da60b4a 100644 --- a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-line-string-usage]] == Geo Line String Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc index 2ec0cf02c1a..d1844b32a90 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-multi-line-string-usage]] == Geo Multi Line String Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc index 76e9b8c285e..2ec90304aed 100644 --- a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-multi-point-usage]] == Geo Multi Point Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc index 3cb97776277..11c185b017f 100644 --- a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-point-usage]] == Geo Point Usage diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc index ee2f03c05ad..9b0a72c8f31 100644 --- a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../../images/ - [[geo-polygon-usage]] == Geo Polygon Usage diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc index 5c655f0a92c..3e5083af76e 100644 --- a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[has-child-query-usage]] == Has Child Query Usage diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc index 46eae8a05ef..30488fd07a7 100644 --- a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[has-parent-query-usage]] == Has Parent Query Usage diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc index 3615e980563..7cac48a1388 100644 --- a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[nested-query-usage]] == Nested Query Usage diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc index 99c46a0088e..5250786a5b3 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[raw-combine-usage]] == Raw Combine Usage diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc index 585b10f6dd8..8a981e5c065 100644 --- a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[raw-query-usage]] == Raw Query Usage diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc index 41d6747c3b6..7b7118358e7 100644 --- a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-containing-query-usage]] == Span Containing Query Usage diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc index 8214697f5be..73b2725f3b7 100644 --- a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-first-query-usage]] == Span First Query Usage diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc index 4b365f3bef9..8e0db66aebe 100644 --- a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-multi-term-query-usage]] == Span Multi Term Query Usage diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc index c783f45d8b8..aaac1e9a051 100644 --- a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-near-query-usage]] == Span Near Query Usage diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc index d6c458d5f96..6ef96d2e2a0 100644 --- a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-not-query-usage]] == Span Not Query Usage diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc index 1f4fbb93312..83640752cd1 100644 --- a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-or-query-usage]] == Span Or Query Usage diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc index 3d2a60f2ce1..3465be21e88 100644 --- a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-term-query-usage]] == Span Term Query Usage diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc index 4a33735dbdb..2aaddef7c6a 100644 --- a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[span-within-query-usage]] == Span Within Query Usage diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc index 9c33308b5b5..bbb1ae7e330 100644 --- a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[more-like-this-query-usage]] == More Like This Query Usage diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc index 1b79cf678d8..c669ac13d84 100644 --- a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[script-query-usage]] == Script Query Usage diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc index 2764d79f9ba..13361285b06 100644 --- a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[template-query-usage]] == Template Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc index 6d68bda89fd..974d4b6c7ac 100644 --- a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[exists-query-usage]] == Exists Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc index 34efcbc5cc7..bee0aeb2619 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[fuzzy-date-query-usage]] == Fuzzy Date Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc index 7f5456ab690..bc8810eafe2 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[fuzzy-numeric-query-usage]] == Fuzzy Numeric Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc index d63c21c67f5..1a0d703c63d 100644 --- a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[fuzzy-query-usage]] == Fuzzy Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc index 5595cc0a9cc..19cd0489925 100644 --- a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[ids-query-usage]] == Ids Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc index 3fb6978d2a7..01a6f3ef835 100644 --- a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[missing-query-usage]] == Missing Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc index 51957a5cccc..719986ba859 100644 --- a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[prefix-query-usage]] == Prefix Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc index 0719d56aa5e..eb60fdb35c6 100644 --- a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[date-range-query-usage]] == Date Range Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc index d44488a6783..f4c4e64f443 100644 --- a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[numeric-range-query-usage]] == Numeric Range Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc index ec1caa8532b..ee93de92f42 100644 --- a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[term-range-query-usage]] == Term Range Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc index 3fcf9536a2c..5d99b771e17 100644 --- a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[regexp-query-usage]] == Regexp Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc index c04e5c603ba..56bfff4117c 100644 --- a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[term-query-usage]] == Term Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc index 2a175595558..41549d983dc 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-list-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[terms-list-query-usage]] == Terms List Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc index 31eb25bead4..95f1f7ad444 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[terms-lookup-query-usage]] == Terms Lookup Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc index baa9e848df9..84e2dcd2185 100644 --- a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[terms-query-usage]] == Terms Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc index e2b1301e1fc..2bff4a45c6f 100644 --- a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[type-query-usage]] == Type Query Usage diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc index 6c375e0d0fe..8e23c6dcab2 100644 --- a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../../images/ - [[wildcard-query-usage]] == Wildcard Query Usage diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc index 4f574058595..fb132480708 100644 --- a/docs/asciidoc/search/request/explain-usage.asciidoc +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[explain-usage]] == Explain Usage diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc index 85baee860e7..8b266c42f30 100644 --- a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[fielddata-fields-usage]] == Fielddata Fields Usage diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc index 94323e1affb..bef2edea17a 100644 --- a/docs/asciidoc/search/request/fields-usage.asciidoc +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[fields-usage]] == Fields Usage diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc index 0bf9d99c658..c9569d7154f 100644 --- a/docs/asciidoc/search/request/from-and-size-usage.asciidoc +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[from-and-size-usage]] == From And Size Usage diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc index 7b0419975ef..d6d248856ea 100644 --- a/docs/asciidoc/search/request/highlighting-usage.asciidoc +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[highlighting-usage]] == Highlighting Usage diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc index a810de773d1..f872e339457 100644 --- a/docs/asciidoc/search/request/index-boost-usage.asciidoc +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[index-boost-usage]] == Index Boost Usage diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc index d3c6cb424cb..e5fc2e80b7c 100644 --- a/docs/asciidoc/search/request/inner-hits-usage.asciidoc +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[inner-hits-usage]] == Inner Hits Usage diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc index 6e00e307375..7be2b54260d 100644 --- a/docs/asciidoc/search/request/min-score-usage.asciidoc +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[min-score-usage]] == Min Score Usage diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc index 56d90489302..66a0dee434b 100644 --- a/docs/asciidoc/search/request/post-filter-usage.asciidoc +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[post-filter-usage]] == Post Filter Usage diff --git a/docs/asciidoc/search/request/profile-usage.asciidoc b/docs/asciidoc/search/request/profile-usage.asciidoc index 63a9486b471..505d44c60c2 100644 --- a/docs/asciidoc/search/request/profile-usage.asciidoc +++ b/docs/asciidoc/search/request/profile-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[profile-usage]] == Profile Usage diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc index 6e952a8b284..4b507e99e59 100644 --- a/docs/asciidoc/search/request/query-usage.asciidoc +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[query-usage]] == Query Usage diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc index 719c8cd7ae5..9f38f7add9a 100644 --- a/docs/asciidoc/search/request/script-fields-usage.asciidoc +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[script-fields-usage]] == Script Fields Usage diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc index 1416b67100b..15592c3f987 100644 --- a/docs/asciidoc/search/request/sort-usage.asciidoc +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[sort-usage]] == Sort Usage diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc index 472eceb4929..dc8d099b34d 100644 --- a/docs/asciidoc/search/request/source-filtering-usage.asciidoc +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[source-filtering-usage]] == Source Filtering Usage diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc index ed7255d73d1..0519601c49c 100644 --- a/docs/asciidoc/search/request/suggest-usage.asciidoc +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[suggest-usage]] == Suggest Usage diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index 072ff19b334..d1832c9443c 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -4,8 +4,6 @@ :nuget: https://www.nuget.org/packages -:imagesdir: ../../images/ - [[suggest-api]] == Suggest API diff --git a/docs/asciidoc/timeoutplot.png b/docs/asciidoc/timeoutplot.png new file mode 100644 index 0000000000000000000000000000000000000000..ceb819bff0b789818ffdafb129d5c63735ea138a GIT binary patch literal 10018 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 a.Name == "imagesdir")) - { - var targetDirectory = new DirectoryInfo(Program.OutputDirPath).FullName; - var currentDirectory = _destination.Directory.FullName; - var difference = currentDirectory.Replace(targetDirectory, string.Empty); - var count = difference.Count(c => c == '\\'); - var imagesDir = string.Join(string.Empty, Enumerable.Repeat("../", count)); - - _newDocument.Attributes.Add(new AttributeEntry("imagesdir", $"{imagesDir}{Program.ImagesDir}/")); - } - // see if the document has some kind of top level title and add one with an anchor if not. if (document.Title == null && document.Elements.Count > 0) { diff --git a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs index e69c7323998..ee958349255 100644 --- a/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs +++ b/src/CodeGeneration/Nest.Litterateur/Documentation/Files/ImageDocumentationFile.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Text.RegularExpressions; namespace Nest.Litterateur.Documentation.Files { @@ -9,19 +10,27 @@ public ImageDocumentationFile(FileInfo fileLocation) : base(fileLocation) { } public override void SaveToDocumentationFolder() { var docFileName = this.CreateDocumentationLocation(); + + // copy for asciidoc to work (path is relative to file) this.FileLocation.CopyTo(docFileName.FullName, true); + + // copy to the root as well, for the doc generation process (path is relative to root) + this.FileLocation.CopyTo(Path.Combine(Program.OutputDirPath, docFileName.Name), true); } protected override FileInfo CreateDocumentationLocation() { var testFullPath = this.FileLocation.FullName; - var testInDocumenationFolder = Path.GetFileName(testFullPath).PascalToHyphen(); - var documenationTargetPath = Path.GetFullPath(Path.Combine(Program.ImagesDirPath, testInDocumenationFolder)); - var fileInfo = new FileInfo(documenationTargetPath); + var testInDocumenationFolder = Regex.Replace(testFullPath, @"(^.+\\Tests\\|\" + this.Extension + "$)", "") + .PascalToHyphen() + this.Extension; + + var documentationTargetPath = Path.GetFullPath(Path.Combine(Program.OutputDirPath, testInDocumenationFolder)); + + var fileInfo = new FileInfo(documentationTargetPath); if (fileInfo.Directory != null) Directory.CreateDirectory(fileInfo.Directory.FullName); return fileInfo; } } -} \ No newline at end of file +} diff --git a/src/CodeGeneration/Nest.Litterateur/Program.cs b/src/CodeGeneration/Nest.Litterateur/Program.cs index f396de0d52d..5e42aa21701 100644 --- a/src/CodeGeneration/Nest.Litterateur/Program.cs +++ b/src/CodeGeneration/Nest.Litterateur/Program.cs @@ -4,8 +4,6 @@ namespace Nest.Litterateur { public static class Program { - public const string ImagesDir = "images"; - static Program() { var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); @@ -21,8 +19,6 @@ static Program() } } - public static string ImagesDirPath => Path.Combine(OutputDirPath, ImagesDir); - public static string InputDirPath { get; } public static string OutputDirPath { get; } diff --git a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs index 36d001cf2e4..0871b5980ec 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/BuildingBlocks/DateTimeProviders.Doc.cs @@ -42,7 +42,7 @@ [U] public void DeadTimeoutCalculation() * *[[timeout]] *.Default formula, x-axis time in minutes, y-axis number of attempts to revive - *image::{imagesdir}timeoutplot.png[dead timeout] + *image::timeoutplot.png[dead timeout] * * The goal here is that whenever a node is resurrected and is found to still be offline, we send it * _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. diff --git a/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs b/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs index 266d4772651..effd5401fba 100644 --- a/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs +++ b/src/Tests/ClientConcepts/ConnectionPooling/Failover/FallingOver.doc.cs @@ -9,8 +9,9 @@ namespace Tests.ClientConcepts.ConnectionPooling.FailOver { public class FallingOver { - /** == Fail over - * When using connection pooling and the pool has sufficient nodes a request will be retried if + /**[[falling-over]] + * == Fail over + * When using connection pooling and the pool has sufficient nodes a request will be retried if * the call to a node throws an exception or returns a 502 or 503 */ @@ -35,7 +36,7 @@ public async Task ExceptionFallsOverToNextNode() /** === 502 Bad Gateway * - * Will be treated as an error that requires retrying + * Will be treated as an error that requires retrying */ [U] public async Task Http502FallsOver() @@ -58,7 +59,7 @@ public async Task Http502FallsOver() /** === 503 Service Unavailable * - * Will be treated as an error that requires retrying + * Will be treated as an error that requires retrying */ [U] public async Task Http503FallsOver() diff --git a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs index 8534d1f13b9..a3515202520 100644 --- a/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs +++ b/src/Tests/QueryDsl/BoolDsl/BoolDsl.doc.cs @@ -34,8 +34,8 @@ public void VerboseWay() /**Now, imagine multiple nested bools; you'll realise that this quickly becomes an exercise in _hadouken indenting_ * *[[indent]] - *.hadouken indenting example - *image::{imagesdir}hadouken-indentation.jpg[dead indent] + *.hadouken indenting + *image::hadouken-indentation.jpg[hadouken indenting] * *=== Operator Overloading * diff --git a/src/Tests/connection-pooling.asciidoc b/src/Tests/connection-pooling.asciidoc index 759505a124d..eadbe1d9f85 100644 --- a/src/Tests/connection-pooling.asciidoc +++ b/src/Tests/connection-pooling.asciidoc @@ -36,7 +36,7 @@ include::{round-robin}/skip-dead-nodes.asciidoc[] include::{round-robin}/volatile-updates.asciidoc[] -include::{failover}/failing-over.asciidoc[] +include::{failover}/falling-over.asciidoc[] include::{max-retries}/respects-max-retry.asciidoc[]

5co8P2I+URk!irBJkN@tGAJ%-ZFhqb+c>vnYpiDxAWlD_%Ye!!MYV#_AwQl z0AC1JEOZfAZF(_yJa`(|u2;$~-1@@@`^*+-?K(c4i{DDhf1~*o1jXbd`7=y@#8_Zm zzYMIgyd2ycd^z|ya3%Ouu-c#~JeE(Z;{1g0_yVx5mw;zj|kE;IAWO6crfL5va4CO=-{npt^;e{w*V{~ zx)H23Put%Hfn8tgA2@p{gwF0AMEm2L$wU5_Z>W%0zXp7EKOmZq@4p$o#fC3qL$Xi1 z#-Dlq$?w-opqEYE4pv-tCs_XPE8ru+ynB*z=>4Gw6R&E0ft{Yf&dK`6&@+RUd}=Yj zmHc_kJ@Cpt?lpO^&IFcy+z(bASAZqs0kHJ45?loSHdy{^6fyqEQ zpaE(Luo74YYyoxv@!`}HCXiT0ds-Hz;a+M zunE`>>;k&raQXm6z+|8jkQ2HSSP85Lwg7Jd@zba$Pza0#rUCW9LSPxN2G|7b0QRPj z)<7H*_xxXZNG|(#iS>-U7a1Vv1`yis|7H7LC$ZXlo$Y&_+}PyH`2=!)+el6}_wcBk zlHv9^fA$>*~f;RaR6b-P;^a zoiTm7RHvx3lk#Iu5hxGGr}N`EPhP=x;M5s5zn36tEkgK_wYV` z|9V}0ZMFQTcvVdQ+U)A8>bjbe(j@0~U1jmF*UgzxS6W+9Qy*SejNR~hO|mwm5Px2y z>sQPPzey4D%YXU&<-F~Vw+iycJNw-SjUoQ^iYoK!zseC+r987bv81-X&eT!s2|itk zxz0WbW!SILwF;wpo5Q#=TTi(WpMNeN$p~LlYx2Ne8(jDE;1XUh(FtGKfF^yfF?l6x zlT}ix+7XeOQ_4LC$8Zn>tDV#@{4&&-+SzeV{Zf$4cs?Bl@u)w`Zmcb_{uJ7#=FC$$ zuQVcVzvD0(Jd5Kq!1KW4z&C@(gKq~<0DlEM5&RJNJn*C7$>3+f7l2;@PX+%Dd@=an zVBUFW_GT^xcc;Q7;G@Aa!2Q5w;8EZt_+0Qz@Dy+bm_3Q$a`1d`CHOjUHTcWm8Zhg| zK`rJQ*gfmx#qt_JTzopC-XJ^Otfn02M#25^7yr@_O)H-RUD z7lP4a@ELFkcoCR+e(*W4zD2$m%-k~g0+{(;a2xoCVBXbt{qx{EIo<{S68JsvSHK6M zf4(E0Iuv{t_!HoJ!TVql`|>UBeS;C~qiEl#05}LZ7dVY`!@#}6a~FV5=iI5_qr7wO z_r;t$#ycNH+xXl`&|g5FCjck&dq4hZ-?k>qX9#!@FaWqRJa;^JEHFRVhxwu#mlNvv zB=z4lBbYM*|Eozp(#5`tLzLv#TpGu+>diPx%n!pR_8mRDq@vRHYsXg;68kapnecty z@hN`w_*~q(GUW5+odw^Q9G~Rv=KcKJBV;nho=-W875$emMJ z8Gh(H8^1M@eB`%W9oL1j9(97iXG3!_HkQ`uxT=c!ijqnVdV3;kS18NZ=Q+sA=R{i8 zZoXMCjQ*|Ux8X#1k954!=WclGLtbC*x$yRLywYc*?;SY(uzvIbx#z)qoa2?;-SFn) zdzAb#PlESk$GZpLP;cCh3qx5NYh9X*tkXSN&HaYDljY`g?wzg!oFMS|$eQ3}HRF5W zPKMJvW1LBZ-03t08CN+OXEgu&=1!KY&)QIyVq=#sK-Lx~s~PcrV;Kqht`hw?ou(pV zyOXg8I#Uc%09Zd5J%2=e%753S^?jN7hx(tJmx|VZ*QE7#(fLyR26I^J-=gyst((Ix zK%Vtyv9zC4oH-XzBHm*TYu^Vu3QPc=k}Vtzo&!Dvd_A};_%`ri;AP+*;0M7y!R@$H zHIF_2cHHrm$9Ub2b^SbcW3;cNdnekFt8_;{39P@11&{JuNzFCZ{IcKCQd#c$3Dez4oZ|#X^zGZIxTeSX$z?&arz9nM)S+xE{>%VK(`mgAGS^jO% zhSpz2=PTMH(T}qu>z|@&iJ?=vAHvaE{}R1V$r2~Dwr&i`f%Om3-<+q7Q*EIc0}gec zl07g^n>_`_PU>UErc?rq?@#GIyms6ZZE+`XpY*Y7SL-igf%7ANyVA$a{Uh|l6m6=# zzm#n4BJd^Pi^1)PKH3GNfYX7~fJ02(Y4gDPhv>O@3A~zf%mBN&xYL>K^O^m)7<8`h z%{1ZifOM>PcNZ>_QoybetgW2R+6piVm3P;wI?}k(p^5(@ zzL{MUQv2gD_h007b$lAbJw7)sYzg_)jxN0b-w}>4N9)aQO}C>H0)7!W1Du>@j6W); zo1YetpVd*cub@w){54Cfm+1a4TDNA&R!U%X5q&Qw?Ud3~g??=IuURXgkK21(+y{TntK>gpvgt9j! zzyH6ColkN7L~(o;?|*#--b;L5w_=D4^_>rU|10-c<(2uoS-$^uEBvz@f7rjZezg|a z1voSL0(bqR-c_iwX1nJle(&_unpuP9vhEwp`;;qVGv2MKI{H4ywo|kZlCL<5 zxXg`_wq2rWXMvt-~VkpMfcOj z{ol4rG;QPlZ`&c7wsHTrI?cZSTRrSq|6dgbpr-%Rw>z9c{|AbIslZ%dF|Yzy2W$pf zds6>*W7P6c83mqF==XU#H2weovG+c3R#n&C_Z=LD5g`r=3JN+XC@AO*4hRZ5BcKo= zqJV)EbOvUWX@>tp0u3hD1QKnr#Xg#7i>aiTVuJ~^m|%kmCYs_?e1ff}+G+|3rkctV zOtjTT-@f19UTfdG@65qOoV@Szd77h(-<-YI+JDwsd+mMpIrkj*(RiOv*PM}8`M=3= z6xS#Rs7FT+gYYlQ)C#rZSH-A-fuU5Ed8Xq0RJKEmiq}SQ&p55O9NAH+?9BEx`aqMd z7wn!Yzm*7wyJq;iJ90d-W$o3qQ6d-DL_GH%jPdLLiJo>^a1)+*wg9dbGEK8G-p$HcxF+tjXP+Tn zv#30?XLig{+3EVk?3c}}`cq!BS2nNKC2{{u^_z{duhYaEp8*lC*(JN&li*F)NM?iV z7>TaJ8cF+Zag7wO$F64+PKU13U%iTdD5yU)7McOILF=GR&`xL{bOaW*)wTx;W&uRKY2#!___ly?1DOCj3^HdUOLWyOdSu# zIx^NVah%7!f^^&+LUwy9o9tyoxpuF!vY@%}d)ta{M7g8wfw){cPJcpu-;Q#}FixY+ ze@0t~t>wqe;bDCC0X07Ddtk-!hzsS+KE>}3$#3HIVk|>z0hOV>W$m|V z>{(g*ZAt03#LO1i<3;7AW7c$^&8xAM?yZ=kw!>Gz zACJt9QAU2>L1w?pz*jhWB6Blmp`I?<_p9@<#l4Kefsa-!>rl^oiDzo3`X6J>GOr`m z8S_)c`dEi_HmCSNPAa?2WmDZTb}BYRS?R8WY>cB-8S^{it>UgIdkk?S_DykP2xNB8 z9(T<3%{~{Mw`{MDh z_|*5~T+~J5a-SC-?Woh2sprKG^}LsHsdlDgt1@F;z5>tBV;vfo$+K;#?4*ow`BP-y zin1D)9c1IU-0HGbQGwvUAzOClv9G&h-!v}eUuKWuJpqLR`KS(!HTl2B(KtqMTvKbV zHvJaIPr44!c$3@-pvDa`jNjA#Zce|Iie;z{(_i+O(R?50SMi#@vd4^g(=lWE$sRMB zx8;+%H{Eefe2&k>!^q!_|L=!hhTewyPD5YN6sQ?m3*80%_9$vV<3Fxp=eY0wZzcM{ zZ~iOR*SYWd2-}m7Y%*$2oS-By7X3t!+vb|;T1zKiba9zvI ztJ<1YOkTZg1y3HgE?u&ceTHf+GxbbDK>gjkbm6M-a((_jjeK<_&0nzUCZ1!p=Vdis z(!9d6t}E@@onHi&KY962zxUU3e=v3T(Br#(^D8?W5#h;$N$85}DGHE^G{#ky{x0v4 z>!x#l%XaHTDpx$Y%%7`{--He?C5K1HZRmC7IM?gM6)k*FyyU5B@kqz)zviYeP$e7r z&+-1Bmh^wslF2INM+_X zO7c3ktFlA>(b}c&d#{1_giEc@s#ojLqt)B9Ltffu*;@2o<|~b>bk2$2)!slo@!&li z73;ixIUW~Z*<#OqD_{C$VUrt%AtV#|)DPvKp7_RMGk377?3?DTC_dgz-|fBmX?}bb z{aE`K$3T^g&T*kZ_?P#KR8%oBsZHL$_=fArOWIe+JfWYB^zj8qvXNiU#w&kd($9iT zT>AaC`EhS^x=#56+I;!1(dNF$ZiFNo`TxIY^L7m$j_(+Rf7yeqnDuM4c`xl9LWB@gT9`^Z%PxN@-Kv$ zFYTm%?Z`|$9}P7E$AcmS#5v6?H{H< z%h6;I{{17`|FqMtz${GLbLZtvYGv68lMK(7${j&1+{pLDKtf|2}U& zWfzW(w13#;ss1M}UF-`I>3IY)_dt?~e6jt5llCuksbke~ynnD;6Bfs<2I1d3X`_BK zU8b`zpG@*q)2!BZoL24JPaAJTR&tRyw)3o{o$W!w#<|K%^W^6fm$ofk;wyp}3sRoA zUbC8y-6nB<*>Zw9#lw9D;om=|zfYF**Kh7L#A#+_=<^=>+lahmBfr|LLKqjtF;Eb@ zzNu|hONepmdnV7c)|LFcEBM-Fzs`D+f_hPw)&+4b*{dw~=^muZ7e44~$$j3MSG551 z<9{GCtvu|~5Pu**g-30FqF01w`JY==^1^DaX$ES0voL@H7@JjhV7Dj-zRrN@2HFD>}w>yzT zT}PFR{fvE_c4ByUYp%x?Mc<*=68UH|^`GiW@>VQuYe@~Ja@WB$g>t_M@5x@S`cG1c zY_!)4@J}N1&&VI>{IZv>?b81LDtpa9V0jtu6-)Y}!IhQ~*Gg*V4C zj}n>K&UNrlfnV3(!zUJff<2NF{*}BjpsnRve!1GxOjZ~>+TTgr5pAh?At86}kD7tbHm+_kz=M__6Pzc;Tpg?t7NxH!qD>oi^8K zi!_zz7rP6I3$chWUS`q$dg^Y2_uiy#uK7!37q`Y4%Esz`!;ialZ!sA^R&%b@+#w4=ZW5BxsAMoE!d&3MwBCPe24US+{HXG*4t(C z|I{T5+g3HRT(#In+v|{%OyrAm|IlPkXmu%#K^33o71sDGZH|;rRpP`olsgjUuX+8F zEkBy9iH0^cB0B=vVaV=GWV;_tHr?Amb{Mi>hIh=BMSCb#r)^$((@pH?+SpKBPV+QZ z@yW(cK7K6M`f;Car(aO+?M7vO@LtP`|MWJRZHnJt(D#V)$cR7kM7x}m*rnq&OPaT= zseO^ElANkd^A?9MJ=pjJtyQ#Qv&ug=@wb&NH|q*# zrP4L0iZ9J?Z7%v-nyz_TLMl`KmgW`o1%ujB#e`8wTk7GPpR`3jn9A{PhncZClG}t_ zIdW&h_eqyi8|9y=oaWPLhge@da!dueZ@66avs6xffTbX-GLFTL@p>&hFhO~rRiS=- z0Xz1)I<@1>mW5if`bCr4o2RYQm=q-!dDUJOF)XoF$JmhO#cMgqDK?~eZ7m;b(LAbn zEnB5|D@$5qx;Pdc#JE_k37TV;LHPF`bnvGoI#;O+Z&DZ-C?Y2VKZ?X%aTC`;`d0{=Eh{E;WN@4Tda>AeY!p)@ZY5AV1ATeOhj z_^Cno_fKg5OV>mnD{cQF+P(}K@kbu{fdtP_+TYyL*1EWrcbjmpMjs+qAJvbPrzQFJ z@v-ayQswEBzRYtmGnZw8e;|FL9hGHmMJ3 zUQ<%$vDzZ8&+6E?*0IhY{L8(Via)%zv>)~rF7u~l>N|3hiG0x>Ba=QH%^oSw`?W`$ ze`?OK4)8wg!f_w{IO)35ew5tY^4LC>zP!xlv1B8EoM$db`r~a4^Gx)uG(Xsk8AW4m zHD%UQ=Jm8@w6{Sr8nUU(id7cBC9@Bi@yOJ}bG6IF^=T?IapsWmmyNygMm~(j%NlA5 zu|L*(h%%m{jDPYn;(U{qq4`Gqli)o7{T1gwO4?b$dCDLCQ8MlDzW|Me=c1XWU-hj= z2bs2(B{yq9CLc}d*SfEXEqYO&??aWb%;8%RWw(yFbz8TM{OD2TMca?nhx){fXz?(2sB*Wowi$V)cz$MJY!V*9qH1!4Y)b}z|G<|fTsC3%ud z>Wn^+@^saH@C&YoOM*7+pFcwn|H{M^R1@{UOS6i(-?0a zuU5@m+a$KSpEeGj-LZ`;+x3z`webM$+gNQfkuS!Z+N6yg<4ug6DNpOlNpY4aT!Wi! zI&e}ljziWLhJTr_E1sQOYU7!$ihYYpGot(7s%d~OOM@ri`t7$=)^p8dVSNQ#x5$9MX&m?vI z1$EVQsB89;j#0vNGmN&r2}wT6MBR)@bQ7<;Vr)tC;`oiRCCzJ#lPu*+_BgOK-{v6s z;<4x|;gw@3_uqE^BLTzh;SU*fcHV+Tfa1?JHZGZ6|uA>7oW* zuA>~45#^#TE>3i@bXEJZRqe&=iZn0Ye^Q+8MmcF->yk-JS7Gw7`$3)Jkv>X!W)^qI zyoLo^K;)9?7oR2wC)fh=?tIxY|2^<`!KXoNlm9Wu)Sv$uxD-6Oi{)>b_=v3rGyfe;NEDxC^`=)IH_R;1l2$@M-Wbz~{g|;E%z-1a%Mm zD_}VhqMXrOj#ulub2_@?X%&I`gZjRJz9CS-?-%urOnoCv-)qtNI6v1nC3HT~&oA-w z2F~?eF?~Z*`IqzW)&BP-{C%bWt#b7~B=KCqL0!!Fuot@M=#>{~k}; zRW2vq@$jmxv5t%Qdy40e;%~i&Np;_l{N2po`d*sS)4%ITiFGPn?*UVr^!H@vZ%zJA z>yqwbpVeNy+pB{A&HztE|N2gwzTMC_{KjMkW6_>}Ez5;Kk8MtaCXudVN6x-s_E%tE z&Ub=?!LNhk!CfF@IQIxR1Kf=ZE51F(IX;+s0{jB_w;;Zi`#bW#4esas0QfZcGw|=h zcfcQjr%?BE@J#?;827|NV?vCHq_7M2Q||Ttwy11dapiz;aM~8r{KVU=OezJRV#N z_5^PMiSc3nI1x0v>bt7ERVDPb9aMky&N#ilsPy|-jmX<`pJj#TM=MC11?f1MGAqGT z!G7QXa4>ipcosMayZ}5C)c0jIzU|ves;Bt<7Ws)itC{^9iL;ScJwrh0VrZefVY&Dl ziG8Hovy)|oXE0ABZ4ab_`$a*Y=Xn_;KB@Di{Vyb8PsRR8!5Tlk*YXmBCt7lXv^ z+*t7UK<38$=fKOrFM*eXTR?mawcUIN>dtLZj?|SRO z-}Y_D50PfS@7hT@_N-)C;aN+qCALC3uBHz8$TU!T`4Ff+U0ar0$2^exFz4R_=YaTm z?jzt^;5-n2$jt}QW$p&>T<}H^{p6a!daxNRXVqqX5LQ4dpf*VF9n|<>H5>Y)_Yc6dVY)foi+fMT7l(D7b|5Q6OuL{3Oqx;`xdzD@kW< zkmGm2;k!5=1D9~V8Z6K0yNqY!*=LiYwV39TI`mu{&h@=2Yx`*Uir)olBiEjFEXy?o z&hWdQT%-TJma^6MTfmdSPl0EEp9Wbkg>OTuZRlaJEXqqxScXI26%QmFTdt_=&*j=07`FnfaSy&n?v=zDy|6m_vhqogzT9@ek8%) zI(kCu!e90+$SVHkxxH{ZjOP{d(%2WkvEV)6WRQCC`zs6208&IryB?rC>6vTFpl7agf}XzuUPSsfP_g47 zQ2J(_nZFL)0nP%hlB*3r2qz6d+hRk@CTg#2>eIzCGa`$WsvRT{9#b_ zC=LkeTKK+Vcko5dnJ2>c6}7){fOE~U;Ti?}5$B2zhrr?BPe9^i_|9Sj$of6Jhy4}s zD$aij5|hGr6LpR7zd8RT_%jfH%^d;n1YZL`5B?ndQ&9EdLjk`EzQOrlgZ~bqy>(^-y@9JNuUTFLK@&{Buxx(>28@oa>r` zZ^h(a1WyC?yByx{_vzusaV^LBLU0JU50qT2wyu&_sHTWfP8u&GEI=B=35cmjqE%;4P-{ku?I179VoDJ%k zRgIe;I{p-#OS;7}eY5i<=E_s>TE)X5kgfx?mO2+2#+qqJ$kTh|doY$Oxl*j;dZGva z_F_)0cRYbHsxrfD$c8%zVMEMBwLj0k!#?5oTr}x ziax+kE~qwhg7s!AY5F+f?Yxq-_^*ehE~pV>GQhn-Ys{yMl5wL&mmEhrbTG z80ts+KS=&aNblf3f&c2kDoEc05KeNOQc_P1b(~SShSHk#dT2H@7rLA_&V%|RGZ7jA z4GLuK()aFkEp#3wjD|~b{**A+)h({??(nk@-0sH(*=MV~wEZ&L;45a3Od; zcoTRf$T-Y%?Vf7|ZvsCGE(P1b6`;nLVxrF1f?Vr|Z%!~?!#5|EgRGsy_YkY8`{SIC z1lNEUf}a4d2G@eq!B2s$U>^J^_!*G7HpiYpo_R3Gc+WHcR5Y8KPFq#9k$ga)JYEAjVf*ergBLEmc7_Z%iT zDldM|VP23Q9Ol*1IsZ1|j6Jhf7M@=dqvjs^8;-kapX|UMNLV|50hE{B3u>;~1YQCD z8Tk9)mq1;w5#PdlsUHA!z4m2r6G*(v|2g;|_yG77a69-_@Y~?mz-Phj;EUi6P;=B@ zgGWGpzwno!zF#Q2Nxxj{gzp&k1b37E0q|R(=B96hr-OUI^TF?cb>Mfwap2?NRPcM? zb>QEEtcSyQ4O_r{oG%Ce7pUvNr$OeI+~0%mfX{#f(ABfx=^)?b$X^UT2aW^(2_$~y z{u%r*NPG|bOg{uyaee^AmqLF&>xfU}enL7r)c1Ju^fmWyAZ^aQ3ev{hVbJ_W*J$z^ zeKS^TMU6M@gY?QkU0Z1HMC%&uqv$%`e5@yb>(HAtD~K10Zx#G|0E3U5fq=tg4#zYuJ!h!)9-tB+C zM!%Voa=!qz%=&jw*9&igiW9#C&jMMb<)Gp!BGBy4&|twU*Yp zRdeHX(sli%@2V>OVo=v);@2E92%BCADXyH3=jbY3?-)Ld)KPfGNF-}Q+6R!)uO4)q zO4&Bg_9ad8T0ci7Y+Jg*-u0<6Kbc~_hiZ5fqzTh};Ajo%X^5=q= zffK;X!AW2}cq7;VD&AiKt^y~5w}O+v_26XC#)qyiG(O~Ont#SX+PBhp(Ye<2MgLoe ztUaq%R@lEdo-|$4>)`uFd0lIK5R|`712u151L_)R1~?wP4pe(*f|J4P!I|J3upFIQ zo75JK1zlU%HKyzoug5CO<8x_c;Tbi=Lz~{#0N|KMSv|n{pxP)O(sf1?=h7i-#-PJy za2V$|gWAJr1*d?&3r+_=3QDJo!NuSbP;=)}Q2JO7{xP@$`~t`tH2)yD3j8|wG4Pw< z$3gl28t{kU?}0xCKLN_;ZviXt)lY)*b@s9IgTPzC3&2lk7cmenT$eKC#Wso&-?k~V;;Dg{C@Grsn;8#FhAFw9R ze+>L8$a*68HSkZs9U${!?yo@R!Q5Yi{}X%|`~moNka;8b4e&p~N5Bef|2N4%{>Xyr`+Fxv?;d_q%FCp zK+4K}A0#ceAN*h7KY;%P{s24(-Uz-5J`cVDl829{d-U2@*SyplKi3{}x+kCR$ESPo zFJ2o{BP~U$Gvdv!>8%`PJ#GUXWakR-uk7aX)k*!qu(OnnJdJopKCHmEo;6nusAQQ%KO&5{2KYL3K~`D?+S zfj59hz!p$)H-o?6yd8WU`~>(KcsKYasCe)exDWhKP;0nff(Jq3R{j-``%d`BRN|i2 zxqZ=v)&g<;p|wkY&Zm&4{a@{ccFdbY-c0CR$kwyM7&le7JwsYncn}^>-@gy*R%f>Uwi4YoUT=^f8|`4m2(%;)^OSbE1j2i!fVfzvS}M6!@c9e9`EVY zA=?iGHNOr5&jQZ?HFH;knx6)PmxE`4iv4GUviUjSJn&p_33wj(De!#oGvEl&Y$kn6 z@A{s%*)8tvYOlV#ekJ8LiT2Q%&YmAF3(t~LT*;cQma^6MQK06pIifo?>D(bSi(J1C4^TN1^+JJwjR~@pKsW>=*n{<51TYcCT+N zZL?=W%L>nys@4&t>)_dju%>$!RQeCVYLNT7!EXNyHgL{6LxRu!3)sl{L9iJ-1h#=M zfr>Bx3T_1d4ZH_D4Bij&UZZeNwqRXTQl0(_hEzX#s|p9lY=JolMXX=AtU zX20V=*{vMZwSITd){MFa*P3xWs5PS2izjhj1uE@ANcxanbRDH=u9)>YW>z5RGj_*Xk$#{Q0*wjzD4xIo&_x{ zJWHzBKaX@BCnKw}dH+dRzn%hWjP(b#jvW9F1*Jo+zXx(&2Mz)+1y2JtH=GG-J$n|| z2%ZgUZjf9ncn;?u1J4C-0f&H!mFI(sWg|e1y$itagBOCbmE@lRFXCKdk3IIVCtVBn zpbulg{@^%J*F~3rL%>VHuA5V2)4tTMaWmX)dri=@?3n7iyjy%0wXE<=>u}_>N1)?! z+EoeGgBlABU^O@qR1CWctOuunSA$c*kAPQ$%fM;iXTj;Chkw{y)~X}-=iwiI_e z&ehrDdOUiz=Vi-?&vqOK)cD`GsE_>pNl5kL-+XKcT$ep{y#vio$dy;cKST1xbX#W6nHN<0sIs2GVo79`S*R` z_23slMaw?}74tWPOTjOJ^7}sr6*nFLZv(#!-VXi+_<8U_a5MOq;FrL!fL{Y20=4$~ zD)>$CYv5jR2lx-*UxA7*e+?c49|m6qzYZP-zXARy_z0+dnZE&b&H5;)akB^1o{H8y z+W)q7e0ps#n)LV_(9zO$Z4i0HAFlz9_P4GLtS&u=6W3K!Xs12DTgGbHj&eYLsN;Lx zbDtRu{!iLG2K+nlDsW%uLj`_k>*rXW{M4SwC6@8G4*9F>t7AWMmEhAsUUS+7VUI^~ z#-5ce3(w7p_ax|${^0n5%l#v$82B7m4gM3T82BRC0R9k^Z~P0m06YLL2Y&==9rt4} z4=R>?8hn{^?K!^!-U+@$ERoF*a~{?KpyrmJfwKJ(&|-=9Kjrt@b5|_UIM+VRFi7KF zTGO1Y{joDR*Bq`jyFGsv^`&@e&&8G%p0ic|;yUPc>eF2N2B>xIe}LLq`%myx@Ry** z(A%Kq`Tqyh9IXCTgBU%pJ3YUV*XsT8mUs_nVB!0I)lv{g6}sFujs1A&1qiWRf2acx$W@0 z*@bn)@llo3v4cAPE7oxg@5YY(_&H@N{+UjS@8C`6VfvPr+Z_+~277|X1wSvo1HXoJ z>vQp4x@j!zBi#|^PzSsGY!S#S9GLxbKjxjfmD8$y|mEuY2Oq&;Bs0k#pCyo+ZN^Ye)2>v#@c&ReX?(hB$l32Flr{bLAXR*vvDc7Dw973MixEOz>R>|m4Thnilm`$^J zRcHLZkIFUsW%KrhH~n6T*)01V>Eey=Q?H?1vr~55r`=%<$XLmj(~ELe*cw0bk=K0< zG?u@2VWfS~A?Qu0YBqBLGzD4&<)M3^?a*H60Q4sG+vERE4JiJ`_^`;kSeEiD{C$uB)Ajk@0unTJP&fV{0Qkzl?P#uG`N8;}6rD#h;cj z%gaEda5SkN0#?XUoIOezF~;jTQypnL7EngdScck>#Of&bct+h^YgOo_kA=DuxoAV4 z)eJ`(z3 z&JXB6%nuYFV)=30XVv$lbPp@WbFInEf3m-G70aglP&VswFRQq=R_r$a$d277A~QHQ zH0();*Zd$mc8fQi6U^S(<oSJ!ft?U!a8^kKOA!n!oNeP3A?-S4{81I`lmd z9ce#?Q^)EqtYd@Mk;aMhsAEkR)^Wt^m}%V!|DI1Bw{>A1+{+9{s;d#y@y}gY2Ycn= zs5S`y^81;J7dq6TJr(Yu>fS|8yfI(t+;hu41D%H%D5>cPL_Uq&5wGW1cH1wFmb~D!$%@b?osvQhQ9M zj&F5g9YcK6FYU*b)bUgo)^S@#9amAuvt3xns~L4np^g{3u#OqNYEJDjl{#MP!a87uK=W>q!0T8tUlRg?04mn+r#oLHKtDbqwjkI+kVBaV>QW?SeYu{qqA}N8tjN zp73sligQZph&SKu<(?Yo03ZJ+ZHZEQnMGLcW$ zwgX991ZjGj>hij_E#sUeU7<@0{VRr4bIjM|@t#)SQ$mxAg>%X~EGpVc+rM;4JFk9i zSuxpPxqnRi09X3^PB&)M$?wf8Zpp5*kcX(ZUWb|F-(yJeNtiJQoXU%c~mHQu-{A`!L*X(mf}B=Kx*+o(IYo^$h35em(&l zLHZ;=|B&a;0g=hu?|*yc?7d$@K)oaDY@R$F28Vv@qu*^0KFsB>_waNYDbh)zU{GQ*Kui5M;pAhS6ar?vUaG~*qw*K>khS-XYPqC7X$rlbbon>7 z5BE%UKHT#!0(k^7j~;ldiajqsAH0rpZVBY=x$|E5MJ*|v{X)O*m+z$QmHlkLG+RFl zC^z;^_OpG>;{D&$emB7@pHW}bw?&*YuK5+KJujqu*->~V_))OSf_sbQH^g;pw8ku)HD_bHfsHqJr-6| zhWfn*>^K&NxLg_eI)t*Pj$7c5x|H6BHd-B7ytgL2@=M#(%l6Cl@TxtZ1?88Y13UVq z${5{f^=VA$kRQf){0Cmf1~21|P=?;UaeBeG)#gc!M{o0;$i)7szRAv;Ro~t4s?DDV z)#fjN9oww>W_cM|I{H&&VtwkzZ0D`yZyoXrm7(L$;8lJ1hkDK|>67hiW&8h@qz;vJ zL*vo=&)6@tN4z(_3-7jsSGsC+-Yi{hhgWUi0ZLbY1=={SF7!iXEPaG&YyO|oc!*>e}a*$eIA9YVCHRG)T@n?1+yyXYX-AC&L#+t5zBP@n7? zHoKj?%camx@!GX$Ht*nscM80AP072X`CCUhB>U+Y8hBY_hc@wS6j(+2dEs2|Pte-A z=;Q0ivunY!!nLHd{Gdk4I{xJJ{t*7kK^wdZR+s{A@|Opw#>y?deI z5u|7>rt`i$3x9ezkA9%O+4Wy`-!7pn&C}yUnf9Jw^^Nxj(6+(ex1qVTJiE5bE|1^r zhVmwRc~^ldZ%R1Vb%bW}@S_j<& zZHFF*UVx53m2+8JL3Pj+s1a(1HbD17yP$p0A?Qu0>Ld6RG#;7(ErQlUcR^dBJGnguO_^umw3pl#3|=sD(Ji! zvInL9s*d;^_FAu_f2;uHcexeYV;y?d*}qf#e(E{o_2`;29^&epn!k^Feomn^ zklCvEyG7}Ah*!w^qwssh%W?~HaZZq&=`{Oy+r5xeyYYqmG`u3psa(@jS>YO1-Hf_K zCf}2tjMz5oYw`K*v~Acpuen>;lU=a$nHS^y^7|){!BGv3Xd!ACgUC=Yo zZ;w(9q~m{)XAMYL_TYp6%G_0^wBO+GKOUnVy^tcU=e>+4wKE;J<)NU`-(7qMo|9r7 zNBP|a>!ffn77E9AksA=@j`G{O`&~|Jp?Exw+~6p848OaGeTw%lUdZUv6Vy=~>p05q zF0@888)pA@?i9w9hER7OV_X~NHAWQ=^xL_Pzr`D`4u(35V^wQR#R(m;yq;d3;)9h_ z`ujVxMfPtH6id?I$(jC(*CbL!j3eSre-mLk&;Ct>Vvgo4#gUG`i7-88w?}cY-?8>?J2IBFT_}6CEy214_ z{42_?c7as(E68q5W&MuSN_aI^<9)zg8M51u{aPxU@jKeM4w&cTA{~4Bz5dsuypKJt zTXs{|5ctI#^M4a-6*Vbct1yP|tf=|EZm6yk+k# z9O<0Ey0+pUV;#q^9*cFv>lM>Wnc`A7y7BK2|66M*^-r;D4DX_i*F=hu*3aTvCY4i+ z(;TW8H-u}PRL&MpU_uFZ>4vmW``20Mm9l8y=AKC@|_W19qfpWSX$NxrGL0zJX z|IL^gerDHd#hi~Sn!WkFtJRAWFx*5vFxCwn>9q45w8?gLfKkL}TV zbn24kmL=^aau%$@^-C1f_ZBOfqnxhc61lhzt@oIb*7q86ZBb73O>6mBOWQR!-9#BG zT&tv z?+Qr!%YCwn-;Z*tZ$?x5BJXExXQPb8k@oZ7k-Ia>slE)k_*>DmzW+e(-YBQ~W;NX$ zuMc8<`!ni$6S@1Noa#&DqCeLiXYG`K#p5mHwnn*Qm;*E(q_XT@{13|5ab$90^@FMVJ@HpT33 z2$2FU~b`70m-W#2c@hRj&DYcDYO;CA{X-+2xA&tlT+;_avDAW|zyH%)PKd z1zz*n>~h6>2G46r_iC^CX?D4%!<*{Cd^5XT@uqq(f6Oj-P=|8O2eZo+Z!EWl_L|>i z&)DX zGaj05_{b%O%ZD2FzS?jw!A^W-1Q+461OefLj<-1W#&4B=$2o=vx$&)Y-rF4TK7ypq zyI*cN{940RGYr>EFdTi2;Zws5pJaeZ?vYx<2g?l)jy8P7(?@!Jqeof#qaQXro{a^` zzd|4uws?E{5U6#23-^bG-3da%HT8y53G6z5fPpJqMKB5HKF3T5`=sz+Vd-}h6qNrW z<4t&YqT!QF0y=-^M#F|i!$&VL?0uEteIGP@>w3e%XBf7gW_ULj;3{V_6OC}O^WX0M zeqgetKY6iXnYVxLNIRcB&T!li!*|@ii`_4tV)9bC&k|dN1KdAeasRl({bRHHM}y11 zQephp63Zm_sN4TxZ&!EM2k&nV`K|5;gIwRwUuNm^-5;jAAKdDG@Q(Yzz3vA)&Nlw; zUf&M)gZW-xncM#rxBnpLJKpsnwUk1#w^Ecf7Yus;I-ESUpziILM-r!!p^w*nMEgU?_@Lrc6-e~8qx!*Ln zT_1Ei_wjKs-245Sm;0#u&tvXCecXR;cRygQ5b9gw{xj9fxz_XFaDRHb()ez5KYDAn zo!3q?e8}53(&NP4?oWp=wfrXcpX1$scDUd4alfc_zj(;~;f|grH+X{KBOfvx>T)l- zAIx>WCx=`9)877mbL{+fxASJV^JA{BTODV+KXi9HKje0P*6lo?-pXlm`%ZT|-tBgL zy4mtqIZkyvxX{uEEHFIWWH{Gxq~nC^ExnK9OYS$1IL>#hb$rFg-J_0gebD5ea$Gaj z&Zj#b_W1Hx#49cTPPg~`20O3yes*_!$o=J3$DxjI`FMM>&g9nnxE$`d*yoo9$5rmH zkGQ`cKHuaXbA0MNJKyZM%JFs|_iN6v{OOKE-7lYX``_pI^kCzAz;TV^`f5v`>lm+P zTHKD~93S%W@`%q1cQ`gV4rid0<#^B8$%gki9`y0~R+Xhc<+#~#4L8XoH{Eg233mQk zPs5RpWsZY=oW0S*@}G2Ub-$nBc+kfU@1YOn-|jg2I6FVyQQrkt{k$hR;QEN9DV<>v z5c337nrO7^WAKf3e#=C|#ophhMms;=?Yd^6olo_+@X{1JpX+`%_ewjz)BWcTA7`^q zwDf+ipEB<+-+~J5=;!U%_uka5JA9lx=I!h5<-F+jnC@|TxyP-|uFogEU1i>`7LQNM zr(3zBJw8nsYUc+(XxQL-?H=tm!`so<@Qv|~9-rJ#`liLkI^2FcKA3e`yI=F*5m6P^X&XSuXpe%c0R%NF}cCcAM-dh`3gIa?<9KI z?YYYPakty^b|0^=czk@)_5G~dajM7r=iOiX`T2dW@5Qd~N4%ZG$63AIJs$O`vGeub z?$%4~e6)}67t6h!KL7W=&d!JXyfD=DKhEd1dtJXnuQtB9j*oc%M|ywW8fE#5qyAlA zZ@K;t&$Rr0-tNUsc0SVe{)+q6Bd+(&ms|dzIInpedC=Dx>)jtWd;B=;c9`mVkMC4^ zWRjKBG{W#{x5Krr_xaxcey;D=y!@BEf0JGBWv-7kW38N8_xJAJzR|A#gC3WkbibYJ z{hi=;c*5+r9tqOtAF%ZkJZ~^Fi*v(;W}HzUR9=o^*TM>-L!6 z$I4mb{yy|0c7CU)H+VZ6+%9w7E>F83^>cl^;Ey=|7iE~*{55%gB&Ng9v*Nzyfw@6pC4j)-xR|gZioBa4uibD zK5mDnJr1pMf4QJ06$jyFKo`*7BcryFBdUsMg0xt=s1{ANNmq{JY(8 zy5mz`{=IIeC)`e}+>TS-PS?7fM!H`=>-KH(^GDtOt9%@+ce}Otcsf{b?d{{^W2ldt zK5nbukJc&q0hc7HkE?Rv1r z_y)TjpK?1s%HYB@83m+%iZ4By1gH`-qIiT_BXhF-#W|E z5Bj)!=@L8d?s4(~_ls-YFB-i3RxfXjm)G6Pd(_K&z{?x$?KtcAL@E)a6h@z{bH{B#ej>A??u<| z`VZLoboYnay+o+PnNr%^j>J`&n_@r?)CNYIQ@Xf=K)^c;VX^r z@MOcGqYZEM@jKY{db{`MA-8kO*~YiS$Iqj#pO;*p!ySkAF}|028$RSX)$KmL($b%- zFl_REy;x@FJ937PxL($KyWbgX>GwMSz0SYc$4?(`?;y_~>H6qB#^eUgHGI+Sey7{} zjdHKg{c-(uc0O{U;e6+N%=zwfe|Yjj%fHugy05baOtmyuW4`Sb2K`pz)_=bm-@z0+XlJkJ->m%APgpJV4Q4KtkT`Y3aKJnZS? zT)$IYFE6>>A9KIzcY(>j=I6)Hv-8`XZ?2a!zpth5@b({eJx+E#4m#WNpLD%FHPO!3 zyT0!B^W$BQ56!gvC%pf&z1#;}PcOQE(f!cxvKfX=?&lA>ep;q^J-*()#r^Fup9jm_ zPVcz>?yWZd;qLFt-Jfo6wsgLk6zaS6GQ&H)-dkP2ces8RyIy;HJD0n?=XxAm-{j?a zoO#60hr1q^yWc$P>30lve%I%8*XO+pExpzKyZazJZ*jdo>Uf`HlgH=DE_bbutDzpJ zhPvM7dpvl<$M+kjTe*k5U$^==USDbHuecosOt$mqeSR41_FCoZn;qWYXFdHv@9$!l zUtDAItsgRc+T-E9v+ev2x9{c#JHOlQ`>@;hTDR}rZr{;vU*5SF?6%nL+v4_ZaQi;u z_IIqvCk2>Dz*y1?OvA5&F8;t*9$J-s}JJvdOcYNNj6CQHB)p54taL0Fi9(>yI z0mn6t(;WvpzTxYQCmru|T<$p8ae(9Dk661ObG+NJ)p3GjAIFz`{(i*q4#y_P(T>ME zzBtFq-{H94(Y_O!%Z>E&GRJ3qJ^7&Hs>@A&s^cKX*Dka4Cmio}TFuqmFkvwm6P+?Cp5auL~Y_yxnoWW36L%$LD?CpX%{qjmMie zJPvI3aksi^t8|J-)ngw(*a4oa%98 zxX0OB23h_SryDLl*>I@O2g^O~-Qw}`v7VM6zk70T4?FK&VR)zO`5})>v&$@fg2(5f z*V%bLZ|~i1hu%JaOg_u~OpEcKtWGo~OEAhPz&#J;%zs!^<7u z{h#jrp5XnR?)_`^{_wr!u%2o1{@mjIxn+Q*KkeiB7H{8uZr?uVS^g`o|IuFVWN-h$ z>n;CQZ~u$#H?`jW0p9+%yqpKT{qw#3uejX?dHZ{N`v-YFP`g6P6 zbE?-j!R<5K^*Er#_|~}oo4o#7*V`H|Z?gOALq6Z`@b%1F_1-@}f5OjKdHe77av$wy ze3N}#J>+`4^9oC!@3`6heaE$y{;;=yg3EVzy-#(28a&ka)?8`${0zef9Ut=X`=aC1 zK90M$ROWh~US3v?J}P<1Lsfk~*O=$opsKTS`Rb}%cOFpa*|R*ip{%m1vYX{slYhm= z>dJgI-%dr}ry+-Yc~5j*Mf=I`R!@6xt>*a#@_U}Zb3=V{WtFt8sy^iB>Q90#f^%FD{iD!bjrlU3z8^6TsS_RZ1uT-BcXB)?~_+VW|6Re7$S z{Q5n)t@-MFFY4%j7S*FvRa0L@0*95a`g0ZPnGQ9Ro_EXD@Jsx9p4Q6OhxYe84r`Zn z!)Cc&Gv)+VwV(RQ=d`k0eRVlyR7jqd=1J?%tGlZ~JNg3@8osU92yTQnK|7&+&>`pu zR7vBip%Ks|Xa>{{ZGg5zd!c8b1CVMQ2{-tU>411*ErLia{{>0SO?pzY8z z(5p~6TA$L3K0)iCjnD|<)(mJKq<2K;p$*U$XgjnQdIowGdJ`(=`eh(g2hD+&L2IGg zpl#6O(0=FzNDqSchsHy*pf+eVv<}(`?S%F~&q0Tvx1q`^`U6!%lOT% zZiKc%JE7;Gx1s7&=sz?M%0nBVEzovoFZ2xbDpY+95qGyaBog+5&Bdc0+riXP^Vnn@~A(Z51>Ss)OpG zIZ!jS47v-tAKC^z4!r=q4D~;QenaD-DbOsa5n2tcgEm5&pqY+JMGqem^3*83w8jQW68fXgC2(5rYH z=m=DK7Ii~op&8I3hzF0uI|uYGfj6P5v#ArRhvq=d&@yN(bQg3#vXajT)v<2D@?S&3N zuR?D^Rp-!Ns2-XI&4HSsWzb#F{m?Gxap(nT$hqhX8V}8a))%Pxtr7m)6<3^=RYz@+Ggp--@@36dX)`M z%CNynIpbZB@ZOcdYiZ8Qn2Wl4Gw^2Xs*1dCRtQ4RXmhSwC?vDh1>9UmH(w!gOM;q%}ukX9q*z#R2vB9E(T&ayM-TARW z?8p6qzq5@k-T5yr@;?{&JKNaOoqudGt}AvP7y9v`Rf`w2tdLHlA6cHs)L`p47mN=w zYEx$!%QKl;Y##g3UZ|(E-VlOw{+)kDweHwoRQIvGrS!&NjtPo=*Vkn zR&EXLi1yJs;f!F@iODw^Y<{;qm!U1upLq|Z%Ve($EZ^l86y??x{y|C-HQ3;P0$|OLzVxo=X1>x$)}!)b^Iemo2#QMtUfF z7T44bW{Xjy85igHT2XRWhm%e7~DVoo;d zEMs|IPZF~x1)0uvvUKN1Uul2O%;@i#*56vi{K%`mb>y`)v%j8|jlQowof-TwJN{U{ z%i)(%PwJP+b@qMBbD6|9)i;wV^<_(Ueta{=60I@L40tipBnHn3vZ}W<##_4c6aS)~72m9`QhrMh{IxasSLELt_&fWq zr8|G(VD6BYDsc`lRqn_~F5;BTE}EYD?(8~XLa?^H0xU=hFCX>7neJ zx@2D668OXTE7`xWbmvce|AoNcS&x?P{E6?Y?ISbVKGOYp46!=uaAyXurI}8~G!{z<hRky7Ib~rsivww5_43 z1v$%ix#pt3EGo#A#wAO4eqv?xFYO_j&Pw?$-T9L^`COrVU7{7+W9i0!Q8FLbGY4Av zrTmue{7IbL8u;TSV6l8lcm8BPZp0ZXa}CX?pr9K|bKWG5&0-$x$ZKiNTUYeeT^YQV z=Ddkt53J~1uBAC|5|8qMcVb&h(~3fSEzNn8eLOvXQJM40+LgurS-SJ%|IwDydKmw* zHM5qczGCUlpR7&w+(u>Ys+RW2OTsLp=^*;D<+%+0AL|%cDH**0ZuK>|MSgyhL;xkE#3JOf1h@|+GG3;)DYWm>CR6{m-uzi z&cHu&%}TuYf{9Dp+FBO2w-UuJnCeR4+USB(l@!V}Suc~$$9RYf<|gIF&sec^Vav*u zVcQ{WT*S6mevlib-vnOZZF$q>wCM9_UA*vBF}1ZNvv0Y-Xs>Of9G_VV=c{i>yowp z)(l=tb6#RgY`d;I&$0Qqy?sUNf>rIM_lzyy<&ybzN0BZ{KS{I29YjCWawvvuR+EnKCvb6YA%|_3m}VjvUDqZ3_cOtt~Kb0 zu>L6Jw{+)E{Gl&x9}#pa{?7MNEZ^nuhiHo#K~6f#ma}}9OV-XCg50FmmCKfLm09eM zr8_@!RqW5}fnTeS(*9Vw^C$DwJYvR(T<7vF-TCpU)D}ZCY%$brp?DB^_tM^uyq0F= zDh5Q}5wyD_ucbL}VuOu=S2oTbla}vt*dUJoeFeGBCT_@w?6Q99?O>Q z{E5G5E~?AWkEJ_*62GLMJ{kJy;5Upgth$871&pXg*uq5M*vTe|ZnWAKGS`KA1p?);3w!rm@EY3+ZP zz1_g$vc&c%J13;8FGrU(9+zz@`qHK#+c|Dqy7Mn6#=IQY1=h~&accQ4*CF0tp5Y^x zn~#jDrA^W98ZRArEiIHgs+RV|v7j+>d4{iAy7PBvM@>dMYJ4nT3~!9@^2-|Ysn#Vo zx3yfmYH8T0kLyXx4|UXD++38~7UY6&Wy)E;%Z2&O=G<2c^@V*2`e^stEZzB8x5mC} zol;ZW$0+byy77-?eHvrsyuiP7*^QHzuWD**ZP$ftti$qLhIk)k_C}ehOIo5-l(9UQ zN#a(wUQ3AXxKyu=Ey!4&%OvA{ z5q?{f>s*JWJAa3me{zPOoa`}eK@$JksJ|nxrG;{97BJ3ZUlqSj4n9>H7cAZRlXaV7 z`pLn@rTmue{7uDJpqOsuA3YWrkIOQaVjNjlsO#vm#^bV#mDn%&!pRvnw{+)E#)$S! ztex3$#PVGZ1IIC`x#nD5E5{pWE3OQir_m=ZKgiYAQD5v^IqfTz3wvxqxF8#NTs9e( z+e3QieOgO*e#T{tUupwi_zT;*g|b7M^+&NT>g}$Ou62)Yl^6Zk(w!e0MgDz(U$Lc> z-_o5QyTtLUeplqCt|X$gHk$}#`F;G5=Q8Lj$}9`%*>S@1T!!{W8O>`IIb<^8gyp$R z62GS40~HxQW9h~}iue`#zAf-~9>bRI{7LMpV$4^_S2E&+<+)4}yVeGo&UIM2^CxQ* z+4__WTc6@_qPfF5dvpfxXrFr&C!!B2estuuw9tmy1xbuh>==ENm{KUasi;TAj?qVn zDFyz-=M*nSXV}Toy*>C`9HUzTzkE7-Y+Js|;dimm(&c#>`Z>?_GnzRd@=6ySc`eP# z9i7B}>F2zo=%-M2veuJ+&O3^J3jD%2Z+F-l4zKnp~uyf6H^3 zWc*Dl$V_i-ZfCT_nteo}_3gfSo-_o5wvDx^*-}xHG(w)D9&BkZ+bG-MnIq`kswc>FLQ6w@=Y$C*Y_0Uu54S{ zRJ?C)>CT_*2fkToUn#$(J3n)J978q4Bh$l_me!jWwWG#@t}V}H@b4(ID9A_$on#%g^PyGD3LLH_2mhSwCpKHxx<=cm8q8%;W`SJ7UFH-`)`cTSm z>CT^Ao8$}SU$>M;b_zPObmvdzpIwFWOZhF``J0OEIZ`OU^d6_BJO6?r|1g59`Fkn9 zr91z^BERl8ntndq+RPV!qJAvh`57NkKlc>MFXgv%=MQ?Y>+}7AzjK_ibmvdTgMI@( zI5)GUJrv)tq}g35w#)KOPWNil7;;)h3^~o`l$NB=ibJOzB|a7S>2n;TbRjp^Vov55 zwR~&SLVPcdhx&qC=Y3Yoa~b?E*0r`ElYI}!@?9?R!`(ryvz{&8`SHW3uSVj**be%# zH0Q+!Bd_{*LI++;3%oVDFBAPkx;^12x;?>dQJ1XQRZdk#*;URv2H%eDcr}C9(ySe0 zuyN#_LI0|9*SB)>u;9~{=Df{C-klk|mgcc2fZ^Y#yEUM~I{$MV{c z-ua%Gr5nHYN~7%#Wt44c&YSq~6y7z{vCWp|yonEQ%iy&%=S_ULs#oW7EzNloA8ya! zwKV5Ve7Ko+dvt8Cr8#fn!?Qlnnb*>sH}TWBYdIwKV5V{C86ZucbL};=epd-Khb58Bt z21|3^#D8~Z@LHPlCjL98e@3|>&3P05-JQW}Y0jJYuihck(RVD(d6O8tF7S4a!Ip0P zP55wJbL!nQUiS2s=2o<%c<%SaLY~VczRa|r8+tQ7{E{P}7>tz{wz0CF6LX3!Wt#o)<#=64CqdZd{RneBjr$aVfv0JAYGA$L)pk zJMZ0Dp35XYv%OG9XBo?LnZ##aE!MNDt*!JPkL9^cbFpo6u%-2V>JpwWY-(Fs)R*PC zOyV<-7i2o`D_Wk*;4{(Ba@|yqbk_S$IXFNv#P#Y)wihYa;9-H(~dbC4*K`whA zqaedriFK_l$Q*qiqac^W*xf;{bDu2T`joyqM|&0%I_S&NoHrRC>i_w_qW|Z6|3@eB zrM@7S-T#6NI!pU+bsfF`1v&H<{Y(8kKf`}5-TI{Gu%o}IujgmOtTWl-b(QAF+*IZQ^t1R95(QCBZ z>cHPwKbG$Ni9Y3P-9me&HuGme|CVn2dS^&1pFiPOdrJ8&-T8@!QU7g$zw{XrOLN|) zBJVR9yq4y?3ySe?Ed8{0&$+JUrqcUsmgh1_%xDiXYI|oH%X1kt5&OG6$aL1Hr8_^d zBKB8$8<62|1ERkrz9~I)K%fJ@D6#rO)vhgL#x+o13_zg`0RK zE96Ahcw9Eof$rZ>mwuK~_(5K*&+=Rb9mM){&m_vk8wHb>w69o`)Mq>{i!P#U-|oL! z)_7bNy+ql)zlN;wxNPF5dS`BIbNrEi?5E|qOmorJ+t~9gkxAChmgh3~YV?n`%7To) z)Td}a%X67z?L2}#Os{9+(#4Bg^h?dyHp?>^?cqdS>@UjjVgP;`wxr!|ge5jGp8vPK zGXb-zIP-qBpdpF`6%+-v5m1or_IkUG3b(g_vI$5qg3@$1(4pyWyBh^pOmK<2331nG zqLCOi8c8(j#5IaW#TboCFi{7`Z6YKx#!Q?rzxPztx#w2jQ+;of=lQ;8W=j8@+x36n zx87P$opb8cF}jS&b}yDkxqoTWGbgX?=RPfG^ckm%%{AG2?o-C;M_*;al`tP#$JmO@ zuV36Nv^BN0p=G5k*tB`qoY7(Y4$F9-P^a6qe@nm_9ma55UJncob@Wo*NS1ASTE^%y zp4;=%n*BoEIr>$!%x8|8H+u9->!<9kYs#rx-Du9}&>wBzAGv>^qhC{tl%I|_^7KV3 zza>Uq#~XS2pUum9_UXkZZ9mnxqD`&}nIzaU(7e%$oEzHN!#C6m-VsaJlje*Lea@D7 z#juD@#=z7Wrl)0$E`86o(Ngx_4buxwMNPcn(%GfoP)(<;<&1u$A0EkmylMU5)u1p< z%^4l~p)H%YGIf|iaf2mN2b$M&oglZCCa+ zwf*(EK(_l_K*t;T$o#o4@)NW8G12&uq^zwU>$1q|IBho>8Ph%sWaH=Bnm2lst!+D{ z%rz$JYnZIp7@9YFk#SAtf?6+g&aLB(d}Lg^Gm!5-N7wO2o^j2V>y|*id%5a(BhPqd z%Sy_1K$dbHVCIx%v{Nf9^G8=!#|3s1a-C|&JefBR2+AjZ&8C*ox^mrWbqA4$0m0ld zURTQ)UD}Dw|NKB#>NB%^b-a;h?6C4zglT2U>v$v2m|^8N2J+p@SH~N9#tPd`WWA^^ zhscSRvax+v^F}YyhNWI6JL?&ATp(L4Yr|~4tj{8=!__vh-zZS22fo?dmuqOaHa9jag)M zoRN);fg7{P>Nq1yf3v9HNdMoMMOMcd*~qzI9M=r44?0fEM%Qv(kwsR=8QDnt-JV5O#~Im3 z`<>sfyAL|f$VS@l!&zi?oRN*R-$JfA+`Q>HBO7VIYqQAeI3pWrzwc*})p15P(tf9L z?c(~Nv9HNc$bcHH~Xm#~Im3`(2eqR>v9H#p!moIg6~0GqREPJGp;% zA9S3NjkMoev&iZ=BO7VI{aDlC=1s>L*+~0s$s()cv~2Xb--}sfb)1onv|ss7jO&Ar zGqREPdrcNu9cN@C?f3I6vO3PlM%wQp)|I$E=r|)AX}?cqk=1cVHqw4a5A1GN#~Im3 z`@JNKtd29Xk@mYSi>!__vXS;Xcdza~=r|)AX}=F-k=1cVHqw5F?cLq3jx(~6_PZvF ztd29Xk@mYKi>!__vXS;XWuNXo=r|)AX}@=7k=1cpR-QlFbJoB?-R%+ ztewyV7c+J~qj{r8TejCfThe;rCeKz!b4G_YZRdfv4i5b?8w)jcm>V_W{7K6gUD~+4 z_8GEocioIj@5mfX%NiSzw$CY7jmR=L9$~IIN+NB4Ll#*b7uYQ-q3zqU7{Xj>L@+lF z-nZ#QHO!CZj1GOk>Z}QLO`q%Vm7$t?aSjsMX-?qweD%IY|6w}Ccb=fE!p zvfby{I^M`r_g20iz9)nEeC8Zm#~XR--O9`Jhh&y#VmjW)Q`fdl-WtfqU&CqM=uy8` zPs*n_s0Z7WGxv$nywO2?d1ka?p>1a;tEJ>v6x-WI0(+T!pp1EWR`q;7Ko#u^RWNfVo^dzn9 zdYU(Sk^Z$dogO#%(siffjeMkkJ)BM_Lte)ldHR>FlkK7X%y(pTypgA0S$Vmp9UAoa zOnDt|3Abgd$RI!{ip5E&5+meMn2M}UJm5DU$g6YBTt+9 zpB%Vs3c@bx^y_RssaEwM;L;}uF84UGoPx7(xBux?Vz(HskD4{s{8R<%_CGy@VW#^* z$mC{^eF~1toFMd7vm<)5$8LhNzPQ}0a09dI?bz`i++l{>Rc%{ne&WlH9RsL)n|GHR z3}@4GxdY+)$JiX>(JO+pd3S9d31{=*a?{|($E3F!j%i{LT)m59Ii+rdWBMM1W}c2s z&=Vl@e6ymmyu7BY+O+!}JG7j93rc?3zjf>~^;RGKOZ=p`GeWAfp*gT0o<>!5U3GO? zO%a0>!P?4hdxe^83`%?I*|vVdnkuVI)D+cK2MP3;#))b&*T52P-8Gjq0mlf4DVu0XJ>#KQ|SNi#UqOvBL zEH19osq~aiSMYsVkzE7g^R%+DxlNT9C5jW}6*>og|5vM#)PaO8v?-5W*@Av*>ykE= ztgS4gx;azo;J4qZE;L4Gam>Mf*lKmlDypd{tthKZ<&xG~CGWXPc+!{FoUV>G9-&p1 z7Z)e1YB)3L;Lpc#YQ1rOpwD*j>5TA+U~x%RvaYHmmwvZWUBNR@30Dm9m6Pe*!K-y_ zBSV)+l~>i-)1^NT4eCfUZmji<8&i1Wn76xm>$tL_h@ww%vM2a$Pf@Z5iUhgOY>G-p z@NYOKP2VpTbaud#;yVa_-#c;}kEgDvU)rQ9lgaY( z;@Vus7!k~^0uo|>MF~M7{gLI`8+4=N8a(Vc18QL`p)J~l`Kn^Rwb*daw(5C zb#pG|?XHS`)<1^E3xC74Tzy;*%d zY3P+nm6eI|x>SmbK7!xwNx`{Pq^#Jh50ykx@^4c8iE>cgL zGVz|L?Oa2)W~NR{tIMmZs!Hs1rU&2W=hkOsYn60|Ew8IBDl4t4${`Qa)n=22^&DgS zYsPBFqS9(+*mff6FZ*wXbJSaX?M7~k+j(kjWlf@_yj1trp6a$qJ!j6{GA6|OFR#c& zrX6+V!DXN>pdQ=Lx$0qab7dTNYhu#~mQHu5s?y4;(nQiuvwNuD3v+9mb6Bson2%7@ zR+JUhl@{w(-&5IqBRmH_NgiYUp3}Cng9&^|byZEOq}om+d+>X4Zu7`F^4XD^@`~E> zr0G&U*!{YC%Q(7-W4zBSIcw->ZtqeR)g|0&uhlaSe_Q;PlDU9{BZ1d;@X8F=da0^f zu4yWBo1b2gtMBbi9me}a8GE4B*4W14_rEi@wxZWomX;J%S5(LbhXlXf^P=ZFeg&Ab#-OQT*k?-sRgF6xB1Fl#(?1Urr9f58(LPu-ITIqF7?eY0vF?t{ScHSGzJ*d-mMG)4x*g>G<$p$Q^*WDM)1;~^5_Lr-)rlPZ zKTW+DNcC|4Y93=to2o9WDo!MGvfCJrE8e*^A2*ZjJ3$;4kwT>U~o--mxI8R=L2LaOBYqC!Z`k6SUN? zu5PLC?Bu&D31$r3La55|8g{07E$?*G_er~ZkPruo%Zn=O%1p-n`JSa#{ZrGIZ{Ac@ zmeepMFefE{`U}(=GuAwcAF=hS&!v)Gl_XHH_LSE{yIG}fHuk;umeTgKRA^CES)!sY z#WmIV2PgcwKn)rvMK)6Y2}1N)&!BM~k5{X3C={ z_oW5`9iqO>8atmzn_fYNpR>lE3}@4GxutOSd6mnx!`bI!E_a?My-Pglt%I|9$h66` zi-=A4S>2B#HeK#MIC=JR+82uoq|K53WtXZ8PP~lY+xJ&$^AYkb6rOk4heiCB;RlNF z@uR_kfBbFxELCdS-Wn2#ZQGG|ZK{j8A)Bnpv2C9dUPJor>(A+xmsTb!D{JjEx(DBn zQB#b=-g^%AO|~i~7nMbIDN`{1a%ljB5+uFdUW(Xsxi{eU4m=Z| zGWGr)&OEy7#(nDHWZk#TpKJ3A9&P}f&AY3&FWf#cevW}VG=`fAX9q^t=IL<9$LMW> z+ard1!^6D`XXgQKdi(X2ZscCy@z`UF3y*i;NsfL z7P##7K4a`haP}E{zl?LhjIl#_CYha^yRa6H<+VYu=K}eoK+Rn^2hOJFa$ke9ZOP>p z!`Xh6$tl$l(X(w|r>E5E5j~f?2+sOq+l|$`GGf!^uJ!2M?9p2fC+8LkuFVq}93InD zH*OeC#`!q{!j_q9bF4?N*rRuZhpU3K>DZ&VEo0<#INK&%?sT}5V)FMIoUL0|?|r!G zF?wZW{2aseH%B>$FB{-c4T8%(RM8k>8XqZ}l?58!McbGg4qY`WYoG-l`^ zxZLh=HV-bhmq%}ZI9r~s-WZR~M8u};zv7tWuOg!7a+5qGe9+&->tH?kd66+k*k%Ovy|Z?gAR#GEH^U+X`0_!yQ87S{=h(4`&snm_CAiw{Q<5f#^xbZ=yzhcpTSL!;dY^b<9rzecX*86(H?FY+}Ies@4$UEhWik1 zS`1fCVJwf~Zh?zS?>V?bV)Ql23f5a4 zX7uPbVG!|kaD^tu~634`=h`a#z7w zKW#nQJp2UC#@VCg9)q)fy4*%M>x;|1=+S%CqxVNRn+MnCR*%h3;SST)5MCqNJRHcx zrYMG+0aqBqwZhrFGX#f0+RI80cP5-I7guksNAF?}_ic~O>)>pex#`^zvB{7h2Fb&{ zaJGzH?g@|HvmWj@a5nF*&DTA8Z+Z0I_vmf)aG!c?{sZnnQyQ+HLm}+F1eZGrZgPy? zO>njzT)n&DCdTN!31{aFoF>B{b@U;eou6?^3xjZj*_X%Gx66%&vo>9>49=cATO1a`$++`{8W+boCyAvwphV zCOA9a<D+7dTsx;`39Gv#W<@SQJdbWJTA@ODZh@Q)hfh!e3 z0;j?-h~7dt>!-^#M$&V+7LQ)1NAC=e-ZwmY7kTuq^yppd(Yx8Bw;s;62{-Q#z!jQO z358-TCyWF4QY~8xt-#mKaNSt0jIGYF8<`B3zUk-+|b5e%OFi8F; z6sE78TrLS`ZMxjiaMn+ktAn$Cy4*ZCJ7zH?hCzHey)ZpSy4-DW))$w%)5G28;U4sG zkHOjex#>LvXY=QBuSfJ47Q!I;d%G~5KbPx2Je@z6+sDHl;NgbD**v&5$9VJ-5xs-M zr(Nb=mxr4SXUoOan*}$?lm^8Rh5~+F4rlAOFl2OkSHamlxZF)1z1uu`cX{+Sc({i= zHlOh5J?qhX$)oqWNAGQq-uoWCZ63Y9dh~X9^mgOsQd}JkfQzf!!5+N>;cQ!S>wP?& zJtw+cT_inR4nqOIrbleL+(M6Dqla4#XU8+w=H+m9uEEbRh%Yx1Vds17m{~Ql@CERdxQ#Dghsh^HlYJo9ym^H{z z@;+b!_pD6ZXmgZnK+mG2yTlA5nOIlLaD-lQEH4i%0a}p!r8KRxdLt$*m`%l zesH!tU2dR9Z$FRT!Em-7T$>X;Hp?U2;cD!zHj9$Kqdc4}cD4C)^^S$JzPQ|pa8z#) zT<#n=J7=@kt0E}ATpvl#<-QMR%hToV@aWy^(fb9Q9Y0;0Ps7=E;&NNzZ2nwspW?L5 zurrwa4TrO1vdfji*)iGWrortkg+$2Y`V^c5*P^NL`LFz0p!yU%3wJ^cH=-o%C*3U! zqE`fG>)qulJlrG?R|jY7&$T%N&bFmYj_1~Jg~mI&a2TY$oDFBkNSC`B&gQ}8Zt`%q zdAK{_Y#v;j8{ljnT<%FYdq2b8+mVb&9^Qzg=W=gH(sQ{FJbK$adY^eXx#-_R93!~t z?Ez===W;{gY`wYM6u82`Vt1R%;OzB{t9KsU$9=V8!syFE%B-`JbwRu6NS9mtM z&W+)of%|3*H*K;~^1W0EuAddPe0L`IIb-xT%~I--81Ay;lv*3Z?LAwm+hX!?{~XFHhI@|;91&x4`0+}O ziqWf^$2lOTJWrUPo@2UsUjnx~bH%4KR9~3d112d=^R1<#t5UbGa`q zNS|{UO2Z&FN5k!HVqESBI9o0*m-28^;Osfa)td!p%f;mu!P#>oLunYq&((0&PnWwG z&id(c--ffkxZHJc))$w%!(;PaxN_rNS?HyV^Ns2~IGcxZ#Uecugpql`_%6gKAtMhQv;jAyN&4qBb&1Z6x#+?iIMN>`{ zYI-spmm|VioUYsb;B4Mq?qE1O_PE@5IGaD0I||O$-*-bYx4{^+Xgea!RmW(wp@-1e@Pw&tJ@Zq^rpj&jY)5nM{hM;T)A8bHz&sC?>#m*!xhHpeeU6gEsD?kNVvE<8s*^* zg^SBynTM_ofJ?TB~(R;54Wes=3uzE_A=6A zbCicW6mBo2!z6Q*Ljg#_*}0y}wRrT-@^F{I?PJoJY>sj$0Jp%|xnj!U?t|OU#8o-m zvv4e14??xWy$omDwaabxa9iN)dD_+c2ySX0ols3Ay!MHvVqrvO^ z{VVGBMr{5TIr--EcK(+4nKmFVScScpNP7g_NVxH&EjQ%GA+wIZ2Vi>>>Bx6iYLJ!h zOuPnPi9LCTdI2&W=wDA--{-g|_ypOd$k;qeKE;-x`iKR`cd}K%f{vA)oeMgH%|#Z} z%N~l2Z4C?T&RYx2?sXFyI&;-9`@`g+VRjJAN29)_rEO(b9vXJz$vjoqEG-X>==M8# zsAcY6kb6mI=%ruD%_HTEJvsBxv-{xXp<=fs>4i$LBS;>4cIT`-RKlVRH=)f#Ib&C+ zJoGYlQprQl?23?kLy;}$^0MFAnTNQoS-o*q9*X2ce>pJ^9oeZU5Akrr);x4FH$=%p zF?08-JQTz2S@Y1z+=4C-#jvU8p_65=)I7B1LlVI*PSb)Y}U+H+<4I|ANUEUvbRP z?UN7t_{ZF+nmDbwb$Rf$g^8`~7TT#Mc6KyOTo!EFy11pSVY!Z2(%jP2IkDl01uNq( za>J|LR<@@*wYjsoOE=QMVqONC%^rI7!Jbai{_?kRs_gIAOI6u&uy?8}Wmm-duC9*e z#Vfm-np(R$R`?qm0)VXKDZpN)$JL83X9w&&i(wo#HH$U=MZ__*Tx5x(_dfj>3^d|&%vJJJFyG!|Jf?n8M-@Ag} zxr_(e`qpm#UboaQZfa?2+&K@L%$G!Zm;2_{aH5;P|IPB@m0qU1v!mvc;Da^2OT0;c zNT-*|E9#qD!iK&R^Bg;3_RfulwiPl>>7DWl`xU3&sqfU;YMK4=RqxWaQ|+CaW%I3# zhUGig?K*=Gob@sf!QGr@Zub2%+EIOIt+(Eo`(^nL0HOOGO-q_Oq(}DB1$)^bb;5MW zd?oOoU~DH%>_qnt%cgfOG`F_!rP`gj3~XY1-JLDVhVXS*QYztQGE#xuuV7T9Llw}wv?8)PIj!U@q=chW5 zBTu>2@AyZSJYL76?L#?k;c>St_mEfmWa&zO_zI5i0G@WM2EfyAbvJ7;t2j#FDZ07^ zd0CdZ9Hm;02Vid`$F(SxbKHp1M2V@<1>&Y952D%1deZ@cQD6Scx*p{<3!T0;W!KVF&y{dIGW=R$@I}2Wr@I8 zj)wq#s;kJKyl&7BKV^CKU&ur?$7lFE$?;gy8PD+*@^ctRS$e}ybrtD}jSsLZOKq;k z&jUD)pu7ihoPnRRZ2o%uJBZ^Vjt6oaf?grV@uV}E<6h{?GS6$#+n3`d=oNFEf?t&! zcjfN{#}?#M92b%JD2@a1YaGWPP)@Q0XE8_dZ2|U&bF9UGyA){iaV69a;c`$2{*I(n z>S>Mo$WJu{@A{&&fZzWcA&sPzN}5ka_NNf#Ta|smll;ArczIu?5Il;Ubdrauuy(k$ zRFHi8Y%-80R8tXVV5;q@i4ZkIg zE_ksoJzVU54&Dcgu)Ur%1n6_afLXw&u`)ILcnn zl1Aa7+HXlS(7{eW_<{Ix=Ha@bja;fJ`QF&;;0^G5uo=7wWIfLx!CL?|bsxtcg4@A* z@FQ>s_%XN>+y(9iKLPiEd%;hEyfd@`{0#gY+z;fNEWZE`0{O1=!{A@QFTo?=QScae z96SM@1iu1Lfv3Sn@CD1D}Wl)xZMFw>lC}dEV0aOM@8F+$0l%otXGT_LdSO|uLL%;|y5{v>=cQBYq zn;!$H;$Tpe0cAXx044$%c#41wNHXZk04alt4CpdA$`~SplnkJ95|M#SPBJpk%AhzI zq(Bv@1~s4-)Bzb|7J`$&$zTzv2a7=iXar4Q383i(``9*f{5n_;TEGg>3fe$BI0bZo zPS6Ebf>Xh1U=>&mP6uazGr?KlY;X=(1I`8C0N(^_!Fk|(Z~?dwd<$FzE(Vu?OTlH} za&QH>5_}tc2do3%1y_Nq!8PDoa2>cF+yHI_H-Ybgo53yM```!QR&X2mA-El^2R{OL zfFFZ9!Cl~P@Dp$kxEK5s+y^#*pMjr)`@sX?7vMqg5O^5;3-~2?1Uw2J1CN6zz?0xt z;3@Dl*a)5h&w^ir=fLye1+WRc2z~=z0>1?>gIB=sz^mXj@H%({{2puuZ-PI7KZ3Ww z+u$AWuV4#!7yKJ|54;aP03U*nz`uh(fsesfunqhf`~`dhwuAowpMt-F&%ocne}cb* z&%u9ze}El874SdU1@r-Z!LDF8@CDEhd=cyp_5l5XtQ{Qyz61t>y@0$gxDOZv27`UU zeqadL9~=ONf?+@=VF!VOK_M6p4gn*;NH7W<3JwEuP8kCZ2V=oFAnO<>fQdlPPeq^@ z$mzZml!0=P1QnnX909%zjs!=6qroIF8KgiJs0KBl7Sw^SfGJ=qI0hUGrh(~T2ABzE zf#bkzFbB*9$Afv`t6)Aj0elUd2o`{a;3RM|SOn_9V$c8@K@(U4mV#xV8GIcq2Q6R) zXa#NH6wnSjKqu$|E5WJYG_VS+2B(8Fz?tAIa5gvxtO4hOZ-8%twctE(KDYo}2)+d_ z0vCfzz@^|aa5=aFTnWAnz5~{Q?}Dqq)!-U%Ew~O`4{iWAf}6niz|G(m@O|(Da4Yy{ Whqtl$4)|BF1-uLXFZ}N*f&T{5eFpFV literal 245248 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

&EL|tp#@9fDNs~Rsdj6dO6}dFcyTtM) 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 HzXkpW`UCuB literal 241152 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 yhS>VAFll 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 PYT!r>9I1i-+coen1w|l| From c0a660846ec7cea1409443760e11184e4c03b873 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Tue, 15 Mar 2016 10:17:35 +1100 Subject: [PATCH 09/18] Revert all Aggregation Usage tests to have .cs extension and target by file pattern --- .../children-aggregation-mapping.asciidoc | 2 +- .../children-aggregation-usage.asciidoc | 10 +- .../date-histogram-aggregation-usage.asciidoc | 8 +- .../date-range-aggregation-usage.asciidoc | 10 +- .../filter/filter-aggregation-usage.asciidoc | 16 +- .../filters-aggregation-usage.asciidoc | 44 ++-- .../geo-distance-aggregation-usage.asciidoc | 8 +- .../geo-hash-grid-aggregation-usage.asciidoc | 8 +- .../global/global-aggregation-usage.asciidoc | 8 +- .../histogram-aggregation-usage.asciidoc | 8 +- .../ip-range-aggregation-usage.asciidoc | 8 +- .../missing-aggregation-usage.asciidoc | 8 +- .../nested/nested-aggregation-usage.asciidoc | 8 +- .../range/range-aggregation-usage.asciidoc | 8 +- .../reverse-nested-aggregation-usage.asciidoc | 8 +- .../sampler-aggregation-usage.asciidoc | 8 +- ...gnificant-terms-aggregation-usage.asciidoc | 8 +- .../terms/terms-aggregation-usage.asciidoc | 8 +- .../average-aggregation-usage.asciidoc | 8 +- .../cardinality-aggregation-usage.asciidoc | 8 +- .../extended-stats-aggregation-usage.asciidoc | 8 +- .../geo-bounds-aggregation-usage.asciidoc | 8 +- .../metric/max/max-aggregation-usage.asciidoc | 8 +- .../metric/min/min-aggregation-usage.asciidoc | 8 +- ...ercentile-ranks-aggregation-usage.asciidoc | 8 +- .../percentiles-aggregation-usage.asciidoc | 8 +- ...scripted-metric-aggregation-usage.asciidoc | 8 +- .../stats/stats-aggregation-usage.asciidoc | 8 +- .../metric/sum/sum-aggregation-usage.asciidoc | 8 +- .../top-hits-aggregation-usage.asciidoc | 8 +- .../value-count-aggregation-usage.asciidoc | 8 +- .../average-bucket-aggregation-usage.asciidoc | 8 +- .../bucket-script-aggregation-usage.asciidoc | 8 +- ...bucket-selector-aggregation-usage.asciidoc | 8 +- .../cumulative-sum-aggregation-usage.asciidoc | 8 +- .../derivative-aggregation-usage.asciidoc | 8 +- .../max-bucket-aggregation-usage.asciidoc | 8 +- .../min-bucket-aggregation-usage.asciidoc | 8 +- ...ng-average-ewma-aggregation-usage.asciidoc | 8 +- ...age-holt-linear-aggregation-usage.asciidoc | 8 +- ...ge-holt-winters-aggregation-usage.asciidoc | 8 +- ...-average-linear-aggregation-usage.asciidoc | 8 +- ...-average-simple-aggregation-usage.asciidoc | 8 +- ...al-differencing-aggregation-usage.asciidoc | 8 +- .../sum-bucket-aggregation-usage.asciidoc | 8 +- .../writing-aggregations.asciidoc | 10 +- .../analyzers/analyzer-usage.asciidoc | 74 ++++++ .../char-filters/char-filter-usage.asciidoc | 45 ++++ .../token-filters/token-filter-usage.asciidoc | 237 ++++++++++++++++++ .../tokenizers/tokenizer-usage.asciidoc | 73 ++++++ .../connection-pooling.asciidoc | 36 +-- .../date-time-providers.asciidoc | 10 +- .../keeping-track-of-nodes.asciidoc | 20 +- .../request-pipelines.asciidoc | 40 +-- .../building-blocks/transports.asciidoc | 6 +- .../exceptions/unexpected-exceptions.asciidoc | 8 +- .../unrecoverable-exceptions.asciidoc | 8 +- .../failover/falling-over.asciidoc | 8 +- .../max-retries/respects-max-retry.asciidoc | 12 +- .../pinging/first-usage.asciidoc | 10 +- .../pinging/revival.asciidoc | 2 +- .../disable-sniff-ping-per-request.asciidoc | 8 +- .../request-timeouts-overrides.asciidoc | 8 +- .../respects-allowed-status-code.asciidoc | 2 +- .../respects-force-node.asciidoc | 2 +- .../respects-max-retry-overrides.asciidoc | 6 +- .../round-robin/round-robin.asciidoc | 8 +- .../round-robin/skip-dead-nodes.asciidoc | 18 +- .../round-robin/volatile-updates.asciidoc | 6 +- .../sniffing/on-connection-failure.asciidoc | 8 +- .../sniffing/on-stale-cluster-state.asciidoc | 10 +- .../sniffing/on-startup.asciidoc | 12 +- .../sniffing/role-detection.asciidoc | 16 +- .../covariant-search-results.asciidoc | 36 +-- .../inference/document-paths.asciidoc | 20 +- .../inference/field-inference.asciidoc | 72 +++--- .../inference/ids-inference.asciidoc | 16 +- .../inference/indices-paths.asciidoc | 4 +- .../inference/property-inference.asciidoc | 6 +- .../high-level/mapping/auto-map.asciidoc | 42 ++-- .../low-level/connecting.asciidoc | 30 +-- .../low-level/lifetimes.asciidoc | 6 +- .../low-level/post-data.asciidoc | 28 +-- .../code-standards/descriptors.asciidoc | 4 +- .../code-standards/elastic-client.asciidoc | 12 +- .../naming-conventions.asciidoc | 10 +- docs/asciidoc/code-standards/queries.asciidoc | 8 +- .../serialization/properties.asciidoc | 2 +- .../date-math/date-math-expressions.asciidoc | 20 +- .../time-unit/time-units.asciidoc | 16 +- docs/asciidoc/index.asciidoc | 174 ++++++++++++- docs/asciidoc/low-level.asciidoc | 1 + .../query-dsl/bool-dsl/bool-dsl.asciidoc | 12 +- .../operators/and-operator-usage.asciidoc | 93 +++++++ .../operators/not-operator-usage.asciidoc | 100 ++++++++ .../operators/or-operator-usage.asciidoc | 104 ++++++++ .../unary-add-operator-usage.asciidoc | 111 ++++++++ .../compound/and/and-query-usage.asciidoc | 4 +- .../bool-dsl-complex-query-usage.asciidoc | 135 ++++++++++ .../compound/bool/bool-query-usage.asciidoc | 52 ++++ .../boosting/boosting-query-usage.asciidoc | 42 ++++ .../constant-score-query-usage.asciidoc | 34 +++ .../dismax/dismax-query-usage.asciidoc | 46 ++++ .../filtered/filtered-query-usage.asciidoc | 40 +++ .../function-score-query-usage.asciidoc | 115 +++++++++ .../indices-no-match-query-usage.asciidoc | 38 +++ .../indices/indices-query-usage.asciidoc | 43 ++++ .../compound/limit/limit-query-usage.asciidoc | 30 +++ .../compound/not/not-query-usage.asciidoc | 44 ++++ .../compound/or/or-query-usage.asciidoc | 44 ++++ .../common-terms/common-terms-usage.asciidoc | 45 ++++ .../match/match-phrase-prefix-usage.asciidoc | 56 +++++ .../match/match-phrase-usage.asciidoc | 56 +++++ .../full-text/match/match-usage.asciidoc | 55 ++++ .../multi-match/multi-match-usage.asciidoc | 59 +++++ .../query-string/query-string-usage.asciidoc | 81 ++++++ .../simple-query-string-usage.asciidoc | 51 ++++ .../geo-bounding-box-query-usage.asciidoc | 52 ++++ .../geo-distance-range-query-usage.asciidoc | 52 ++++ .../geo/distance/distance-units.asciidoc | 24 +- .../geo-distance-query-usage.asciidoc | 46 ++++ .../geo-hash-cell-query-usage.asciidoc | 38 +++ .../polygon/geo-polygon-query-usage.asciidoc | 48 ++++ .../circle/geo-shape-circle-usage.asciidoc | 19 ++ .../envelope/geo-envelope-usage.asciidoc | 19 ++ .../geo-indexed-shape-usage.asciidoc | 44 ++++ .../geo-line-string-usage.asciidoc | 19 ++ .../geo-multi-line-string-usage.asciidoc | 19 ++ .../geo-multi-point-usage.asciidoc | 19 ++ .../geo/shape/point/geo-point-usage.asciidoc | 19 ++ .../shape/polygon/geo-polygon-usage.asciidoc | 19 ++ .../has-child/has-child-query-usage.asciidoc | 44 ++++ .../has-parent-query-usage.asciidoc | 40 +++ .../nested/nested-query-usage.asciidoc | 38 +++ .../raw/raw-combine-usage.asciidoc | 37 +++ .../raw/raw-query-usage.asciidoc | 23 ++ .../span-containing-query-usage.asciidoc | 44 ++++ .../first/span-first-query-usage.asciidoc | 41 +++ .../span-multi-term-query-usage.asciidoc | 36 +++ .../span/near/span-near-query-usage.asciidoc | 63 +++++ .../span/not/span-not-query-usage.asciidoc | 50 ++++ .../span/or/span-or-query-usage.asciidoc | 57 +++++ .../span/term/span-term-query-usage.asciidoc | 33 +++ .../within/span-within-query-usage.asciidoc | 44 ++++ .../more-like-this-query-usage.asciidoc | 77 ++++++ .../script/script-query-usage.asciidoc | 37 +++ .../template/template-query-usage.asciidoc | 41 +++ .../exists/exists-query-usage.asciidoc | 30 +++ .../fuzzy/fuzzy-date-query-usage.asciidoc | 43 ++++ .../fuzzy/fuzzy-numeric-query-usage.asciidoc | 43 ++++ .../fuzzy/fuzzy-query-usage.asciidoc | 43 ++++ .../term-level/ids/ids-query-usage.asciidoc | 40 +++ .../missing/missing-query-usage.asciidoc | 34 +++ .../prefix/prefix-query-usage.asciidoc | 35 +++ .../range/date-range-query-usage.asciidoc | 43 ++++ .../range/numeric-range-query-usage.asciidoc | 39 +++ .../range/term-range-query-usage.asciidoc | 39 +++ .../regexp/regexp-query-usage.asciidoc | 37 +++ .../term-level/term/term-query-usage.asciidoc | 33 +++ .../terms/terms-lookup-query-usage.asciidoc | 42 ++++ .../terms/terms-query-usage.asciidoc | 38 +++ .../term-level/type/type-query-usage.asciidoc | 30 +++ .../wildcard/wildcard-query-usage.asciidoc | 35 +++ .../search/request/explain-usage.asciidoc | 31 +++ .../request/fielddata-fields-usage.asciidoc | 40 +++ .../search/request/fields-usage.asciidoc | 38 +++ .../request/from-and-size-usage.asciidoc | 35 +++ .../request/highlighting-usage.asciidoc | 190 ++++++++++++++ .../search/request/index-boost-usage.asciidoc | 42 ++++ .../search/request/inner-hits-usage.asciidoc | 150 +++++++++++ .../search/request/min-score-usage.asciidoc | 47 ++++ .../search/request/post-filter-usage.asciidoc | 34 +++ .../search/request/query-usage.asciidoc | 46 ++++ .../request/script-fields-usage.asciidoc | 69 +++++ .../search/request/sort-usage.asciidoc | 162 ++++++++++++ .../request/source-filtering-usage.asciidoc | 116 +++++++++ .../search/request/suggest-usage.asciidoc | 227 +++++++++++++++++ .../search/suggesters/suggest-api.asciidoc | 8 +- .../Nest.Litterateur/AsciiDoc/AsciiVisitor.cs | 34 ++- .../Documentation/Blocks/CodeBlock.cs | 6 +- .../Documentation/Blocks/CombinedBlock.cs | 2 +- .../Files/CSharpDocumentationFile.cs | 2 +- src/CodeGeneration/Nest.Litterateur/LitUp.cs | 21 +- .../Nest.Litterateur/StringExtensions.cs | 6 +- ...oc.cs => ChildrenAggregationUsageTests.cs} | 2 - ... => DateHistogramAggregationUsageTests.cs} | 0 ...c.cs => DateRangeAggregationUsageTests.cs} | 0 ....doc.cs => FilterAggregationUsageTests.cs} | 0 ...doc.cs => FiltersAggregationUsageTests.cs} | 5 +- ...cs => GeoDistanceAggregationUsageTests.cs} | 0 ...cs => GeoHashGridAggregationUsageTests.cs} | 0 ....doc.cs => GlobalAggregationUsageTests.cs} | 0 ...c.cs => HistogramAggregationUsageTests.cs} | 0 ...doc.cs => IpRangeAggregationUsageTests.cs} | 0 ...doc.cs => MissingAggregationUsageTests.cs} | 0 ....doc.cs => NestedAggregationUsageTests.cs} | 0 ...s.doc.cs => RangeAggregationUsageTests.cs} | 0 ... => ReverseNestedAggregationUsageTests.cs} | 0 ...doc.cs => SamplerAggregationUsageTests.cs} | 0 ... SignificantTermsAggregationUsageTests.cs} | 0 ...s.doc.cs => TermsAggregationUsageTests.cs} | 0 ...doc.cs => AverageAggregationUsageTests.cs} | 0 ...cs => CardinalityAggregationUsageTests.cs} | 0 ... => ExtendedStatsAggregationUsageTests.cs} | 0 ...c.cs => GeoBoundsAggregationUsageTests.cs} | 0 ...sts.doc.cs => MaxAggregationUsageTests.cs} | 0 ...sts.doc.cs => MinAggregationUsageTests.cs} | 0 ...> PercentileRanksAggregationUsageTests.cs} | 0 ...cs => PercentilesAggregationUsageTests.cs} | 0 ...=> ScriptedMetricAggregationUsageTests.cs} | 0 ...s.doc.cs => StatsAggregationUsageTests.cs} | 0 ...sts.doc.cs => SumAggregationUsageTests.cs} | 0 ...doc.cs => TopHitsAggregationUsageTests.cs} | 0 ....cs => ValueCountAggregationUsageTests.cs} | 0 ... => AverageBucketAggregationUsageTests.cs} | 0 ...s => BucketScriptAggregationUsageTests.cs} | 0 ...=> BucketSelectorAggregationUsageTests.cs} | 0 ... => CumulativeSumAggregationUsageTests.cs} | 0 ....cs => DerivativeAggregationUsageTests.cs} | 0 ...c.cs => MaxBucketAggregationUsageTests.cs} | 0 ...c.cs => MinBucketAggregationUsageTests.cs} | 0 ...MovingAverageEwmaAggregationUsageTests.cs} | 0 ...AverageHoltLinearAggregationUsageTests.cs} | 0 ...verageHoltWintersAggregationUsageTests.cs} | 0 ...vingAverageLinearAggregationUsageTests.cs} | 0 ...vingAverageSimpleAggregationUsageTests.cs} | 0 ...erialDifferencingAggregationUsageTests.cs} | 0 ...c.cs => SumBucketAggregationUsageTests.cs} | 0 .../{BulkApiTests.doc.cs => BulkApiTests.cs} | 0 ...sageTests.doc.cs => AndQueryUsageTests.cs} | 0 230 files changed, 5603 insertions(+), 558 deletions(-) create mode 100644 docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc create mode 100644 docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc create mode 100644 docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc create mode 100644 docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc create mode 100644 docs/asciidoc/low-level.asciidoc create mode 100644 docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc create mode 100644 docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc create mode 100644 docs/asciidoc/search/request/explain-usage.asciidoc create mode 100644 docs/asciidoc/search/request/fielddata-fields-usage.asciidoc create mode 100644 docs/asciidoc/search/request/fields-usage.asciidoc create mode 100644 docs/asciidoc/search/request/from-and-size-usage.asciidoc create mode 100644 docs/asciidoc/search/request/highlighting-usage.asciidoc create mode 100644 docs/asciidoc/search/request/index-boost-usage.asciidoc create mode 100644 docs/asciidoc/search/request/inner-hits-usage.asciidoc create mode 100644 docs/asciidoc/search/request/min-score-usage.asciidoc create mode 100644 docs/asciidoc/search/request/post-filter-usage.asciidoc create mode 100644 docs/asciidoc/search/request/query-usage.asciidoc create mode 100644 docs/asciidoc/search/request/script-fields-usage.asciidoc create mode 100644 docs/asciidoc/search/request/sort-usage.asciidoc create mode 100644 docs/asciidoc/search/request/source-filtering-usage.asciidoc create mode 100644 docs/asciidoc/search/request/suggest-usage.asciidoc rename src/Tests/Aggregations/Bucket/Children/{ChildrenAggregationUsageTests.doc.cs => ChildrenAggregationUsageTests.cs} (97%) rename src/Tests/Aggregations/Bucket/DateHistogram/{DateHistogramAggregationUsageTests.doc.cs => DateHistogramAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/DateRange/{DateRangeAggregationUsageTests.doc.cs => DateRangeAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Filter/{FilterAggregationUsageTests.doc.cs => FilterAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Filters/{FiltersAggregationUsageTests.doc.cs => FiltersAggregationUsageTests.cs} (97%) rename src/Tests/Aggregations/Bucket/GeoDistance/{GeoDistanceAggregationUsageTests.doc.cs => GeoDistanceAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/GeoHashGrid/{GeoHashGridAggregationUsageTests.doc.cs => GeoHashGridAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Global/{GlobalAggregationUsageTests.doc.cs => GlobalAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Histogram/{HistogramAggregationUsageTests.doc.cs => HistogramAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/IpRange/{IpRangeAggregationUsageTests.doc.cs => IpRangeAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Missing/{MissingAggregationUsageTests.doc.cs => MissingAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Nested/{NestedAggregationUsageTests.doc.cs => NestedAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Range/{RangeAggregationUsageTests.doc.cs => RangeAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/ReverseNested/{ReverseNestedAggregationUsageTests.doc.cs => ReverseNestedAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Sampler/{SamplerAggregationUsageTests.doc.cs => SamplerAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/SignificantTerms/{SignificantTermsAggregationUsageTests.doc.cs => SignificantTermsAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Bucket/Terms/{TermsAggregationUsageTests.doc.cs => TermsAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Average/{AverageAggregationUsageTests.doc.cs => AverageAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Cardinality/{CardinalityAggregationUsageTests.doc.cs => CardinalityAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/ExtendedStats/{ExtendedStatsAggregationUsageTests.doc.cs => ExtendedStatsAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/GeoBounds/{GeoBoundsAggregationUsageTests.doc.cs => GeoBoundsAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Max/{MaxAggregationUsageTests.doc.cs => MaxAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Min/{MinAggregationUsageTests.doc.cs => MinAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/PercentileRanks/{PercentileRanksAggregationUsageTests.doc.cs => PercentileRanksAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Percentiles/{PercentilesAggregationUsageTests.doc.cs => PercentilesAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/ScriptedMetric/{ScriptedMetricAggregationUsageTests.doc.cs => ScriptedMetricAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Stats/{StatsAggregationUsageTests.doc.cs => StatsAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/Sum/{SumAggregationUsageTests.doc.cs => SumAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/TopHits/{TopHitsAggregationUsageTests.doc.cs => TopHitsAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Metric/ValueCount/{ValueCountAggregationUsageTests.doc.cs => ValueCountAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/AverageBucket/{AverageBucketAggregationUsageTests.doc.cs => AverageBucketAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/BucketScript/{BucketScriptAggregationUsageTests.doc.cs => BucketScriptAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/BucketSelector/{BucketSelectorAggregationUsageTests.doc.cs => BucketSelectorAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/CumulativeSum/{CumulativeSumAggregationUsageTests.doc.cs => CumulativeSumAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/Derivative/{DerivativeAggregationUsageTests.doc.cs => DerivativeAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MaxBucket/{MaxBucketAggregationUsageTests.doc.cs => MaxBucketAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MinBucket/{MinBucketAggregationUsageTests.doc.cs => MinBucketAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageEwmaAggregationUsageTests.doc.cs => MovingAverageEwmaAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageHoltLinearAggregationUsageTests.doc.cs => MovingAverageHoltLinearAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageHoltWintersAggregationUsageTests.doc.cs => MovingAverageHoltWintersAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageLinearAggregationUsageTests.doc.cs => MovingAverageLinearAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/MovingAverage/{MovingAverageSimpleAggregationUsageTests.doc.cs => MovingAverageSimpleAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/SerialDifferencing/{SerialDifferencingAggregationUsageTests.doc.cs => SerialDifferencingAggregationUsageTests.cs} (100%) rename src/Tests/Aggregations/Pipeline/SumBucket/{SumBucketAggregationUsageTests.doc.cs => SumBucketAggregationUsageTests.cs} (100%) rename src/Tests/Document/Multiple/Bulk/{BulkApiTests.doc.cs => BulkApiTests.cs} (100%) rename src/Tests/QueryDsl/Compound/And/{AndQueryUsageTests.doc.cs => AndQueryUsageTests.cs} (100%) diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc index ac427837537..99fb5d1bef9 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-mapping.asciidoc @@ -11,7 +11,7 @@ To use the child aggregation you have to make sure index with two mapped types, `project` and `commitactivity` and we add a `_parent` mapping from `commitactivity` to `parent` -[source,csharp,method-name="mappingexample"] +[source,csharp,method="mappingexample"] ---- var createProjectIndex = TestClient.GetClient().CreateIndex(typeof(Project), c => c .Mappings(map => map diff --git a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc index a82e206a0db..c71259ea2c5 100644 --- a/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/children/children-aggregation-usage.asciidoc @@ -11,7 +11,7 @@ buckets on child documents. Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-children-aggregation.html[on this subject here] -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -37,11 +37,9 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation } ---- -Fluent DSL Example - === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -54,11 +52,9 @@ s => s ) ---- -Object Initializer Syntax Example - === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { diff --git a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc index a13335b2190..f750140c7f7 100644 --- a/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-histogram/date-histogram-aggregation-usage.asciidoc @@ -16,7 +16,7 @@ as part of the format value. Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregation.html[the elasticsearch documentation on Date Histogram Aggregation]. -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -58,7 +58,7 @@ Be sure to read {ref_current}/search-aggregations-bucket-datehistogram-aggregati === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -85,7 +85,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -120,7 +120,7 @@ new SearchRequest Using the `.Aggs` aggregation helper on `ISearchResponse`, we can fetch our aggregation results easily in the correct type. TODO: [Be sure to read more about `.Agg` vs `.Aggregations` on the response here] -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); diff --git a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc index 6fc4bc00e1c..ce9c98bba24 100644 --- a/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/date-range/date-range-aggregation-usage.asciidoc @@ -16,7 +16,7 @@ IMPORTANT: this aggregation includes the `from` value and excludes the `to` valu Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.html[the elasticsearch documentation on {sectiontitle}] -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -51,7 +51,7 @@ Be sure to read {ref_current}/search-aggregations-bucket-daterange-aggregation.h === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -71,7 +71,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -95,7 +95,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -108,7 +108,7 @@ We specified three ranges so we expect to have three of them in the response === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- dateHistogram.Buckets.Count.Should().Be(3); diff --git a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc index 37d423873dd..719fbb3edb9 100644 --- a/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filter/filter-aggregation-usage.asciidoc @@ -11,7 +11,7 @@ Often this will be used to narrow down the current aggregation context to a spec Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html[the elasticsearch documentation on Filter Aggregation] -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -38,7 +38,7 @@ Be sure to read {ref_current}/search-aggregations-bucket-filter-aggregation.html === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -53,7 +53,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -71,7 +71,7 @@ new SearchRequest Using the `.Aggs` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -88,7 +88,7 @@ tags.Buckets.Should().NotBeEmpty(); When the collection of filters is empty or all are conditionless, NEST will serialize them to an empty object. -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -102,7 +102,7 @@ to an empty object. === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -118,7 +118,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -134,7 +134,7 @@ new SearchRequest === Handling Response -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filter("empty_filter").DocCount.Should().BeGreaterThan(0); diff --git a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc index a3a47250bcd..a4185aaf8be 100644 --- a/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/filters/filters-aggregation-usage.asciidoc @@ -8,13 +8,13 @@ Defines a multi bucket aggregations where each bucket is associated with a filter. Each bucket will collect all documents that match its associated filter. For documents -that do not match any filter, these will be collected in the other bucket. +that do not match any filter, these will be collected in the _other bucket_. -Be sure to read the elasticsearch documentation {ref_current}/search-aggregations-bucket-filters-aggregation.html[on this subject here] +Be sure to read {ref_current}/search-aggregations-bucket-filters-aggregation.html[the Elasticsearch documentation on Filters Aggregation]. == Named filters -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -61,7 +61,7 @@ Be sure to read the elasticsearch documentation {ref_current}/search-aggregation === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -82,7 +82,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -107,7 +107,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -129,7 +129,7 @@ namedResult.DocCount.Should().Be(0); == Anonymous filters -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -175,7 +175,7 @@ namedResult.DocCount.Should().Be(0); === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -195,7 +195,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -222,7 +222,7 @@ new SearchRequest Using the `.Agg` aggregation helper we can fetch our aggregation results easily in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]() -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); @@ -231,12 +231,20 @@ filterAgg.Should().NotBeNull(); var results = filterAgg.AnonymousBuckets(); results.Count.Should().Be(4); singleBucket.DocCount.Should().BeGreaterThan(0); +---- + +The last bucket is the _other bucket_ + +=== Handling Responses + +[source,csharp,method="expectresponse"] +---- results.Last().DocCount.Should().Be(0); ---- == Empty Filters -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -252,7 +260,7 @@ results.Last().DocCount.Should().Be(0); === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -264,7 +272,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -277,7 +285,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); @@ -285,7 +293,7 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); == Conditionless Filters -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -301,7 +309,7 @@ response.Aggs.Filters("empty_filters").Buckets.Should().BeEmpty(); === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -315,7 +323,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -331,7 +339,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); response.Aggs.Filters("conditionless_filters").Buckets.Should().BeEmpty(); diff --git a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc index 6753dd411e8..ba2d7da4af4 100644 --- a/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-distance/geo-distance-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -36,7 +36,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -54,7 +54,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -74,7 +74,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var ringsAroundAmsterdam = response.Aggs.GeoDistance("rings_around_amsterdam"); diff --git a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc index 8362425ef93..a5a2aed71e0 100644 --- a/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/geo-hash-grid/geo-hash-grid-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -23,7 +23,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -38,7 +38,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -54,7 +54,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var myGeoHashGrid = response.Aggs.GeoHash("my_geohash_grid"); diff --git a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc index 90615ec164e..ff04357043b 100644 --- a/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/global/global-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -25,7 +25,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -41,7 +41,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -57,7 +57,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var allProjects = response.Aggs.Global("all_projects"); diff --git a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc index 756085c889d..6496e64c413 100644 --- a/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/histogram/histogram-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -25,7 +25,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -40,7 +40,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -56,7 +56,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commits = response.Aggs.Histogram("commits"); diff --git a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc index d1ce3173006..e8dd43fd886 100644 --- a/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/ip-range/ip-range-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -28,7 +28,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -44,7 +44,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -62,7 +62,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var ipRanges = response.Aggs.IpRange("ip_ranges"); diff --git a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc index a6f8c14c041..3d1502380e4 100644 --- a/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/missing/missing-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -45,7 +45,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsWithoutDesc = response.Aggs.Missing("projects_without_a_description"); diff --git a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc index a79c6c84a50..121f4084956 100644 --- a/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/nested/nested-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -27,7 +27,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -44,7 +44,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -61,7 +61,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var tags = response.Aggs.Nested("tags"); diff --git a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc index 1dcdfb7cd71..34db5d81177 100644 --- a/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/range/range-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -32,7 +32,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -49,7 +49,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -68,7 +68,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitRanges = response.Aggs.Range("commit_ranges"); diff --git a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc index c1867778c0f..f3e74ed8399 100644 --- a/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/reverse-nested/reverse-nested-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -39,7 +39,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -65,7 +65,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -89,7 +89,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var tags = response.Aggs.Nested("tags"); diff --git a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc index b34082451c6..120c184acea 100644 --- a/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/sampler/sampler-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -28,7 +28,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -46,7 +46,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -64,7 +64,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var sample = response.Aggs.Sampler("sample"); diff --git a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc index 1dda79e617c..255757373b1 100644 --- a/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/significant-terms/significant-terms-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -25,7 +25,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -42,7 +42,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -61,7 +61,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var sigNames = response.Aggs.SignificantTerms("significant_names"); diff --git a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc index 7283841fda0..6d5cbe0cec4 100644 --- a/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/bucket/terms/terms-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -40,7 +40,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -64,7 +64,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -93,7 +93,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var states = response.Aggs.Terms("states"); diff --git a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc index d1a34806415..9c2f9af06be 100644 --- a/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/average/average-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -27,7 +27,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -44,7 +44,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -62,7 +62,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitsAvg = response.Aggs.Average("average_commits"); diff --git a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc index 7ec6a3c505d..ed8e1eacbc1 100644 --- a/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/cardinality/cardinality-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -21,7 +21,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -34,7 +34,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -47,7 +47,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectCount = response.Aggs.Cardinality("state_count"); diff --git a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc index 62308fdeeef..98148760544 100644 --- a/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/extended-stats/extended-stats-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitStats = response.Aggs.ExtendedStats("commit_stats"); diff --git a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc index fc20f4f0ea7..cb5d25bc0c1 100644 --- a/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/geo-bounds/geo-bounds-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -21,7 +21,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -34,7 +34,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -47,7 +47,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var viewport = response.Aggs.GeoBounds("viewport"); diff --git a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc index 93b7f4e11ba..1223a64c70d 100644 --- a/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/max/max-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var max = response.Aggs.Max("max_commits"); diff --git a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc index fde7d62514a..e6fe8a591a1 100644 --- a/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/min/min-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var min = response.Aggs.Max("min_commits"); diff --git a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc index d46b028356b..fb0061e4cf4 100644 --- a/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentile-ranks/percentile-ranks-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -31,7 +31,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -51,7 +51,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -70,7 +70,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitsOutlier = response.Aggs.PercentileRanks("commits_outlier"); diff --git a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc index 302697ffd7d..f0719ad6672 100644 --- a/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/percentiles/percentiles-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -32,7 +32,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -52,7 +52,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -71,7 +71,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitsOutlier = response.Aggs.Percentiles("commits_outlier"); diff --git a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc index 01a6797e521..66ae4a224ec 100644 --- a/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/scripted-metric/scripted-metric-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -31,7 +31,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -46,7 +46,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -62,7 +62,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var sumTheHardWay = response.Aggs.ScriptedMetric("sum_the_hard_way"); diff --git a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc index b99ccf3f998..a49d559ed6f 100644 --- a/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/stats/stats-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitStats = response.Aggs.Stats("commit_stats"); diff --git a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc index a2b19e6876e..072e1b225c9 100644 --- a/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/sum/sum-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitsSum = response.Aggs.Sum("commits_sum"); diff --git a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc index fab343e98ec..cf49ab9e854 100644 --- a/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/top-hits/top-hits-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -59,7 +59,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -103,7 +103,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -145,7 +145,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var states = response.Aggs.Terms("states"); diff --git a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc index b77112e6e96..91586851e1d 100644 --- a/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/metric/value-count/value-count-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -20,7 +20,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(a => a @@ -32,7 +32,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -42,7 +42,7 @@ new SearchRequest === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var commitCount = response.Aggs.ValueCount("commit_count"); diff --git a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc index d09bab56e48..be5ea293c96 100644 --- a/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/average-bucket/average-bucket-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -35,7 +35,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -58,7 +58,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -78,7 +78,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc index 1f6faa0c1f2..a11a4b1aead 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-script/bucket-script-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -56,7 +56,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -92,7 +92,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -126,7 +126,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc index 621d33e2cb1..97538352169 100644 --- a/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/bucket-selector/bucket-selector-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -39,7 +39,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -64,7 +64,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -88,7 +88,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc index b9da5bad5a3..ce96ce52b5d 100644 --- a/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/cumulative-sum/cumulative-sum-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -34,7 +34,7 @@ === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); @@ -48,7 +48,7 @@ commitsDerivative.Value.Should().NotBe(null); === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -70,7 +70,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { diff --git a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc index ddd5ccc9aa4..14d79bbcea1 100644 --- a/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/derivative/derivative-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -34,7 +34,7 @@ === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); @@ -48,7 +48,7 @@ commitsDerivative.Value.Should().NotBe(null); === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -70,7 +70,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { diff --git a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc index 4ad3e31344f..918669178a8 100644 --- a/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/max-bucket/max-bucket-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -34,7 +34,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -56,7 +56,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -73,7 +73,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc index c277c017ad1..332b5927d69 100644 --- a/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/min-bucket/min-bucket-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -34,7 +34,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -56,7 +56,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -73,7 +73,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc index 7b8012c8fab..ec35876fe7d 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-ewma-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -38,7 +38,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -65,7 +65,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -89,7 +89,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc index 4daf10a16c1..8c62867ff83 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-linear-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -39,7 +39,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -67,7 +67,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -92,7 +92,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc index a5f03bfba41..0b5a3e3da36 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-holt-winters-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -44,7 +44,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -77,7 +77,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -107,7 +107,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); ---- diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc index 2974260a8fc..16bb300d22b 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-linear-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -37,7 +37,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -63,7 +63,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -85,7 +85,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc index b5484c8e69b..4e30d35227b 100644 --- a/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/moving-average/moving-average-simple-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -38,7 +38,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -65,7 +65,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -88,7 +88,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc index 4e6a385dae0..e3d515ab084 100644 --- a/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/serial-differencing/serial-differencing-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -35,7 +35,7 @@ === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); @@ -49,7 +49,7 @@ commits.Value.Should().NotBe(null); === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -72,7 +72,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { diff --git a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc index 2b106baf854..0028772954d 100644 --- a/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc +++ b/docs/asciidoc/aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -34,7 +34,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Size(0) @@ -56,7 +56,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest() { @@ -73,7 +73,7 @@ Aggregations = new DateHistogramAggregation("projects_started_per_month") === Handling Responses -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- response.IsValid.Should().BeTrue(); var projectsPerMonth = response.Aggs.DateHistogram("projects_started_per_month"); diff --git a/docs/asciidoc/aggregations/writing-aggregations.asciidoc b/docs/asciidoc/aggregations/writing-aggregations.asciidoc index 0b7ac1d33b7..295e5b0a34f 100644 --- a/docs/asciidoc/aggregations/writing-aggregations.asciidoc +++ b/docs/asciidoc/aggregations/writing-aggregations.asciidoc @@ -22,7 +22,7 @@ want to use each. This is the json output for each example -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -53,7 +53,7 @@ This is the json output for each example The fluent lambda syntax is the most terse way to write aggregations. It benefits from types that are carried over to sub aggregations -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Aggregations(aggs => aggs @@ -72,7 +72,7 @@ The object initializer syntax (OIS) is a one-to-one mapping with how aggregation have to be represented in the Elasticsearch API. While it has the benefit of being a one-to-one mapping, being dictionary based in C means it can grow exponentially in complexity rather quickly. -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -93,7 +93,7 @@ It also allows you to combine multiple aggregations using bitwise AND (`&&`) ope Compare the following example with the previous vanilla OIS syntax -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SearchRequest { @@ -112,7 +112,7 @@ An advanced scenario may involve an existing collection of aggregation functions on the request. Using LINQ's `.Aggregate()` method, each function can be applied to the aggregation descriptor (`childAggs` below) in turn, returning the descriptor after each function application. -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- var aggregations = new List, IAggregationContainer>> //<1> { diff --git a/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc new file mode 100644 index 00000000000..6a645009b46 --- /dev/null +++ b/docs/asciidoc/analysis/analyzers/analyzer-usage.asciidoc @@ -0,0 +1,74 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "analysis": { + "analyzer": { + "myCustom": { + "type": "custom", + "tokenizer": "ng", + "filter": [ + "myAscii", + "kstem" + ], + "char_filter": [ + "stripMe", + "patterned" + ] + }, + "myKeyword": { + "type": "keyword" + }, + "myPattern": { + "type": "pattern", + "pattern": "\\w" + }, + "mySimple": { + "type": "simple" + }, + "myLanguage": { + "type": "dutch" + }, + "mySnow": { + "type": "snowball", + "language": "Dutch" + }, + "myStandard": { + "type": "standard", + "max_token_length": 2 + }, + "myStop": { + "type": "stop", + "stopwords_path": "analysis/stopwords.txt" + }, + "myWhiteSpace": { + "type": "whitespace" + }, + "myWhiteSpace2": { + "type": "whitespace" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + diff --git a/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc new file mode 100644 index 00000000000..97e43235b05 --- /dev/null +++ b/docs/asciidoc/analysis/char-filters/char-filter-usage.asciidoc @@ -0,0 +1,45 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "analysis": { + "char_filter": { + "stripMe": { + "type": "html_strip" + }, + "patterned": { + "pattern": "x", + "replacement": "y", + "type": "pattern_replace" + }, + "mapped": { + "mappings": [ + "a=>b" + ], + "type": "mapping" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + diff --git a/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc new file mode 100644 index 00000000000..7633c83941a --- /dev/null +++ b/docs/asciidoc/analysis/token-filters/token-filter-usage.asciidoc @@ -0,0 +1,237 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "analysis": { + "filter": { + "myAscii": { + "type": "asciifolding", + "preserveOriginal": true + }, + "myCommonGrams": { + "type": "common_grams", + "common_words": [ + "x", + "y", + "z" + ], + "ignore_case": true, + "query_mode": true + }, + "mydp": { + "type": "delimited_payload_filter", + "delimiter": "-", + "encoding": "identity" + }, + "dcc": { + "type": "dictionary_decompounder", + "word_list": [ + "x", + "y", + "z" + ], + "min_word_size": 2, + "min_subword_size": 2, + "max_subword_size": 2, + "only_longest_match": true + }, + "etf": { + "type": "edge_ngram", + "min_gram": 1, + "max_gram": 2 + }, + "elision": { + "type": "elision", + "articles": [ + "a", + "b", + "c" + ] + }, + "hunspell": { + "type": "hunspell", + "ignore_case": true, + "locale": "en_US", + "dictionary": "path_to_dict", + "dedup": true, + "longest_only": true + }, + "hypdecomp": { + "type": "hyphenation_decompounder", + "word_list": [ + "x", + "y", + "z" + ], + "min_word_size": 2, + "min_subword_size": 2, + "max_subword_size": 2, + "only_longest_match": true, + "hyphenation_patterns_path": "analysis/fop.xml" + }, + "keeptypes": { + "type": "keep_types", + "types": [ + "", + "" + ] + }, + "keepwords": { + "type": "keep", + "keep_words": [ + "a", + "b", + "c" + ], + "keep_words_case": true + }, + "marker": { + "type": "keyword_marker", + "keywords": [ + "a", + "b" + ], + "ignore_case": true + }, + "kstem": { + "type": "kstem" + }, + "length": { + "type": "length", + "min": 10, + "max": 200 + }, + "limit": { + "type": "limit", + "max_token_count": 12, + "consume_all_tokens": true + }, + "lc": { + "type": "lowercase" + }, + "ngram": { + "type": "ngram", + "min_gram": 3, + "max_gram": 30 + }, + "pc": { + "type": "pattern_capture", + "patterns": [ + "\\d", + "\\w" + ], + "preserve_original": true + }, + "pr": { + "type": "pattern_replace", + "pattern": "(\\d|\\w)", + "replacement": "replacement" + }, + "porter": { + "type": "porter_stem" + }, + "rev": { + "type": "reverse" + }, + "shing": { + "type": "shingle", + "min_shingle_size": 8, + "max_shingle_size": 12, + "output_unigrams": true, + "output_unigrams_if_no_shingles": true, + "token_separator": "|", + "filler_token": "x" + }, + "snow": { + "type": "snowball", + "language": "Dutch" + }, + "standard": { + "type": "standard" + }, + "stem": { + "type": "stemmer", + "language": "arabic" + }, + "stemo": { + "type": "stemmer_override", + "rules_path": "analysis/custom_stems.txt" + }, + "stop": { + "type": "stop", + "stopwords": [ + "x", + "y", + "z" + ], + "ignore_case": true, + "remove_trailing": true + }, + "syn": { + "type": "synonym", + "synonyms_path": "analysis/stopwords.txt", + "format": "wordnet", + "synonyms": [ + "x=>y", + "z=>s" + ], + "ignore_case": true, + "expand": true, + "tokenizer": "whitespace" + }, + "trimmer": { + "type": "trim" + }, + "truncer": { + "type": "truncate", + "length": 100 + }, + "uq": { + "type": "unique", + "only_on_same_position": true + }, + "upper": { + "type": "uppercase" + }, + "wd": { + "type": "word_delimiter", + "generate_word_parts": true, + "generate_number_parts": true, + "catenate_words": true, + "catenate_numbers": true, + "catenate_all": true, + "split_on_case_change": true, + "preserve_original": true, + "split_on_numerics": true, + "stem_english_possessive": true, + "protected_words": [ + "x", + "y", + "z" + ] + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + diff --git a/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc new file mode 100644 index 00000000000..abbbdb10612 --- /dev/null +++ b/docs/asciidoc/analysis/tokenizers/tokenizer-usage.asciidoc @@ -0,0 +1,73 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "analysis": { + "tokenizer": { + "endgen": { + "min_gram": 1, + "max_gram": 2, + "token_chars": [ + "digit", + "letter" + ], + "type": "edge_ngram" + }, + "ng": { + "min_gram": 1, + "max_gram": 2, + "token_chars": [ + "digit", + "letter" + ], + "type": "ngram" + }, + "path": { + "delimiter": "|", + "replacement": "-", + "buffer_size": 2048, + "reverse": true, + "skip": 1, + "type": "path_hierarchy" + }, + "pattern": { + "pattern": "\\W+", + "flags": "CASE_INSENSITIVE", + "group": 1, + "type": "pattern" + }, + "standard": { + "type": "standard" + }, + "uax": { + "max_token_length": 12, + "type": "uax_url_email" + }, + "whitespace": { + "type": "whitespace" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +FluentExample +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +InitializerExample +---- + diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc index 8f258511877..56b54416ca1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/connection-pooling.asciidoc @@ -23,7 +23,7 @@ The simplest of all connection pools, this takes a single `Uri` and uses that to It doesn't opt in to sniffing and pinging behavior, and will never mark nodes dead or alive. The one `Uri` it holds is always ready to go. -[source,csharp,method-name="singlenode"] +[source,csharp,method="singlenode"] ---- var uri = new Uri("http://localhost:9201"); var pool = new SingleNodeConnectionPool(uri); @@ -34,14 +34,14 @@ node.Uri.Port.Should().Be(9201); This type of pool is hardwired to opt out of sniffing -[source,csharp,method-name="singlenode"] +[source,csharp,method="singlenode"] ---- pool.SupportsReseeding.Should().BeFalse(); ---- and pinging -[source,csharp,method-name="singlenode"] +[source,csharp,method="singlenode"] ---- pool.SupportsPinging.Should().BeFalse(); ---- @@ -49,7 +49,7 @@ pool.SupportsPinging.Should().BeFalse(); When you use the low ceremony `ElasticClient` constructor that takes a single `Uri`, We default to using `SingleNodeConnectionPool` -[source,csharp,method-name="singlenode"] +[source,csharp,method="singlenode"] ---- var client = new ElasticClient(uri); @@ -58,7 +58,7 @@ client.ConnectionSettings.ConnectionPool.Should().BeOfType new Uri("http://localhost:" + p)); ---- a connection pool can be seeded using an enumerable of `Uri`s -[source,csharp,method-name="static"] +[source,csharp,method="static"] ---- var pool = new StaticConnectionPool(uris); ---- Or using an enumerable of `Node`s -[source,csharp,method-name="static"] +[source,csharp,method="static"] ---- var nodes = uris.Select(u => new Node(u)); @@ -102,14 +102,14 @@ pool = new StaticConnectionPool(nodes); This type of pool is hardwired to opt out of sniffing -[source,csharp,method-name="static"] +[source,csharp,method="static"] ---- pool.SupportsReseeding.Should().BeFalse(); ---- but supports pinging when enabled -[source,csharp,method-name="static"] +[source,csharp,method="static"] ---- pool.SupportsPinging.Should().BeTrue(); ---- @@ -117,7 +117,7 @@ pool.SupportsPinging.Should().BeTrue(); To create a client using this static connection pool, pass the connection pool to the `ConnectionSettings` you pass to `ElasticClient` -[source,csharp,method-name="static"] +[source,csharp,method="static"] ---- var client = new ElasticClient(new ConnectionSettings(pool)); @@ -129,14 +129,14 @@ client.ConnectionSettings.ConnectionPool.Should().BeOfType A subclass of `StaticConnectionPool` that allows itself to be reseeded at run time. It comes with a very minor overhead of a `ReaderWriterLockSlim` to ensure thread safety. -[source,csharp,method-name="sniffing"] +[source,csharp,method="sniffing"] ---- var uris = Enumerable.Range(9200, 5).Select(p => new Uri("http://localhost:" + p)); ---- a connection pool can be seeded using an enumerable of `Uri` -[source,csharp,method-name="sniffing"] +[source,csharp,method="sniffing"] ---- var pool = new SniffingConnectionPool(uris); ---- @@ -146,7 +146,7 @@ A major benefit here is you can include known node roles when seeding and NEST can use this information to favour sniffing on master eligible nodes first and take master only nodes out of rotation for issuing client calls on. -[source,csharp,method-name="sniffing"] +[source,csharp,method="sniffing"] ---- var nodes = uris.Select(u=>new Node(u)); @@ -155,14 +155,14 @@ pool = new SniffingConnectionPool(nodes); This type of pool is hardwired to opt in to sniffing -[source,csharp,method-name="sniffing"] +[source,csharp,method="sniffing"] ---- pool.SupportsReseeding.Should().BeTrue(); ---- and pinging -[source,csharp,method-name="sniffing"] +[source,csharp,method="sniffing"] ---- pool.SupportsPinging.Should().BeTrue(); ---- @@ -170,7 +170,7 @@ pool.SupportsPinging.Should().BeTrue(); To create a client using the sniffing connection pool pass the connection pool to the `ConnectionSettings` you pass to `ElasticClient` -[source,csharp,method-name="sniffing"] +[source,csharp,method="sniffing"] ---- var client = new ElasticClient(new ConnectionSettings(pool)); diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc index 3cb2ab0a16a..050485d2b06 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/date-time-providers.asciidoc @@ -12,14 +12,14 @@ Not typically something you'll have to pass to the client but all calls to `Syst in the client have been abstracted by `IDateTimeProvider`. This allows us to unit test timeouts and cluster failover without being bound to wall clock time as calculated by using `System.DateTime.UtcNow` directly. -[source,csharp,method-name="defaultnowbehaviour"] +[source,csharp,method="defaultnowbehaviour"] ---- var dateTimeProvider = DateTimeProvider.Default; ---- dates are always returned in UTC -[source,csharp,method-name="defaultnowbehaviour"] +[source,csharp,method="defaultnowbehaviour"] ---- dateTimeProvider.Now().Should().BeCloseTo(DateTime.UtcNow); ---- @@ -28,7 +28,7 @@ Another responsibility of this interface is to calculate the time a node has to based on the number of attempts to revive it. For very advanced use cases, this might be something of interest to provide a custom implementation for. -[source,csharp,method-name="deadtimeoutcalculation"] +[source,csharp,method="deadtimeoutcalculation"] ---- var dateTimeProvider = DateTimeProvider.Default; ---- @@ -36,7 +36,7 @@ var dateTimeProvider = DateTimeProvider.Default; The default timeout calculation is: `min(timeout * 2 ^ (attempts * 0.5 -1), maxTimeout)`, where the default values for `timeout` and `maxTimeout` are -[source,csharp,method-name="deadtimeoutcalculation"] +[source,csharp,method="deadtimeoutcalculation"] ---- var timeout = TimeSpan.FromMinutes(1); @@ -52,7 +52,7 @@ image::{imagesdir}/timeoutplot.png[dead timeout] The goal here is that whenever a node is resurrected and is found to still be offline, we send it _back to the doghouse_ for an ever increasingly long period, until we hit a bounded maximum. -[source,csharp,method-name="deadtimeoutcalculation"] +[source,csharp,method="deadtimeoutcalculation"] ---- var timeouts = Enumerable.Range(0, 30) .Select(attempt => dateTimeProvider.DeadTime(attempt, timeout, maxTimeout)) diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc index 34453fb9df7..25a7f6f1111 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/keeping-track-of-nodes.asciidoc @@ -12,7 +12,7 @@ A `Node` can be instantiated by passing it a `Uri` -[source,csharp,method-name="creating"] +[source,csharp,method="creating"] ---- var node = new Node(new Uri("http://localhost:9200")); @@ -22,7 +22,7 @@ node.Uri.Port.Should().Be(9200); By default master eligible and holds data is presumed to be true -[source,csharp,method-name="creating"] +[source,csharp,method="creating"] ---- node.MasterEligible.Should().BeTrue(); @@ -31,7 +31,7 @@ node.HoldsData.Should().BeTrue(); Is resurrected is true on first usage, hints to the transport that a ping might be useful -[source,csharp,method-name="creating"] +[source,csharp,method="creating"] ---- node.IsResurrected.Should().BeTrue(); ---- @@ -44,7 +44,7 @@ a known cluster topology. passing a node with a path should be preserved. Sometimes an elasticsearch node lives behind a proxy -[source,csharp,method-name="buildingpaths"] +[source,csharp,method="buildingpaths"] ---- var node = new Node(new Uri("http://test.example/elasticsearch")); @@ -55,7 +55,7 @@ node.Uri.AbsolutePath.Should().Be("/elasticsearch/"); We force paths to end with a forward slash so that they can later be safely combined -[source,csharp,method-name="buildingpaths"] +[source,csharp,method="buildingpaths"] ---- var combinedPath = new Uri(node.Uri, "index/type/_search"); @@ -64,7 +64,7 @@ combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); which is exactly what the `CreatePath` method does on `Node` -[source,csharp,method-name="buildingpaths"] +[source,csharp,method="buildingpaths"] ---- combinedPath = node.CreatePath("index/type/_search"); @@ -73,7 +73,7 @@ combinedPath.AbsolutePath.Should().Be("/elasticsearch/index/type/_search"); === Marking Nodes -[source,csharp,method-name="marknodes"] +[source,csharp,method="marknodes"] ---- var node = new Node(new Uri("http://localhost:9200")); @@ -85,7 +85,7 @@ node.IsAlive.Should().BeTrue(); every time a node is marked dead the number of attempts should increase and the passed datetime should be exposed. -[source,csharp,method-name="marknodes"] +[source,csharp,method="marknodes"] ---- var deadUntil = DateTime.Now.AddMinutes(1); @@ -100,7 +100,7 @@ node.DeadUntil.Should().Be(deadUntil); however when marking a node alive, the `DeadUntil` property should be reset and `FailedAttempts` reset to 0 -[source,csharp,method-name="marknodes"] +[source,csharp,method="marknodes"] ---- node.MarkAlive(); @@ -115,7 +115,7 @@ node.IsAlive.Should().BeTrue(); Nodes are considered equal if they have the same endpoint, no matter what other metadata is associated -[source,csharp,method-name="equality"] +[source,csharp,method="equality"] ---- var node = new Node(new Uri("http://localhost:9200")) { MasterEligible = false }; diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc index 093ef9b0613..25019419619 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc @@ -11,14 +11,14 @@ Every request is executed in the context of a `RequestPipeline` when using the default `ITransport` implementation. -[source,csharp,method-name="requestpipeline"] +[source,csharp,method="requestpipeline"] ---- var settings = TestClient.CreateSettings(); ---- When calling Request/RequestAsync on Transport the whole coordination of the request is deferred to a new instance in a `using` block. -[source,csharp,method-name="requestpipeline"] +[source,csharp,method="requestpipeline"] ---- var pipeline = new RequestPipeline(settings, DateTimeProvider.Default, new MemoryStreamFactory(), new SearchRequestParameters()); @@ -28,7 +28,7 @@ pipeline.GetType().Should().Implement(); However the transport does not instantiate `RequestPipeline` directly; it uses a pluggable `IRequestPipelineFactory` to create it -[source,csharp,method-name="requestpipeline"] +[source,csharp,method="requestpipeline"] ---- var requestPipelineFactory = new RequestPipelineFactory(); @@ -45,12 +45,12 @@ requestPipeline.GetType().Should().Implement(); you can pass your own `IRequestPipeline` implementation to the transport when instantiating a client allowing you to have requests executed on your own custom request pipeline -[source,csharp,method-name="requestpipeline"] +[source,csharp,method="requestpipeline"] ---- var transport = new Transport(settings, requestPipelineFactory, DateTimeProvider.Default, new MemoryStreamFactory()); ---- -[source,csharp,method-name="createpipeline"] +[source,csharp,method="createpipeline"] ---- var pool = setupPool(new[] { TestClient.CreateNode(), TestClient.CreateNode(9201) }); @@ -59,7 +59,7 @@ var settings = new ConnectionSettings(pool, TestClient.CreateConnection()); settings = settingsSelector?.Invoke(settings) ?? settings; ---- -[source,csharp,method-name="firstusagecheck"] +[source,csharp,method="firstusagecheck"] ---- var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); @@ -70,7 +70,7 @@ var sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris)); Here we have setup three pipelines using three different connection pools, lets see how they behave -[source,csharp,method-name="firstusagecheck"] +[source,csharp,method="firstusagecheck"] ---- singleNodePipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); @@ -82,14 +82,14 @@ sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeTrue(); Only the cluster that supports reseeding will opt in to FirstPoolUsageNeedsSniffing() You can however disable this on ConnectionSettings -[source,csharp,method-name="firstusagecheck"] +[source,csharp,method="firstusagecheck"] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnStartup(false)); sniffingPipeline.FirstPoolUsageNeedsSniffing.Should().BeFalse(); ---- -[source,csharp,method-name="sniffsonconnectionfailure"] +[source,csharp,method="sniffsonconnectionfailure"] ---- var singleNodePipeline = CreatePipeline(uris => new SingleNodeConnectionPool(uris.First())); @@ -107,14 +107,14 @@ sniffingPipeline.SniffsOnConnectionFailure.Should().BeTrue(); Only the cluster that supports reseeding will opt in to SniffsOnConnectionFailure() You can however disable this on ConnectionSettings -[source,csharp,method-name="sniffsonconnectionfailure"] +[source,csharp,method="sniffsonconnectionfailure"] ---- sniffingPipeline = CreatePipeline(uris => new SniffingConnectionPool(uris), s => s.SniffOnConnectionFault(false)); sniffingPipeline.SniffsOnConnectionFailure.Should().BeFalse(); ---- -[source,csharp,method-name="sniffsonstalecluster"] +[source,csharp,method="sniffsonstalecluster"] ---- var dateTime = new TestableDateTimeProvider(); @@ -139,14 +139,14 @@ sniffingPipeline.StaleClusterState.Should().BeFalse(); go one hour into the future -[source,csharp,method-name="sniffsonstalecluster"] +[source,csharp,method="sniffsonstalecluster"] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- connection pools that do not support reseeding never go stale -[source,csharp,method-name="sniffsonstalecluster"] +[source,csharp,method="sniffsonstalecluster"] ---- singleNodePipeline.StaleClusterState.Should().BeFalse(); @@ -155,7 +155,7 @@ staticPipeline.StaleClusterState.Should().BeFalse(); the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source,csharp,method-name="sniffsonstalecluster"] +[source,csharp,method="sniffsonstalecluster"] ---- sniffingPipeline.StaleClusterState.Should().BeTrue(); ---- @@ -163,7 +163,7 @@ sniffingPipeline.StaleClusterState.Should().BeTrue(); A request pipeline also checks whether the overall time across multiple retries exceeds the request timeout. See the <> for more details, here we assert that our request pipeline exposes this propertly -[source,csharp,method-name="istakingtoolong"] +[source,csharp,method="istakingtoolong"] ---- var dateTime = new TestableDateTimeProvider(); @@ -182,14 +182,14 @@ sniffingPipeline.IsTakingTooLong.Should().BeFalse(); go one hour into the future -[source,csharp,method-name="istakingtoolong"] +[source,csharp,method="istakingtoolong"] ---- dateTime.ChangeTime(d => d.Add(TimeSpan.FromHours(2))); ---- connection pools that do not support reseeding never go stale -[source,csharp,method-name="istakingtoolong"] +[source,csharp,method="istakingtoolong"] ---- singleNodePipeline.IsTakingTooLong.Should().BeTrue(); @@ -198,14 +198,14 @@ staticPipeline.IsTakingTooLong.Should().BeTrue(); the sniffing connection pool supports reseeding so the pipeline will signal the state is out of date -[source,csharp,method-name="istakingtoolong"] +[source,csharp,method="istakingtoolong"] ---- sniffingPipeline.IsTakingTooLong.Should().BeTrue(); ---- request pipeline exposes the DateTime it started, here we assert it started 2 hours in the past -[source,csharp,method-name="istakingtoolong"] +[source,csharp,method="istakingtoolong"] ---- (dateTime.Now() - singleNodePipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); @@ -214,7 +214,7 @@ request pipeline exposes the DateTime it started, here we assert it started 2 ho (dateTime.Now() - sniffingPipeline.StartedOn).Should().BePositive().And.BeCloseTo(TimeSpan.FromHours(2)); ---- -[source,csharp,method-name="setssniffpathusingtotimespan"] +[source,csharp,method="setssniffpathusingtotimespan"] ---- var dateTime = new TestableDateTimeProvider(); diff --git a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc index f199c3f3dba..1e447a2735f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/building-blocks/transports.asciidoc @@ -19,14 +19,14 @@ This is the minimum `ITransport` needs to report back for the client to function e.g in the low level client, transport is instantiated like this: -[source,csharp,method-name="interfaceexplained"] +[source,csharp,method="interfaceexplained"] ---- var lowLevelTransport = new Transport(new ConnectionConfiguration()); ---- and in the high level client, like this: -[source,csharp,method-name="interfaceexplained"] +[source,csharp,method="interfaceexplained"] ---- var highlevelTransport = new Transport(new ConnectionSettings()); @@ -38,7 +38,7 @@ The only two methods on `ITransport` are `Request()` and `RequestAsync()`, the d many of the building blocks in the client, if these do not work for you can swap them out for your own custom `ITransport` implementation. If you feel this need, {github}/issues[please let us know] as we'd love to learn why you've go down this route! -[source,csharp,method-name="interfaceexplained"] +[source,csharp,method="interfaceexplained"] ---- var response = inMemoryTransport.Request>(HttpMethod.GET, "/_search", new { query = new { match_all = new { } } }); diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc index 6be7fc2d2d6..5e5d4f12c19 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc @@ -11,7 +11,7 @@ out the client as an UnexpectedElasticsearchClientException, regardless whether An IConnection is in charge of knowning what exceptions it can recover from or not. The default IConnection that is based on WebRequest can and will recover from WebExceptions but others will be grounds for immediately exiting the pipeline. -[source,csharp,method-name="unexpectedexceptionsbubbleout"] +[source,csharp,method="unexpectedexceptionsbubbleout"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -47,7 +47,7 @@ in the pipeline the unexpected exception is not lost, here a call to 9200 fails It then falls over to 9201 which throws an hard exception from within IConnection. We assert that we can still see the audit trail for the whole coordinated request. -[source,csharp,method-name="willfailoverknowconnectionexceptionbutnotunexpected"] +[source,csharp,method="willfailoverknowconnectionexceptionbutnotunexpected"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -85,7 +85,7 @@ An unexpected hard exception on ping and sniff is something we *do* try to revov Here pinging nodes on first use is enabled and 9200 throws on ping, we still fallover to 9201's ping succeeds. However the client call on 9201 throws a hard exception we can not recover from -[source,csharp,method-name="pingunexceptedexceptiondoesfailover"] +[source,csharp,method="pingunexceptedexceptiondoesfailover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -97,7 +97,7 @@ var audit = new Auditor(() => Framework.Cluster ); ---- -[source,csharp,method-name="pingunexceptedexceptiondoesfailover"] +[source,csharp,method="pingunexceptedexceptiondoesfailover"] ---- audit = await audit.TraceUnexpectedException( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc index 74e3415f828..1bcd782799f 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc @@ -14,7 +14,7 @@ both a client that throws and one that returns an invalid response with an `.Ori The following are recoverable exceptions -[source,csharp,method-name="somepipelinefailuresarerecoverable"] +[source,csharp,method="somepipelinefailuresarerecoverable"] ---- var recoverablExceptions = new[] { @@ -27,7 +27,7 @@ recoverablExceptions.Should().OnlyContain(e => e.Recoverable); and the unrecoverable exceptions -[source,csharp,method-name="somepipelinefailuresarerecoverable"] +[source,csharp,method="somepipelinefailuresarerecoverable"] ---- var unrecoverableExceptions = new[] { @@ -45,7 +45,7 @@ unrecoverableExceptions.Should().OnlyContain(e => !e.Recoverable); As an example, let's set up a 10 node cluster that will always succeed when pinged but will fail with a 401 response when making client calls -[source,csharp,method-name="badauthenticationisunrecoverable"] +[source,csharp,method="badauthenticationisunrecoverable"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -59,7 +59,7 @@ var audit = new Auditor(() => Framework.Cluster Here we make a client call and determine that the first audit event was a successful ping, followed by a bad response as a result of a bad authentication response -[source,csharp,method-name="badauthenticationisunrecoverable"] +[source,csharp,method="badauthenticationisunrecoverable"] ---- audit = await audit.TraceElasticsearchException( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc index be82942f0b5..4fcf267ce0a 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/failover/falling-over.asciidoc @@ -9,7 +9,7 @@ When using connection pooling and the pool has sufficient nodes a request will be retried if the call to a node throws an exception or returns a 502 or 503 -[source,csharp,method-name="exceptionfallsovertonextnode"] +[source,csharp,method="exceptionfallsovertonextnode"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -30,7 +30,7 @@ audit = await audit.TraceCall( Will be treated as an error that requires retrying -[source,csharp,method-name="http502fallsover"] +[source,csharp,method="http502fallsover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -52,7 +52,7 @@ audit = await audit.TraceCall( Will be treated as an error that requires retrying -[source,csharp,method-name="http503fallsover"] +[source,csharp,method="http503fallsover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -72,7 +72,7 @@ audit = await audit.TraceCall( If a call returns a valid (_for the request*_) http status code other then 502/503. the request won't be retried. -[source,csharp,method-name="httpteapotdoesnotfallover"] +[source,csharp,method="httpteapotdoesnotfallover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc index cf6eb2d24dd..91231ecbd43 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/max-retries/respects-max-retry.asciidoc @@ -10,7 +10,7 @@ By default retry as many times as we have nodes. However retries still respect t Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds -[source,csharp,method-name="defaultmaxisnumberofnodes"] +[source,csharp,method="defaultmaxisnumberofnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -38,7 +38,7 @@ audit = await audit.TraceCall( When you have a 100 node cluster you might want to ensure a fixed number of retries. Remember that the actual number of requests is initial attempt + set number of retries -[source,csharp,method-name="fixedmaximumnumberofretries"] +[source,csharp,method="fixedmaximumnumberofretries"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -63,7 +63,7 @@ In our previous test we simulated very fast failures, in the real world a call m Here we simulate a particular heavy search that takes 10 seconds to fail, our Request timeout is set to 20 seconds. In this case it does not make sense to retry our 10 second query on 10 nodes. We should try it twice and give up before a third call is attempted -[source,csharp,method-name="respectsoveralrequesttimeout"] +[source,csharp,method="respectsoveralrequesttimeout"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -87,7 +87,7 @@ Here we simulate calls taking 3 seconds, a request time out of 2 and an overall We should see 5 attempts to perform this query, testing that our request timeout cuts the query off short and that our max retry timeout of 10 wins over the configured request timeout -[source,csharp,method-name="respectsmaxretrytimeoutoverrequesttimeout"] +[source,csharp,method="respectsmaxretrytimeoutoverrequesttimeout"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -111,7 +111,7 @@ audit = await audit.TraceCall( If your retry policy expands beyond available nodes we won't retry the same node twice -[source,csharp,method-name="retriesarelimitedbynodesinpool"] +[source,csharp,method="retriesarelimitedbynodesinpool"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(2) @@ -134,7 +134,7 @@ This makes setting any retry setting on a single node connection pool a NOOP, th Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. -[source,csharp,method-name="doesnotretryonsinglenodeconnectionpool"] +[source,csharp,method="doesnotretryonsinglenodeconnectionpool"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc index e0aa2ca4657..a73a8cca401 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/first-usage.asciidoc @@ -14,7 +14,7 @@ This allows us to fail and fallover to a healthy node faster A cluster with 2 nodes where the second node fails on ping -[source,csharp,method-name="pingfailsfallsovertohealthynodewithoutping"] +[source,csharp,method="pingfailsfallsovertohealthynodewithoutping"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(2) @@ -32,7 +32,7 @@ It fails so we wrap over to node 9200 which we've already pinged Finally we assert that the connectionpool has one node that is marked as dead -[source,csharp,method-name="pingfailsfallsovertohealthynodewithoutping"] +[source,csharp,method="pingfailsfallsovertohealthynodewithoutping"] ---- await audit.TraceCalls( new ClientCall { @@ -53,7 +53,7 @@ new ClientCall { A cluster with 4 nodes where the second and third pings fail -[source,csharp,method-name="pingfailsfallsovermultipletimestohealthynode"] +[source,csharp,method="pingfailsfallsovermultipletimestohealthynode"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -73,7 +73,7 @@ we haven't used it before and it succeeds Finally we assert that the connectionpool has two nodes that are marked as dead -[source,csharp,method-name="pingfailsfallsovermultipletimestohealthynode"] +[source,csharp,method="pingfailsfallsovermultipletimestohealthynode"] ---- await audit.TraceCalls( new ClientCall { @@ -96,7 +96,7 @@ new ClientCall { A healthy cluster of 4 (min master nodes of 3 of course!) -[source,csharp,method-name="allnodesarepingedonlyonfirstuseprovidedtheyarehealthy"] +[source,csharp,method="allnodesarepingedonlyonfirstuseprovidedtheyarehealthy"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) diff --git a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc index 11226450cad..6ac650bcc66 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/pinging/revival.asciidoc @@ -11,7 +11,7 @@ When a node is marked dead it will only be put in the dog house for a certain amount of time. Once it comes out of the dog house, or revived, we schedule a ping before the actual call to make sure its up and running. If its still down we put it back in the dog house a little longer. For an explanation on these timeouts see: TODO LINK -[source,csharp,method-name="pingafterrevival"] +[source,csharp,method="pingafterrevival"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(3) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc index 49529e8620f..20477cdcaf1 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/disable-sniff-ping-per-request.asciidoc @@ -16,7 +16,7 @@ but we disable the sniffing on our first request so we only see the ping and the Let's set up the cluster and configure clients to **always** sniff on startup -[source,csharp,method-name="disablesniff"] +[source,csharp,method="disablesniff"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -34,7 +34,7 @@ does not disable sniffing on a per request basis And after that no sniff on startup will happen again -[source,csharp,method-name="disablesniff"] +[source,csharp,method="disablesniff"] ---- audit = await audit.TraceCalls( new ClientCall(r => r.DisableSniffing()) //<1> @@ -64,7 +64,7 @@ new ClientCall() Now, let's disable pinging on the request -[source,csharp,method-name="disableping"] +[source,csharp,method="disableping"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -87,7 +87,7 @@ audit = await audit.TraceCall( Finally, let's demonstrate disabling both sniff and ping on the request -[source,csharp,method-name="disablesniffandping"] +[source,csharp,method="disablesniffandping"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc index 3391d1a10ff..26346af6d69 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/request-timeouts-overrides.asciidoc @@ -14,7 +14,7 @@ we set up a 10 node cluster with a global time out of 20 seconds. Each call on a node takes 10 seconds. So we can only try this call on 2 nodes before the max request time out kills the client call. -[source,csharp,method-name="respectsrequesttimeoutoverride"] +[source,csharp,method="respectsrequesttimeoutoverride"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -28,7 +28,7 @@ var audit = new Auditor(() => Framework.Cluster On the second request we specify a request timeout override to 60 seconds We should now see more nodes being tried. -[source,csharp,method-name="respectsrequesttimeoutoverride"] +[source,csharp,method="respectsrequesttimeoutoverride"] ---- audit = await audit.TraceCalls( new ClientCall { @@ -58,7 +58,7 @@ we set up a 10 node cluster with a global time out of 20 seconds. Each call on a node takes 10 seconds. So we can only try this call on 2 nodes before the max request time out kills the client call. -[source,csharp,method-name="respectsconnecttimeoutoverride"] +[source,csharp,method="respectsconnecttimeoutoverride"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -75,7 +75,7 @@ calls always take 20, so we should see a single ping failure On the second request we set a request ping timeout override of 2seconds We should now see more nodes being tried before the request timeout is hit. -[source,csharp,method-name="respectsconnecttimeoutoverride"] +[source,csharp,method="respectsconnecttimeoutoverride"] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc index 0c46f4adeed..49cd23fb61c 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-allowed-status-code.asciidoc @@ -8,7 +8,7 @@ == Allowed status codes -[source,csharp,method-name="canoverridebadresponse"] +[source,csharp,method="canoverridebadresponse"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc index c5b65f841d7..5f457321333 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-force-node.asciidoc @@ -11,7 +11,7 @@ Sometimes you might want to fire a single request to a specific node. You can do so using the `ForceNode` request configuration. This will ignore the pool and not retry. -[source,csharp,method-name="onlycallsforcednode"] +[source,csharp,method="onlycallsforcednode"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc index 6b646e3ed8d..ef91ad1dc8b 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/request-overrides/respects-max-retry-overrides.asciidoc @@ -12,7 +12,7 @@ By default retry as many times as we have nodes. However retries still respect t Meaning if you have a 100 node cluster and a request timeout of 20 seconds we will retry as many times as we can but give up after 20 seconds -[source,csharp,method-name="defaultmaxisnumberofnodes"] +[source,csharp,method="defaultmaxisnumberofnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -34,7 +34,7 @@ audit = await audit.TraceCall( When you have a 100 node cluster you might want to ensure a fixed number of retries. Remember that the actual number of requests is initial attempt + set number of retries -[source,csharp,method-name="fixedmaximumnumberofretries"] +[source,csharp,method="fixedmaximumnumberofretries"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -58,7 +58,7 @@ This makes setting any retry setting on a single node connection pool a NOOP, th Connection pooling and connection failover is about trying to fail sanely whilst still utilizing available resources and not giving up on the fail fast principle. It's *NOT* a mechanism for forcing requests to succeed. -[source,csharp,method-name="doesnotretryonsinglenodeconnectionpool"] +[source,csharp,method="doesnotretryonsinglenodeconnectionpool"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc index 0c2404cf360..71e6b8a26b6 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/round-robin.asciidoc @@ -14,7 +14,7 @@ Each connection pool round robins over the `live` nodes, to evenly distribute th over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. -[source,csharp,method-name="eachviewstartsatnexpositionandwrapsover"] +[source,csharp,method="eachviewstartsatnexpositionandwrapsover"] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); var staticPool = new StaticConnectionPool(uris, randomize: false); @@ -32,7 +32,7 @@ Thread B calls GetNext() second without a local cursor and therefor starts at 1. After this each thread should walk the nodes in successive order using their local cursor e.g Thread A might get 0,1,2,3,5 and thread B will get 1,2,3,4,0. -[source,csharp,method-name="assertcreateview"] +[source,csharp,method="assertcreateview"] ---- var startingPositions = Enumerable.Range(0, NumberOfNodes) .Select(i => pool.CreateView().First()) @@ -54,7 +54,7 @@ Lets up the ante: We'll validate that each thread sees all the nodes and they they wrap over e.g after node 9209 comes 9200 again -[source,csharp,method-name="assertcreateview"] +[source,csharp,method="assertcreateview"] ---- var threadedStartPositions = new ConcurrentBag(); @@ -70,7 +70,7 @@ t.Join(); Each thread reported the first node it started off lets make sure we see each node twice as the first node because we started `NumberOfNodes * 2` threads -[source,csharp,method-name="assertcreateview"] +[source,csharp,method="assertcreateview"] ---- var grouped = threadedStartPositions.GroupBy(p => p).ToList(); diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc index 92880fe37f5..f1d91811244 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/skip-dead-nodes.asciidoc @@ -14,7 +14,7 @@ GetNext is implemented in a lock free thread safe fashion, meaning each callee g over the internal list of nodes. This to guarantee each request that needs to fall over tries all the nodes without suffering from noisy neighboors advancing a global cursor. -[source,csharp,method-name="eachviewseesnextbutskipsthedeadnode"] +[source,csharp,method="eachviewseesnextbutskipsthedeadnode"] ---- var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); @@ -31,7 +31,7 @@ node = pool.CreateView().First(); node.Uri.Port.Should().Be(9202); ---- -[source,csharp,method-name="eachviewskipsaheadwithone"] +[source,csharp,method="eachviewskipsaheadwithone"] ---- var seeds = Enumerable.Range(9200, NumberOfNodes).Select(p => new Node(new Uri("http://localhost:" + p))).ToList(); var pool = new StaticConnectionPool(seeds, randomize: false); @@ -45,7 +45,7 @@ node.Uri.Port.Should().Be(9202); After we marked the first node alive again, we expect it to be hit again -[source,csharp,method-name="eachviewseesnextbutskipsthedeadnode"] +[source,csharp,method="eachviewseesnextbutskipsthedeadnode"] ---- seeds.First().MarkAlive(); @@ -62,7 +62,7 @@ node = pool.CreateView().First(); node.Uri.Port.Should().Be(9200); ---- -[source,csharp,method-name="viewseesresurrectednodes"] +[source,csharp,method="viewseesresurrectednodes"] ---- var dateTimeProvider = new TestableDateTimeProvider(); @@ -83,7 +83,7 @@ node.Uri.Port.Should().Be(9202); If we roll the clock forward two days, the node that was marked dead until tomorrow (or yesterday!) should be resurrected -[source,csharp,method-name="viewseesresurrectednodes"] +[source,csharp,method="viewseesresurrectednodes"] ---- dateTimeProvider.ChangeTime(d => d.AddDays(2)); @@ -104,7 +104,7 @@ n.IsResurrected.Should().BeTrue(); A cluster with 2 nodes where the second node fails on ping -[source,csharp,method-name="fallsoverdeadnodes"] +[source,csharp,method="fallsoverdeadnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -125,7 +125,7 @@ Finally we assert that the connectionpool has one node that is marked as dead The next call goes to 9203 which fails so we should wrap over -[source,csharp,method-name="fallsoverdeadnodes"] +[source,csharp,method="fallsoverdeadnodes"] ---- await audit.TraceCalls( new ClientCall { @@ -163,7 +163,7 @@ new ClientCall { A cluster with 2 nodes where the second node fails on ping -[source,csharp,method-name="picksadifferentnodeeachtimeanodeisdown"] +[source,csharp,method="picksadifferentnodeeachtimeanodeisdown"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(4) @@ -179,7 +179,7 @@ After all our registered nodes are marked dead we want to sample a single dead n each time to quickly see if the cluster is back up. We do not want to retry all 4 nodes -[source,csharp,method-name="picksadifferentnodeeachtimeanodeisdown"] +[source,csharp,method="picksadifferentnodeeachtimeanodeisdown"] ---- await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc index 55bc511487e..9cf93cb3c21 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/round-robin/volatile-updates.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,csharp,method-name="staticpoolwithstandsconcurrentreadandwrites"] +[source,csharp,method="staticpoolwithstandsconcurrentreadandwrites"] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); @@ -15,7 +15,7 @@ Action callStatic = () => this.AssertCreateView(staticPool); callStatic.ShouldNotThrow(); ---- -[source,csharp,method-name="sniffingpoolwithstandsconcurrentreadandwrites"] +[source,csharp,method="sniffingpoolwithstandsconcurrentreadandwrites"] ---- var uris = Enumerable.Range(9200, NumberOfNodes).Select(p => new Uri("http://localhost:" + p)); var sniffingPool = new SniffingConnectionPool(uris, randomize: false); @@ -23,7 +23,7 @@ Action callSniffing = () => this.AssertCreateView(sniffingPool); callSniffing.ShouldNotThrow(); ---- -[source,csharp,method-name="assertcreateview"] +[source,csharp,method="assertcreateview"] ---- var threads = Enumerable.Range(0, 50) .Select(i => CreateReadAndUpdateThread(pool)) diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc index e1c14adbaa2..e1c86ad213e 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-connection-failure.asciidoc @@ -25,7 +25,7 @@ still fails once After this second failure on 9201 another sniff will be returned a cluster that no longer fails but looks completely different (9210-9212) we should be able to handle this -[source,csharp,method-name="doesasniffafterconnectionfailure"] +[source,csharp,method="doesasniffafterconnectionfailure"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(5) @@ -54,7 +54,7 @@ Our pool should now have three nodes We assert we do a sniff on the first master node in our updated cluster -[source,csharp,method-name="doesasniffafterconnectionfailure"] +[source,csharp,method="doesasniffafterconnectionfailure"] ---- audit = await audit.TraceCalls( new ClientCall { @@ -90,7 +90,7 @@ new ClientCall { Here we set up our cluster exactly the same as the previous setup Only we enable pinging (default is true) and make the ping fail -[source,csharp,method-name="doesasniffafterconnectionfailureonping"] +[source,csharp,method="doesasniffafterconnectionfailureonping"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(5) @@ -120,7 +120,7 @@ We assert we do a sniff on the first master node in our updated cluster 9210 was already pinged after the sniff returned the new nodes -[source,csharp,method-name="doesasniffafterconnectionfailureonping"] +[source,csharp,method="doesasniffafterconnectionfailureonping"] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc index 854dcf90a22..b2f50e7f0a3 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-stale-cluster-state.asciidoc @@ -13,7 +13,7 @@ In addition to sniffing on startup and sniffing on failures, sniffing periodical clusters are often scaled horizontally during peak hours. An application might have a healthy view of a subset of the nodes but without sniffing periodically it will never find the nodes that have been added to help out with load -[source,csharp,method-name="asniffonstartuphappens"] +[source,csharp,method="asniffonstartuphappens"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -41,7 +41,7 @@ var audit = new Auditor(() => Framework.Cluster healty cluster all nodes return healthy responses -[source,csharp,method-name="asniffonstartuphappens"] +[source,csharp,method="asniffonstartuphappens"] ---- audit = await audit.TraceCalls( new ClientCall { { HealthyResponse, 9200 } }, @@ -64,14 +64,14 @@ audit = await audit.TraceCalls( Now let's forward the clock 31 minutes, our sniff lifespan should now go state and the first call should do a sniff which discovered we scaled up to a 100 nodes! -[source,csharp,method-name="asniffonstartuphappens"] +[source,csharp,method="asniffonstartuphappens"] ---- audit.ChangeTime(d => d.AddMinutes(31)); ---- a sniff is done first and it prefers the first node master node -[source,csharp,method-name="asniffonstartuphappens"] +[source,csharp,method="asniffonstartuphappens"] ---- audit = await audit.TraceCalls( new ClientCall { @@ -87,7 +87,7 @@ audit.ChangeTime(d => d.AddMinutes(31)); a sniff is done first and it prefers the first node master node -[source,csharp,method-name="asniffonstartuphappens"] +[source,csharp,method="asniffonstartuphappens"] ---- audit = await audit.TraceCalls( new ClientCall { diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc index bd554d52b93..f976c44b1c8 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/on-startup.asciidoc @@ -10,7 +10,7 @@ Connection pools that return true for `SupportsReseeding` by default sniff on startup. -[source,csharp,method-name="asniffonstartuphappensonce"] +[source,csharp,method="asniffonstartuphappensonce"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -38,7 +38,7 @@ await audit.TraceCalls( ); ---- -[source,csharp,method-name="sniffonstartuptakesnewclusterstate"] +[source,csharp,method="sniffonstartuptakesnewclusterstate"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -58,7 +58,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method-name="snifftriesallnodes"] +[source,csharp,method="snifftriesallnodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -85,7 +85,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method-name="sniffprefersmasternodes"] +[source,csharp,method="sniffprefersmasternodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(new[] { @@ -106,7 +106,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method-name="sniffprefersmasternodesbutstillfailsover"] +[source,csharp,method="sniffprefersmasternodesbutstillfailsover"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(new[] { @@ -130,7 +130,7 @@ await audit.TraceCall(new ClientCall { }); ---- -[source,csharp,method-name="asniffonstartuphappens"] +[source,csharp,method="asniffonstartuphappens"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc index e0ff37c5e36..cab25b04c21 100644 --- a/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc +++ b/docs/asciidoc/client-concepts/connection-pooling/sniffing/role-detection.asciidoc @@ -11,7 +11,7 @@ When we sniff the custer state we detect the role of the node whether its master eligible and holds data We use this information when selecting a node to perform an API call on. -[source,csharp,method-name="detectsdatanodes"] +[source,csharp,method="detectsdatanodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -53,7 +53,7 @@ pool.Nodes.Where(n => n.HoldsData).Should().HaveCount(5); await audit.TraceStartup(); ---- -[source,csharp,method-name="detectsfqdn"] +[source,csharp,method="detectsfqdn"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) @@ -100,7 +100,7 @@ pool.Nodes.Should().OnlyContain(n => n.Uri.Host.StartsWith("fqdn") && !n.Uri.Hos await audit.TraceStartup(); ---- -[source,csharp,method-name="sniffpicksuproles"] +[source,csharp,method="sniffpicksuproles"] ---- var node = SniffAndReturnNode(); @@ -115,21 +115,21 @@ node.MasterEligible.Should().BeTrue(); node.HoldsData.Should().BeFalse(); ---- -[source,csharp,method-name="sniffandreturnnode"] +[source,csharp,method="sniffandreturnnode"] ---- var pipeline = CreatePipeline(); pipeline.Sniff(); ---- -[source,csharp,method-name="sniffandreturnnodeasync"] +[source,csharp,method="sniffandreturnnodeasync"] ---- var pipeline = CreatePipeline(); await pipeline.SniffAsync(); ---- -[source,csharp,method-name="createpipeline"] +[source,csharp,method="createpipeline"] ---- this._settings = this._cluster.Client(u => new SniffingConnectionPool(new[] {u}), c => c.PrettyJson()).ConnectionSettings; @@ -138,7 +138,7 @@ var pipeline = new RequestPipeline(this._settings, DateTimeProvider.Default, new new SearchRequestParameters()); ---- -[source,csharp,method-name="assertsniffresponse"] +[source,csharp,method="assertsniffresponse"] ---- var nodes = this._settings.ConnectionPool.Nodes; @@ -147,7 +147,7 @@ nodes.Should().NotBeEmpty().And.HaveCount(1); var node = nodes.First(); ---- -[source,csharp,method-name="detectsmasternodes"] +[source,csharp,method="detectsmasternodes"] ---- var audit = new Auditor(() => Framework.Cluster .Nodes(10) diff --git a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc index fcde875a521..0c065e6f7ee 100644 --- a/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/covariant-hits/covariant-search-results.asciidoc @@ -15,7 +15,7 @@ but the actual instance type of the result can be that of the subclass directly Let's look at an example; Imagine we want to search over multiple types that all implement `ISearchResult` -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public interface ISearchResult { @@ -25,7 +25,7 @@ public interface ISearchResult We have three implementations of `ISearchResult` namely `A`, `B` and `C` -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class A : ISearchResult { @@ -52,7 +52,7 @@ The most straightforward way to search over multiple types is to type the response to the parent interface or base class and pass the actual types we want to search over using `.Type()` -[source,csharp,method-name="usingtypes"] +[source,csharp,method="usingtypes"] ---- var result = this._client.Search(s => s .Type(Types.Type(typeof(A), typeof(B), typeof(C))) @@ -66,7 +66,7 @@ hits that have "_type" : "a` will be serialized to `A` and so forth Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method-name="usingtypes"] +[source,csharp,method="usingtypes"] ---- result.IsValid.Should().BeTrue(); @@ -76,7 +76,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method-name="usingtypes"] +[source,csharp,method="usingtypes"] ---- var aDocuments = result.Documents.OfType(); @@ -89,7 +89,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method-name="usingtypes"] +[source,csharp,method="usingtypes"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -101,7 +101,7 @@ cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); A more low level approach is to inspect the hit yourself and determine the CLR type to deserialize to -[source,csharp,method-name="usingconcretetypeselector"] +[source,csharp,method="usingconcretetypeselector"] ---- var result = this._client.Search(s => s .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) @@ -118,7 +118,7 @@ here for each hit we'll call the delegate passed to ConcreteTypeSelector where Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method-name="usingconcretetypeselector"] +[source,csharp,method="usingconcretetypeselector"] ---- result.IsValid.Should().BeTrue(); @@ -128,7 +128,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method-name="usingconcretetypeselector"] +[source,csharp,method="usingconcretetypeselector"] ---- var aDocuments = result.Documents.OfType(); @@ -145,7 +145,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method-name="usingconcretetypeselector"] +[source,csharp,method="usingconcretetypeselector"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -159,7 +159,7 @@ Scroll also supports CovariantSearchResponses The Scroll API is a continuation of the previous Search example so Types() are lost. You can hint at the types using `.CovariantTypes()` -[source,csharp,method-name="usingcovarianttypesonscroll"] +[source,csharp,method="usingcovarianttypesonscroll"] ---- var result = this._client.Scroll(TimeSpan.FromMinutes(60), "scrollId", s => s .CovariantTypes(Types.Type(typeof(A), typeof(B), typeof(C))) @@ -172,7 +172,7 @@ hits that have "_type" : "a` will be serialized to `A` and so forth Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method-name="usingcovarianttypesonscroll"] +[source,csharp,method="usingcovarianttypesonscroll"] ---- result.IsValid.Should().BeTrue(); @@ -182,7 +182,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method-name="usingcovarianttypesonscroll"] +[source,csharp,method="usingcovarianttypesonscroll"] ---- var aDocuments = result.Documents.OfType(); @@ -199,7 +199,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method-name="usingcovarianttypesonscroll"] +[source,csharp,method="usingcovarianttypesonscroll"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); @@ -210,7 +210,7 @@ cDocuments.Should().OnlyContain(a => a.PropertyOnC > 0); The more low level concrete type selector can also be specified on scroll -[source,csharp,method-name="usingconcretetypeselectoronscroll"] +[source,csharp,method="usingconcretetypeselectoronscroll"] ---- var result = this._client.Scroll(TimeSpan.FromMinutes(1), "scrollid", s => s .ConcreteTypeSelector((d, h) => h.Type == "a" ? typeof(A) : h.Type == "b" ? typeof(B) : typeof(C)) @@ -226,7 +226,7 @@ As before, within the delegate passed to `.ConcreteTypeSelector` Here we assume our response is valid and that we received the 100 documents we are expecting. Remember `result.Documents` is an `IEnumerable` -[source,csharp,method-name="usingconcretetypeselectoronscroll"] +[source,csharp,method="usingconcretetypeselectoronscroll"] ---- result.IsValid.Should().BeTrue(); @@ -236,7 +236,7 @@ result.Documents.Count().Should().Be(100); To prove the returned result set is covariant we filter the documents based on their actual type and assert the returned subsets are the expected sizes -[source,csharp,method-name="usingconcretetypeselectoronscroll"] +[source,csharp,method="usingconcretetypeselectoronscroll"] ---- var aDocuments = result.Documents.OfType(); @@ -253,7 +253,7 @@ cDocuments.Count().Should().Be(50); and assume that properties that only exist on the subclass itself are properly filled -[source,csharp,method-name="usingconcretetypeselectoronscroll"] +[source,csharp,method="usingconcretetypeselectoronscroll"] ---- aDocuments.Should().OnlyContain(a => a.PropertyOnA > 0); diff --git a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc index 454d61ebced..ac9fca23db8 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/document-paths.asciidoc @@ -16,7 +16,7 @@ to your document more succintly here we create a new document path based on Project with the id 1 -[source,csharp,method-name="fromid"] +[source,csharp,method="fromid"] ---- IDocumentPath path = new DocumentPath(1); @@ -27,7 +27,7 @@ Expect(1).WhenSerializing(path.Id); You can still override the inferred index and type name -[source,csharp,method-name="fromid"] +[source,csharp,method="fromid"] ---- path = new DocumentPath(1).Type("project1"); @@ -38,7 +38,7 @@ Expect("project1").WhenSerializing(path.Index); and there is also a static way to describe such paths -[source,csharp,method-name="fromid"] +[source,csharp,method="fromid"] ---- path = DocumentPath.Id(1); @@ -51,14 +51,14 @@ Expect(1).WhenSerializing(path.Id); if you have an instance of your document you can use it as well generate document paths -[source,csharp,method-name="fromobject"] +[source,csharp,method="fromobject"] ---- var project = new Project { Name = "hello-world" }; ---- here we create a new document path based on the instance of `Project`, project -[source,csharp,method-name="fromobject"] +[source,csharp,method="fromobject"] ---- IDocumentPath path = new DocumentPath(project); @@ -71,7 +71,7 @@ Expect("hello-world").WhenSerializing(path.Id); You can still override the inferred index and type name -[source,csharp,method-name="fromobject"] +[source,csharp,method="fromobject"] ---- path = new DocumentPath(project).Type("project1"); @@ -84,7 +84,7 @@ Expect("project1").WhenSerializing(path.Index); and again, there is also a static way to describe such paths -[source,csharp,method-name="fromobject"] +[source,csharp,method="fromobject"] ---- path = DocumentPath.Id(project); @@ -99,14 +99,14 @@ DocumentPath p = project; === An example with requests -[source,csharp,method-name="usingwithrequests"] +[source,csharp,method="usingwithrequests"] ---- var project = new Project { Name = "hello-world" }; ---- we can see an example of how `DocumentPath` helps your describe your requests more tersely -[source,csharp,method-name="usingwithrequests"] +[source,csharp,method="usingwithrequests"] ---- var request = new IndexRequest(2) { Document = project }; @@ -116,7 +116,7 @@ request = new IndexRequest(project) { }; when comparing with the full blown constructor and passing document manually, `DocumentPath`'s benefits become apparent. -[source,csharp,method-name="usingwithrequests"] +[source,csharp,method="usingwithrequests"] ---- request = new IndexRequest(IndexName.From(), TypeName.From(), 2) { diff --git a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc index 6eacd91488b..6c5a30e08a7 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/field-inference.asciidoc @@ -15,14 +15,14 @@ These expressions are assigned to a type called `Field` and there are several wa Using the constructor directly is possible but rather involved -[source,csharp,method-name="usingconstructors"] +[source,csharp,method="usingconstructors"] ---- var fieldString = new Field { Name = "name" }; ---- especially when using C expressions since these can not be simply new'ed -[source,csharp,method-name="usingconstructors"] +[source,csharp,method="usingconstructors"] ---- Expression> expression = p => p.Name; @@ -34,14 +34,14 @@ Expect("name") Therefore you can also implicitly convert strings and expressions to `Field`s -[source,csharp,method-name="implicitconversion"] +[source,csharp,method="implicitconversion"] ---- Field fieldString = "name"; ---- but for expressions this is still rather involved -[source,csharp,method-name="implicitconversion"] +[source,csharp,method="implicitconversion"] ---- Expression> expression = p => p.Name; @@ -54,14 +54,14 @@ Expect("name") to ease creating `Field`s from expressions there is a static Property class you can use -[source,csharp,method-name="usingstaticpropertyfield"] +[source,csharp,method="usingstaticpropertyfield"] ---- Field fieldString = "name"; ---- but for expressions this is still rather involved -[source,csharp,method-name="usingstaticpropertyfield"] +[source,csharp,method="usingstaticpropertyfield"] ---- var fieldExpression = Infer.Field(p => p.Name); ---- @@ -69,14 +69,14 @@ var fieldExpression = Infer.Field(p => p.Name); this can be even shortened even further using static imports in c 6 i.e. `using static Nest.Static;` -[source,csharp,method-name="usingstaticpropertyfield"] +[source,csharp,method="usingstaticpropertyfield"] ---- fieldExpression = Field(p => p.Name); ---- Now this is much much terser then our first example using the constructor! -[source,csharp,method-name="usingstaticpropertyfield"] +[source,csharp,method="usingstaticpropertyfield"] ---- Expect("name") .WhenSerializing(fieldString) @@ -87,7 +87,7 @@ By default, NEST will camel-case all field names to be more _javascript-y_ using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior -[source,csharp,method-name="defaultfieldnameinferrer"] +[source,csharp,method="defaultfieldnameinferrer"] ---- var setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p.ToUpper())); @@ -96,14 +96,14 @@ setup.Expect("NAME").WhenSerializing(Field(p => p.Name)); However string are *always* passed along verbatim -[source,csharp,method-name="defaultfieldnameinferrer"] +[source,csharp,method="defaultfieldnameinferrer"] ---- setup.Expect("NaMe").WhenSerializing("NaMe"); ---- if you want the same behavior for expressions simply do nothing in the default inferrer -[source,csharp,method-name="defaultfieldnameinferrer"] +[source,csharp,method="defaultfieldnameinferrer"] ---- setup = WithConnectionSettings(s => s.DefaultFieldNameInferrer(p => p)); @@ -114,14 +114,14 @@ setup.Expect("Name").WhenSerializing(Field(p => p.Name)); You can follow your property expression to any depth. Here we are traversing to the LeadDeveloper's (Person) FirstName -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- Expect("leadDeveloper.firstName").WhenSerializing(Field(p => p.LeadDeveloper.FirstName)); ---- When dealing with collection indexers, the indexer access is ignored allowing you to traverse into properties of collections -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); ---- @@ -129,7 +129,7 @@ Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags[0])); NOTE: Similarly, LINQ's `.First()` method also works remember these are expressions and not actual code that will be executed -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- Expect("curatedTags").WhenSerializing(Field(p => p.CuratedTags.First())); @@ -140,7 +140,7 @@ Expect("curatedTags.name").WhenSerializing(Field(p => p.CuratedTags.Fir An indexer on a dictionary is assumed to describe a property name -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- Expect("metadata.hardcoded").WhenSerializing(Field(p => p.Metadata["hardcoded"])); @@ -149,7 +149,7 @@ Expect("metadata.hardcoded.created").WhenSerializing(Field(p => p.Metad A cool feature here is that we'll evaluate variables passed to an indexer -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- var variable = "var"; @@ -163,7 +163,7 @@ you to analyze a string in a number of different ways, these _"virtual" sub fiel do not always map back on to your POCO. By calling `.Suffix()` on expressions, you describe the sub fields that should be mapped. -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- Expect("leadDeveloper.firstName.raw").WhenSerializing(Field(p => p.LeadDeveloper.FirstName.Suffix("raw"))); @@ -180,14 +180,14 @@ Expect("metadata.hardcoded.created.raw").WhenSerializing(Field(p => p.M You can even chain `.Suffix()` calls to any depth! -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- Expect("curatedTags.name.raw.evendeeper").WhenSerializing(Field(p => p.CuratedTags.First().Name.Suffix("raw").Suffix("evendeeper"))); ---- Variables passed to suffix will be evaluated as well -[source,csharp,method-name="complexfieldnameexpressions"] +[source,csharp,method="complexfieldnameexpressions"] ---- var suffix = "unanalyzed"; @@ -201,7 +201,7 @@ to a list of fields. Here we have a list of expressions -[source,csharp,method-name="appendingsuffixtoexpressions"] +[source,csharp,method="appendingsuffixtoexpressions"] ---- var expressions = new List>> { @@ -214,7 +214,7 @@ var expressions = new List>> and we want to append the suffix "raw" to each -[source,csharp,method-name="appendingsuffixtoexpressions"] +[source,csharp,method="appendingsuffixtoexpressions"] ---- var fieldExpressions = expressions.Select>, Field>(e => e.AppendSuffix("raw")).ToList(); @@ -232,7 +232,7 @@ Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]); When using NEST's property attributes you can specify a new name for the properties -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class BuiltIn { @@ -241,7 +241,7 @@ public class BuiltIn } ---- -[source,csharp,method-name="builtinannotiatons"] +[source,csharp,method="builtinannotiatons"] ---- Expect("naam").WhenSerializing(Field(p => p.Name)); ---- @@ -250,7 +250,7 @@ Starting with NEST 2.x we also ask the serializer if it can resolve the property Here we ask the default `JsonNetSerializer` to resolve a property name and it takes the `JsonPropertyAttribute` into account -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class SerializerSpecific { @@ -259,7 +259,7 @@ public class SerializerSpecific } ---- -[source,csharp,method-name="serializerspecificannotations"] +[source,csharp,method="serializerspecificannotations"] ---- Expect("nameInJson").WhenSerializing(Field(p => p.Name)); ---- @@ -267,7 +267,7 @@ Expect("nameInJson").WhenSerializing(Field(p => p.Name)); If both a NEST property attribute and a serializer specific attribute are present on a property, NEST takes precedence -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class Both { @@ -277,7 +277,7 @@ public class Both } ---- -[source,csharp,method-name="nestattributetakesprecedence"] +[source,csharp,method="nestattributetakesprecedence"] ---- Expect("naam").WhenSerializing(Field(p => p.Name)); @@ -290,7 +290,7 @@ Expect(new Resolution of field names is cached per connection settings instance. To demonstrate, take the following simple POCOs -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- class A { public C C { get; set; } } @@ -299,7 +299,7 @@ class B { public C C { get; set; } } class C { public string Name { get; set; } } ---- -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +[source,csharp,method="expressionsarecachedbutseedifferenttypes"] ---- var connectionSettings = TestClient.CreateSettings(forceInMemory: true); @@ -313,7 +313,7 @@ var fieldNameOnB = client.Infer.Field(Field(p => p.C.Name)); Here we have to similary shaped expressions on coming from A and on from B that will resolve to the same field name, as expected -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +[source,csharp,method="expressionsarecachedbutseedifferenttypes"] ---- fieldNameOnA.Should().Be("c.name"); @@ -323,7 +323,7 @@ fieldNameOnB.Should().Be("c.name"); now we create a new connectionsettings with a remap for C on class A to `d` now when we resolve the field path for A will be different -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +[source,csharp,method="expressionsarecachedbutseedifferenttypes"] ---- var newConnectionSettings = TestClient.CreateSettings(forceInMemory: true, modifySettings: s => s .InferMappingFor(m => m @@ -344,7 +344,7 @@ fieldNameOnB.Should().Be("c.name"); however we didn't break inferrence on the first client instance using its separate connectionsettings -[source,csharp,method-name="expressionsarecachedbutseedifferenttypes"] +[source,csharp,method="expressionsarecachedbutseedifferenttypes"] ---- fieldNameOnA = client.Infer.Field(Field(p => p.C.Name)); @@ -367,7 +367,7 @@ To wrap up, the precedence in which field names are inferred is: The following example class will demonstrate this precedence -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- class Precedence { @@ -398,7 +398,7 @@ class Precedence Here we create a custom serializer that renames any property named `AskSerializer` to `ask` -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- class CustomSerializer : JsonNetSerializer { @@ -416,7 +416,7 @@ class CustomSerializer : JsonNetSerializer here we provide an explicit rename of a property on connectionsettings using `.Rename()` and all properties that are not mapped verbatim should be uppercased -[source,csharp,method-name="precedenceisasexpected"] +[source,csharp,method="precedenceisasexpected"] ---- var usingSettings = WithConnectionSettings(s => s @@ -439,7 +439,7 @@ usingSettings.Expect("DEFAULTFIELDNAMEINFERRER").ForField(Field(p => The same naming rules also apply when indexing a document -[source,csharp,method-name="precedenceisasexpected"] +[source,csharp,method="precedenceisasexpected"] ---- usingSettings.Expect(new [] { diff --git a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc index fb85a375f6d..8babd2f9966 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/ids-inference.asciidoc @@ -23,7 +23,7 @@ This is a special box type that you can implicitly convert to from the following Methods that take an `Id` can be passed any of these types and it will be implicitly converted to an `Id` -[source,csharp,method-name="canimplicitlyconverttoid"] +[source,csharp,method="canimplicitlyconverttoid"] ---- Id idFromInt = 1; Id idFromLong = 2L; @@ -42,7 +42,7 @@ There is no implicit conversion from any object to Id but we can call `Id.From`. Imagine your codebase has the following type that we want to index into Elasticsearch -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- class MyDTO { @@ -55,7 +55,7 @@ class MyDTO By default NEST will try to find a property called `Id` on the class using reflection and create a cached fast func delegate based on the properties getter -[source,csharp,method-name="cangetidfromdocument"] +[source,csharp,method="cangetidfromdocument"] ---- var dto = new MyDTO { @@ -70,7 +70,7 @@ Expect("d70bd3cf-4e38-46f3-91ca-fcbef29b148e").WhenInferringIdOn(dto); Using the connection settings you can specify a different property that NEST should use to infer the document Id. Here we instruct NEST to infer the Id for `MyDTO` based on its `Name` property -[source,csharp,method-name="cangetidfromdocument"] +[source,csharp,method="cangetidfromdocument"] ---- WithConnectionSettings(x => x .InferMappingFor(m => m @@ -84,7 +84,7 @@ IMPORTANT: Inference rules are cached __per__ `ConnectionSettings` instance. Because the cache is per `ConnectionSettings` instance, we can create another `ConnectionSettings` instance with different inference rules -[source,csharp,method-name="cangetidfromdocument"] +[source,csharp,method="cangetidfromdocument"] ---- WithConnectionSettings(x => x .InferMappingFor(m => m @@ -98,7 +98,7 @@ WithConnectionSettings(x => x Another way is to mark the type with an `ElasticsearchType` attribute, setting `IdProperty` to the name of the property that should be used for the document id -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- [ElasticsearchType(IdProperty = nameof(Name))] class MyOtherDTO @@ -111,7 +111,7 @@ class MyOtherDTO Now when we infer the id we expect it to be the value of the `Name` property without doing any configuration on the `ConnectionSettings` -[source,csharp,method-name="cangetidfromattribute"] +[source,csharp,method="cangetidfromattribute"] ---- var dto = new MyOtherDTO { Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"), Name = "x", OtherName = "y" }; @@ -124,7 +124,7 @@ This attribute *is* cached statically/globally, however an inference rule on the still win over the attribute. Here we demonstrate this by creating a different `ConnectionSettings` instance that will infer the document id from the property `OtherName`: -[source,csharp,method-name="cangetidfromattribute"] +[source,csharp,method="cangetidfromattribute"] ---- WithConnectionSettings(x => x .InferMappingFor(m => m diff --git a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc index 3fbdb39838b..dc0df0a8ea7 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/indices-paths.asciidoc @@ -13,7 +13,7 @@ In nest this is encoded using `Indices` Several types implicitly convert to `Indices` -[source,csharp,method-name="implicitconversionfromstring"] +[source,csharp,method="implicitconversionfromstring"] ---- Nest.Indices singleIndexFromString = "name"; Nest.Indices multipleIndicesFromString = "name1, name2"; @@ -39,7 +39,7 @@ allWithOthersFromString.Match( to ease creating Field's from expressions there is a static Property class you can use -[source,csharp,method-name="usingstaticpropertyfield"] +[source,csharp,method="usingstaticpropertyfield"] ---- var all = Nest.Indices.All; diff --git a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc index 421cbf92b5b..4218dd541e9 100644 --- a/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/inference/property-inference.asciidoc @@ -10,7 +10,7 @@ Property names resolve to the last token. An example using the `.Suffix()` extension -[source,csharp,method-name="propertynamesareresolvedtolasttokenusingsuffix"] +[source,csharp,method="propertynamesareresolvedtolasttokenusingsuffix"] ---- Expression> expression = p => p.Name.Suffix("raw"); Expect("raw").WhenSerializing(expression); @@ -18,7 +18,7 @@ Expect("raw").WhenSerializing(expression); And an example using the `.ApplySuffix()` extension on lambda expressions -[source,csharp,method-name="propertynamesareresolvedtolasttokenusingapplysuffix"] +[source,csharp,method="propertynamesareresolvedtolasttokenusingapplysuffix"] ---- Expression> expression = p => p.Name; @@ -30,7 +30,7 @@ Expect("raw").WhenSerializing(expression); Property names cannot contain a `.` in order to prevent the potential for collision with a field that may have {ref_current}/_multi_fields.html[`multi_fields`] -[source,csharp,method-name="stringscontainingdotsisanexception"] +[source,csharp,method="stringscontainingdotsisanexception"] ---- Assert.Throws(() => Expect("exception!").WhenSerializing("name.raw")); ---- diff --git a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc index 693b7905767..ca07f9da95c 100644 --- a/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc +++ b/docs/asciidoc/client-concepts/high-level/mapping/auto-map.asciidoc @@ -18,7 +18,7 @@ For these examples, we'll define two POCOS, `Company`, which has a name and a collection of Employees, and `Employee` which has various properties of different types, and itself has a collection of `Employee` types. -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class Company { @@ -43,7 +43,7 @@ public class Employee To create a mapping for our Company type, we can use the fluent API and map each property explicitly -[source,csharp,method-name="mappingmanually"] +[source,csharp,method="mappingmanually"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -76,7 +76,7 @@ This is all fine and dandy and useful for some use cases however in most cases this can become verbose and wieldy. The majority of the time you simply just want to map *all* the properties of a POCO in a single go. -[source,csharp,method-name="mappingmanually"] +[source,csharp,method="mappingmanually"] ---- var expected = new { @@ -122,7 +122,7 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); This is exactly where `AutoMap()` becomes useful. Instead of manually mapping each property, explicitly, we can instead call `.AutoMap()` for each of our mappings and let NEST do all the work -[source,csharp,method-name="usingautomap"] +[source,csharp,method="usingautomap"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -145,7 +145,7 @@ In this example, * Employees as an object and the remaining string properties as strings. -[source,csharp,method-name="usingautomap"] +[source,csharp,method="usingautomap"] ---- var expected = new { @@ -248,7 +248,7 @@ Here we are using AutoMap() to automatically map our company type, but then we'r overriding our employee property and making it a `nested` type, since by default, AutoMap() will infer objects as `object`. -[source,csharp,method-name="overridingautomappedproperties"] +[source,csharp,method="overridingautomappedproperties"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -296,7 +296,7 @@ It is also possible to define your mappings using attributes on your POCOS. Whe use attributes, you *must* use `.AutoMap()` in order for the attributes to be applied. Here we define the same two types but this time using attributes. -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- [ElasticsearchType(Name = "company")] public class CompanyWithAttributes @@ -337,7 +337,7 @@ public class EmployeeWithAttributes Then map the types by calling `.AutoMap()` -[source,csharp,method-name="usingautomapwithattributes"] +[source,csharp,method="usingautomapwithattributes"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -484,7 +484,7 @@ Just as we were able to override the inferred properties in our earlier example, mappings also take precedence over attributes. Therefore we can also override any mappings applied via any attributes defined on the POCO -[source,csharp,method-name="overridingautomappedattributes"] +[source,csharp,method="overridingautomappedattributes"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -658,7 +658,7 @@ Properties on a POCO can be ignored in a few ways: This example demonstrates all ways, using the `Ignore` property on the attribute to ignore the property `PropertyToIgnore`, the infer mapping to ignore the property `AnotherPropertyToIgnore` and the json serializer specific attribute to ignore the property `JsonIgnoredProperty` -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- [ElasticsearchType(Name = "company")] public class CompanyWithAttributesAndPropertiesToIgnore @@ -677,7 +677,7 @@ public class CompanyWithAttributesAndPropertiesToIgnore All of the properties except `Name` have been ignored in the mapping -[source,csharp,method-name="ignoringproperties"] +[source,csharp,method="ignoringproperties"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -726,7 +726,7 @@ the need to do this, so you can control the recursion depth of `.AutoMap()`. Let's introduce a very simple class, `A`, which itself has a property Child of type `A`. -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class A { @@ -736,7 +736,7 @@ public class A By default, `.AutoMap()` only goes as far as depth 1 -[source,csharp,method-name="controllingrecursiondepth"] +[source,csharp,method="controllingrecursiondepth"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -746,7 +746,7 @@ var descriptor = new CreateIndexDescriptor("myindex") Thus we do not map properties on the second occurrence of our Child property -[source,csharp,method-name="controllingrecursiondepth"] +[source,csharp,method="controllingrecursiondepth"] ---- var expected = new { @@ -771,7 +771,7 @@ Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); Now lets specify a maxRecursion of 3 -[source,csharp,method-name="controllingrecursiondepth"] +[source,csharp,method="controllingrecursiondepth"] ---- var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -781,7 +781,7 @@ var withMaxRecursionDescriptor = new CreateIndexDescriptor("myindex") `.AutoMap()` has now mapped three levels of our Child property -[source,csharp,method-name="controllingrecursiondepth"] +[source,csharp,method="controllingrecursiondepth"] ---- var expectedWithMaxRecursion = new { @@ -835,7 +835,7 @@ does nothing and acts as a blank canvas for you to implement your own visiting m For instance, lets create a custom visitor that disables doc values for numeric and boolean types. (Not really a good idea in practice, but let's do it anyway for the sake of a clear example.) -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor { @@ -855,7 +855,7 @@ public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor Now we can pass an instance of our custom visitor to `.AutoMap()` -[source,csharp,method-name="usingacustompropertyvisitor"] +[source,csharp,method="usingacustompropertyvisitor"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms @@ -868,7 +868,7 @@ and anytime it maps a property as a number (`INumberProperty`) or boolean (`IBoo it will apply the transformation defined in each `Visit()` respectively, which in this example disables {ref_current}/doc-values.html[doc values]. -[source,csharp,method-name="usingacustompropertyvisitor"] +[source,csharp,method="usingacustompropertyvisitor"] ---- var expected = new { @@ -915,7 +915,7 @@ You can even take the visitor approach a step further, and instead of visiting o directly on your POCO properties (`PropertyInfo`). For example, let's create a visitor that maps all CLR types to an Elasticsearch string (`IStringProperty`). -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor { @@ -924,7 +924,7 @@ public class EverythingIsAStringPropertyVisitor : NoopPropertyVisitor } ---- -[source,csharp,method-name="usingacustompropertyvisitoronpropertyinfo"] +[source,csharp,method="usingacustompropertyvisitoronpropertyinfo"] ---- var descriptor = new CreateIndexDescriptor("myindex") .Mappings(ms => ms diff --git a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc index bfddd8158ea..5fe3ae29d35 100644 --- a/docs/asciidoc/client-concepts/low-level/connecting.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/connecting.asciidoc @@ -14,7 +14,7 @@ Connecting to Elasticsearch with `Elasticsearch.Net` is quite easy and there a f If you simply new an `ElasticLowLevelClient`, it will be a non-failover connection to `http://localhost:9200` -[source,csharp,method-name="instantiateusingalldefaults"] +[source,csharp,method="instantiateusingalldefaults"] ---- var client = new ElasticLowLevelClient(); ---- @@ -24,7 +24,7 @@ you will need to pass in some instance of `IConnectionConfigurationValues`. The easiest way to do this is: -[source,csharp,method-name="instantiatingasinglenodeclient"] +[source,csharp,method="instantiatingasinglenodeclient"] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -37,7 +37,7 @@ This will still be a non-failover connection, meaning if that `node` goes down t To get a failover connection we have to pass an `IConnectionPool` instance instead of a `Uri`. -[source,csharp,method-name="instantiatingaconnectionpoolclient"] +[source,csharp,method="instantiatingaconnectionpoolclient"] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -55,7 +55,7 @@ Be sure to read more about <<../connection-pooling/connection-pooling, Connectio Besides either passing a `Uri` or `IConnectionPool` to `ConnectionConfiguration`, you can also fluently control many more options. For instance: -[source,csharp,method-name="specifyingclientoptions"] +[source,csharp,method="specifyingclientoptions"] ---- var node = new Uri("http://mynode.example.com:8082/apiKey"); @@ -69,7 +69,7 @@ var config = new ConnectionConfiguration(connectionPool) The following is a list of available connection configuration options: -[source,csharp,method-name="availableoptions"] +[source,csharp,method="availableoptions"] ---- var client = new ElasticLowLevelClient(); ---- @@ -82,7 +82,7 @@ See the {ref_current}/modules-http.html[http module settings] for more info). By default responses are deserialized off stream to the object you tell it to. For debugging purposes it can be very useful to keep a copy of the raw response on the result object. -[source,csharp,method-name="availableoptions"] +[source,csharp,method="availableoptions"] ---- var config = new ConnectionConfiguration() .DisableAutomaticProxyDetection() @@ -94,7 +94,7 @@ var result = client.Search>(new { size = 12 }); This will only have a value if the client configuration has `DisableDirectStreaming` set -[source,csharp,method-name="availableoptions"] +[source,csharp,method="availableoptions"] ---- var raw = result.ResponseBodyInBytes; ---- @@ -102,7 +102,7 @@ var raw = result.ResponseBodyInBytes; Please note that this only make sense if you need a mapped response and the raw response at the same time. If you need a `string` or `byte[]` response simply call: -[source,csharp,method-name="availableoptions"] +[source,csharp,method="availableoptions"] ---- var stringResult = client.Search(new { }); ---- @@ -139,7 +139,7 @@ when an API in the client is misused. These should not be handled as you want t * `BasicAuthentication(username, password)`: sets the HTTP basic authentication credentials to specify with all requests. -[source,csharp,method-name="availableoptions"] +[source,csharp,method="availableoptions"] ---- config = config .GlobalQueryStringParameters(new NameValueCollection()) @@ -152,7 +152,7 @@ config = config NOTE: Basic authentication credentials can alternatively be specified on the node URI directly: -[source,csharp,method-name="availableoptions"] +[source,csharp,method="availableoptions"] ---- var uri = new Uri("http://username:password@localhost:9200"); @@ -166,7 +166,7 @@ var settings = new ConnectionConfiguration(uri); You can pass a callback of type `Action` that can eaves drop every time a response (good or bad) is created. If you have complex logging needs this is a good place to add that in. -[source,csharp,method-name="onrequestcompletediscalled"] +[source,csharp,method="onrequestcompletediscalled"] ---- var counter = 0; @@ -191,7 +191,7 @@ Here's an example of using `OnRequestCompleted()` for complex logging. Remember, to capture the request and/or response bytes, you also need to set `.DisableDirectStreaming()` to `true` -[source,csharp,method-name="usingonrequestcompletedforlogging"] +[source,csharp,method="usingonrequestcompletedforlogging"] ---- var list = new List(); @@ -279,7 +279,7 @@ property. The bare minimum to make .NET accept self-signed SSL certs that are not in the Window's CA store would be to have the callback simply return `true`: -[source,csharp,method-name="configuringssl"] +[source,csharp,method="configuringssl"] ---- ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; ---- @@ -298,7 +298,7 @@ Override ModifyJsonSerializerSettings if you need access to `JsonSerializerSetti You can inject contract resolved converters by implementing the ContractConverters property This can be much faster then registering them on JsonSerializerSettings.Converters -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- public class MyJsonNetSerializer : JsonNetSerializer { @@ -320,7 +320,7 @@ public int CallToContractConverter { get; set; } = 0; You can then register a factory on `ConnectionSettings` to create an instance of your subclass instead. This is **_called once per instance_** of ConnectionSettings. -[source,csharp,method-name="modifyjsonserializersettingsiscalled"] +[source,csharp,method="modifyjsonserializersettingsiscalled"] ---- var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); diff --git a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc index 6e3700b2cda..88e54543e66 100644 --- a/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/lifetimes.asciidoc @@ -25,7 +25,7 @@ Elasticsearch 1.x and 2.x in the same application as the former would require NE Let's demonstrate which components are disposed by creating our own derived `ConnectionSettings`, `IConnectionPool` and `IConnection` types -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- class AConnectionSettings : ConnectionSettings { @@ -65,7 +65,7 @@ class AConnection : InMemoryConnection `ConnectionSettings`, `IConnectionPool` and `IConnection` all explictily implement `IDisposable` -[source,csharp,method-name="initialdisposestate"] +[source,csharp,method="initialdisposestate"] ---- var connection = new AConnection(); var connectionPool = new AConnectionPool(new Uri("http://localhost:9200")); @@ -77,7 +77,7 @@ connection.IsDisposed.Should().BeFalse(); Disposing `ConnectionSettings` will dispose the `IConnectionPool` and `IConnection` it has a hold of -[source,csharp,method-name="disposingsettingsdisposesmovingparts"] +[source,csharp,method="disposingsettingsdisposesmovingparts"] ---- var connection = new AConnection(); diff --git a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc index bba14d4cf53..73752561a7c 100644 --- a/docs/asciidoc/client-concepts/low-level/post-data.asciidoc +++ b/docs/asciidoc/client-concepts/low-level/post-data.asciidoc @@ -25,7 +25,7 @@ You can implicitly convert from the following types * `object` -[source,csharp,method-name="implicitconversions"] +[source,csharp,method="implicitconversions"] ---- var fromString = ImplicitlyConvertsFrom(@string); @@ -37,19 +37,19 @@ var fromObject = ImplicitlyConvertsFrom(@object); PostData bytes will always be set if it originated from a byte -[source,csharp,method-name="implicitconversions"] +[source,csharp,method="implicitconversions"] ---- fromByteArray.WrittenBytes.Should().BeSameAs(bytes); ---- -[source,csharp,method-name="writescorrectlyusingbothlowandhighlevelsettings"] +[source,csharp,method="writescorrectlyusingbothlowandhighlevelsettings"] ---- await this.AssertOn(new ConnectionSettings()); await this.AssertOn(new ConnectionConfiguration()); ---- -[source,csharp,method-name="implicitconversions"] +[source,csharp,method="implicitconversions"] ---- fromString.Type.Should().Be(PostType.LiteralString); fromByteArray.Type.Should().Be(PostType.ByteArray); @@ -70,7 +70,7 @@ fromObject.Type.Should().Be(PostType.Serializable); Although each implicitly types behaves slightly differently -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- await Post(() => @string, writes: Utf8Bytes(@string), storesBytes: true, settings: settings); @@ -80,7 +80,7 @@ await Post(() => bytes, writes: bytes, storesBytes: true, settings: settings); When passing a list of strings we assume its a list of valid serialized json that we join with newlinefeeds making sure there is a trailing linefeed -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- await Post(() => listOfStrings, writes: multiStringJson, storesBytes: true, settings: settings); ---- @@ -88,21 +88,21 @@ await Post(() => listOfStrings, writes: multiStringJson, storesBytes: true, sett When passing a list of object we assume its a list of objects we need to serialize individually to json and join with newlinefeeds aking sure there is a trailing linefeed -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: false, settings: settings); ---- In all other cases postdata is serialized as is. -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- await Post(() => @object, writes: objectJson, storesBytes: false, settings: settings); ---- If you want to maintain a copy of the request that went out use the following settings -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- settings = new ConnectionSettings().DisableDirectStreaming(); ---- @@ -110,26 +110,26 @@ settings = new ConnectionSettings().DisableDirectStreaming(); by forcing `DisableDirectStreaming` serializing happens first in a private MemoryStream so we can get hold of the serialized bytes -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- await Post(() => listOfObjects, writes: multiObjectJson, storesBytes: true, settings: settings); ---- this behavior can also be observed when serializing a simple object using `DisableDirectStreaming` -[source,csharp,method-name="asserton"] +[source,csharp,method="asserton"] ---- await Post(() => @object, writes: objectJson, storesBytes: true, settings: settings); ---- -[source,csharp,method-name="post"] +[source,csharp,method="post"] ---- PostAssert(postData(), writes, storesBytes, settings); await PostAssertAsync(postData(), writes, storesBytes, settings); ---- -[source,csharp,method-name="postassert"] +[source,csharp,method="postassert"] ---- postData.Write(ms, settings); @@ -142,7 +142,7 @@ postData.WrittenBytes.Should().NotBeNull(); postData.WrittenBytes.Should().BeNull(); ---- -[source,csharp,method-name="postassertasync"] +[source,csharp,method="postassertasync"] ---- await postData.WriteAsync(ms, settings); diff --git a/docs/asciidoc/code-standards/descriptors.asciidoc b/docs/asciidoc/code-standards/descriptors.asciidoc index 5d88340a2a3..403c540ff9d 100644 --- a/docs/asciidoc/code-standards/descriptors.asciidoc +++ b/docs/asciidoc/code-standards/descriptors.asciidoc @@ -6,7 +6,7 @@ Every descriptor should inherit from `DescriptorBase`, this hides object members from the fluent interface -[source,csharp,method-name="descriptorshavetobemarkedwithidescriptor"] +[source,csharp,method="descriptorshavetobemarkedwithidescriptor"] ---- var notDescriptors = new[] { typeof(ClusterProcessOpenFileDescriptors).Name, "DescriptorForAttribute" }; var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() @@ -20,7 +20,7 @@ descriptors.Should().BeEmpty(); Methods taking a func should have that func return an interface -[source,csharp,method-name="selectorsreturninterface"] +[source,csharp,method="selectorsreturninterface"] ---- var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types() diff --git a/docs/asciidoc/code-standards/elastic-client.asciidoc b/docs/asciidoc/code-standards/elastic-client.asciidoc index b951bd93294..bbda2ad5c1a 100644 --- a/docs/asciidoc/code-standards/elastic-client.asciidoc +++ b/docs/asciidoc/code-standards/elastic-client.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../images -[source,csharp,method-name="consistentinitializerparameternames"] +[source,csharp,method="consistentinitializerparameternames"] ---- var requestParametersNotNamedRequest = from m in typeof(IElasticClient).GetMethods() @@ -16,7 +16,7 @@ var requestParametersNotNamedRequest = requestParametersNotNamedRequest.Should().BeEmpty(); ---- -[source,csharp,method-name="initializerrequestsarenotoptional"] +[source,csharp,method="initializerrequestsarenotoptional"] ---- var requestParameters = (from m in typeof(IElasticClient).GetMethods() @@ -27,7 +27,7 @@ var requestParameters = requestParameter.HasDefaultValue.Should().BeFalse(); ---- -[source,csharp,method-name="concreteclientoptionalparametersmatchinterfaceclient"] +[source,csharp,method="concreteclientoptionalparametersmatchinterfaceclient"] ---- var concreteMethodParametersDoNotMatchInterface = new List(); @@ -53,7 +53,7 @@ concreteMethodParametersDoNotMatchInterface.Add( concreteMethodParametersDoNotMatchInterface.Should().BeEmpty(); ---- -[source,csharp,method-name="consistentoptionalparametersforsyncandasyncmethods"] +[source,csharp,method="consistentoptionalparametersforsyncandasyncmethods"] ---- var methodGroups = from methodInfo in typeof(IElasticClient).GetMethods() @@ -79,7 +79,7 @@ asyncMethod.Parameter.HasDefaultValue.Should().Be(syncMethod.Parameter.HasDefaul $"sync and async versions of {asyncMethod.MethodType} '{nameof(ElasticClient)}{methodGroup.Key}' should match"); ---- -[source,csharp,method-name="consistentfluentparameternames"] +[source,csharp,method="consistentfluentparameternames"] ---- var fluentParametersNotNamedSelector = from m in typeof (IElasticClient).GetMethods() @@ -90,7 +90,7 @@ var fluentParametersNotNamedSelector = fluentParametersNotNamedSelector.Should().BeEmpty(); ---- -[source,csharp,method-name="unknown"] +[source,csharp,method="unknown"] ---- private class MethodWithRequestParameter { diff --git a/docs/asciidoc/code-standards/naming-conventions.asciidoc b/docs/asciidoc/code-standards/naming-conventions.asciidoc index 348a52b8370..cfd6b1b9ce2 100644 --- a/docs/asciidoc/code-standards/naming-conventions.asciidoc +++ b/docs/asciidoc/code-standards/naming-conventions.asciidoc @@ -12,7 +12,7 @@ NEST uses the following naming conventions (with _some_ exceptions). Abstract class names should end with a `Base` suffix -[source,csharp,method-name="abstractclassnamesendwithbase"] +[source,csharp,method="abstractclassnamesendwithbase"] ---- var exceptions = new[] { @@ -28,7 +28,7 @@ abstractClasses.Should().BeEmpty(); Class names that end with `Base` suffix are abstract -[source,csharp,method-name="classnamecontainsbaseshouldbeabstract"] +[source,csharp,method="classnamecontainsbaseshouldbeabstract"] ---- var exceptions = new[] { typeof(DateMath) }; @@ -46,7 +46,7 @@ baseClassesNotAbstract.Should().BeEmpty(); Request class names should end with `Request` -[source,csharp,method-name="requestclassnamesendwithrequest"] +[source,csharp,method="requestclassnamesendwithrequest"] ---- var types = typeof(IRequest).Assembly().GetTypes(); @@ -62,7 +62,7 @@ requests.Should().BeEmpty(); Response class names should end with `Response` -[source,csharp,method-name="responseclassnamesendwithresponse"] +[source,csharp,method="responseclassnamesendwithresponse"] ---- var types = typeof(IRequest).Assembly().GetTypes(); @@ -80,7 +80,7 @@ e.g. `ValidateRequest` => `ValidateResponse`, and not `ValidateQueryRequest` => There are a few exceptions to this rule, most notably the `Cat` prefixed requests and the `Exists` requests. -[source,csharp,method-name="paritybetweenrequestsandresponses"] +[source,csharp,method="paritybetweenrequestsandresponses"] ---- var exceptions = new[] //<1> { diff --git a/docs/asciidoc/code-standards/queries.asciidoc b/docs/asciidoc/code-standards/queries.asciidoc index ebc00ab80d1..c2272429279 100644 --- a/docs/asciidoc/code-standards/queries.asciidoc +++ b/docs/asciidoc/code-standards/queries.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../images -[source,csharp,method-name="staticqueryexposesall"] +[source,csharp,method="staticqueryexposesall"] ---- var staticProperties = from p in typeof(Query<>).GetMethods() let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name @@ -15,7 +15,7 @@ var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("Geo staticProperties.Distinct().Should().Contain(placeHolders.Distinct()); ---- -[source,csharp,method-name="fluentdescriptorexposesall"] +[source,csharp,method="fluentdescriptorexposesall"] ---- var fluentMethods = from p in typeof(QueryContainerDescriptor<>).GetMethods() let name = p.Name.StartsWith("GeoShape") ? "GeoShape" : p.Name @@ -26,7 +26,7 @@ var placeHolders = QueryPlaceHolderProperties.Select(p => p.Name.StartsWith("Geo fluentMethods.Distinct().Should().Contain(placeHolders.Distinct()); ---- -[source,csharp,method-name="visitorvisitsall"] +[source,csharp,method="visitorvisitsall"] ---- var skipQueryImplementations = new[] { typeof(IFieldNameQuery), typeof(IFuzzyQuery<,>), typeof(IConditionlessQuery) }; @@ -49,7 +49,7 @@ var missingTypes = from q in queries missingTypes.Should().BeEmpty(); ---- -[source,csharp,method-name="interfacepropertiesmustbemarkedexplicitly"] +[source,csharp,method="interfacepropertiesmustbemarkedexplicitly"] ---- var properties = from p in QueryProperties let a = p.GetCustomAttributes().Concat(p.GetCustomAttributes()) diff --git a/docs/asciidoc/code-standards/serialization/properties.asciidoc b/docs/asciidoc/code-standards/serialization/properties.asciidoc index 73b686ca5ff..6923fcd7ee0 100644 --- a/docs/asciidoc/code-standards/serialization/properties.asciidoc +++ b/docs/asciidoc/code-standards/serialization/properties.asciidoc @@ -6,7 +6,7 @@ Our Json.NET contract resolver picks up attributes set on the interface -[source,csharp,method-name="seesinterfaceproperties"] +[source,csharp,method="seesinterfaceproperties"] ---- var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(pool, new InMemoryConnection()); diff --git a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc index ec684ae595c..e9595eb8286 100644 --- a/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc +++ b/docs/asciidoc/common-options/date-math/date-math-expressions.asciidoc @@ -37,7 +37,7 @@ Be sure to read the elasticsearch documentation {datemath}[on this subject here] You can create simple expressions using any of the static methods on `DateMath` -[source,csharp,method-name="simpleexpressions"] +[source,csharp,method="simpleexpressions"] ---- Expect("now").WhenSerializing(Nest.DateMath.Now); @@ -46,21 +46,21 @@ Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTim strings implicitly convert to `DateMath` -[source,csharp,method-name="simpleexpressions"] +[source,csharp,method="simpleexpressions"] ---- Expect("now").WhenSerializing("now"); ---- but are lenient to bad math expressions -[source,csharp,method-name="simpleexpressions"] +[source,csharp,method="simpleexpressions"] ---- var nonsense = "now||*asdaqwe"; ---- the resulting date math will assume the whole string is the anchor -[source,csharp,method-name="simpleexpressions"] +[source,csharp,method="simpleexpressions"] ---- Expect(nonsense).WhenSerializing(nonsense) .Result(dateMath => ((IDateMath)dateMath) @@ -73,14 +73,14 @@ Expect(nonsense).WhenSerializing(nonsense) `DateTime` also implicitly convert to simple date math expressions -[source,csharp,method-name="simpleexpressions"] +[source,csharp,method="simpleexpressions"] ---- var date = new DateTime(2015, 05, 05); ---- the anchor will be an actual `DateTime`, even after a serialization/deserialization round trip -[source,csharp,method-name="simpleexpressions"] +[source,csharp,method="simpleexpressions"] ---- Expect("2015-05-05T00:00:00").WhenSerializing(date) .Result(dateMath => ((IDateMath)dateMath) @@ -95,21 +95,21 @@ Expect("2015-05-05T00:00:00").WhenSerializing(date) Ranges can be chained on to simple expressions -[source,csharp,method-name="complexexpressions"] +[source,csharp,method="complexexpressions"] ---- Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d")); ---- Including multiple operations -[source,csharp,method-name="complexexpressions"] +[source,csharp,method="complexexpressions"] ---- Expect("now+1d-1m").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1))); ---- A rounding value can be chained to the end of the expression, after which no more ranges can be appended -[source,csharp,method-name="complexexpressions"] +[source,csharp,method="complexexpressions"] ---- Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)).RoundTo(Nest.TimeUnit.Day)); ---- @@ -117,7 +117,7 @@ Expect("now+1d-1m/d").WhenSerializing(Nest.DateMath.Now.Add("1d").Subtract(TimeS When anchoring dates, a `||` needs to be appended as clear separator between the anchor and ranges. Again, multiple ranges can be chained -[source,csharp,method-name="complexexpressions"] +[source,csharp,method="complexexpressions"] ---- Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05,05)).Add("1d").Subtract(TimeSpan.FromMinutes(1))); ---- diff --git a/docs/asciidoc/common-options/time-unit/time-units.asciidoc b/docs/asciidoc/common-options/time-unit/time-units.asciidoc index fa1fdd4df2c..ab1a39c0f18 100644 --- a/docs/asciidoc/common-options/time-unit/time-units.asciidoc +++ b/docs/asciidoc/common-options/time-unit/time-units.asciidoc @@ -17,7 +17,7 @@ NEST uses `Time` to strongly type this and there are several ways to construct o The most straight forward way to construct a `Time` is through its constructor -[source,csharp,method-name="constructor"] +[source,csharp,method="constructor"] ---- var unitString = new Time("2d"); var unitComposed = new Time(2, Nest.TimeUnit.Day); @@ -37,7 +37,7 @@ When serializing Time constructed from the expression will be serialized to a time unit string composed of the factor and interval e.g. `2d` -[source,csharp,method-name="constructor"] +[source,csharp,method="constructor"] ---- Expect("2d") .WhenSerializing(unitString) @@ -48,7 +48,7 @@ Expect("2d") The `Milliseconds` property on `Time` is calculated even when not using the constructor that takes a double -[source,csharp,method-name="constructor"] +[source,csharp,method="constructor"] ---- unitMilliseconds.Milliseconds.Should().Be(1000*60*60*24*2); @@ -61,7 +61,7 @@ unitString.Milliseconds.Should().Be(1000*60*60*24*2); Alternatively to using the constructor, `string`, `TimeSpan` and `double` can be implicitly converted to `Time` -[source,csharp,method-name="implicitconversion"] +[source,csharp,method="implicitconversion"] ---- Time oneAndHalfYear = "1.5y"; @@ -76,7 +76,7 @@ Expect("2w").WhenSerializing(twoWeeks); Expect("2d").WhenSerializing(twoDays); ---- -[source,csharp,method-name="equalityandcomparable"] +[source,csharp,method="equalityandcomparable"] ---- Time oneAndHalfYear = "1.5y"; @@ -88,7 +88,7 @@ Time twoDays = 1000*60*60*24*2; Again, the `Milliseconds` property is calculated on `Time`, allowing you to do comparisons -[source,csharp,method-name="equalityandcomparable"] +[source,csharp,method="equalityandcomparable"] ---- oneAndHalfYear.Milliseconds.Should().BeGreaterThan(1); @@ -113,7 +113,7 @@ twoDays.Should().BeLessThan(twoWeeks); And assert equality -[source,csharp,method-name="equalityandcomparable"] +[source,csharp,method="equalityandcomparable"] ---- twoDays.Should().Be(new Time("2d")); @@ -129,7 +129,7 @@ twoDays.Should().Be(new Time("2d")); Time units are specified as a union of either a `DateInterval` or `Time`, both of which implicitly convert to the `Union` of these two. -[source,csharp,method-name="usinginterval"] +[source,csharp,method="usinginterval"] ---- Expect("month").WhenSerializing>(DateInterval.Month); diff --git a/docs/asciidoc/index.asciidoc b/docs/asciidoc/index.asciidoc index 5888beec998..1143c6ad30f 100644 --- a/docs/asciidoc/index.asciidoc +++ b/docs/asciidoc/index.asciidoc @@ -147,6 +147,14 @@ include::aggregations/pipeline/serial-differencing/serial-differencing-aggregati include::aggregations/pipeline/sum-bucket/sum-bucket-aggregation-usage.asciidoc[] +include::analysis/analyzers/analyzer-usage.asciidoc[] + +include::analysis/char-filters/char-filter-usage.asciidoc[] + +include::analysis/token-filters/token-filter-usage.asciidoc[] + +include::analysis/tokenizers/tokenizer-usage.asciidoc[] + include::client-concepts/connection-pooling/exceptions/unexpected-exceptions.asciidoc[] include::client-concepts/connection-pooling/exceptions/unrecoverable-exceptions.asciidoc[] @@ -175,13 +183,175 @@ include::common-options/date-math/date-math-expressions.asciidoc[] include::common-options/time-unit/time-units.asciidoc[] -include::document/multiple/bulk/bulk-api.asciidoc[] - include::query-dsl/bool-dsl/bool-dsl.asciidoc[] +include::query-dsl/bool-dsl/operators/and-operator-usage.asciidoc[] + +include::query-dsl/bool-dsl/operators/not-operator-usage.asciidoc[] + +include::query-dsl/bool-dsl/operators/or-operator-usage.asciidoc[] + +include::query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc[] + include::query-dsl/compound/and/and-query-usage.asciidoc[] +include::query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc[] + +include::query-dsl/compound/bool/bool-query-usage.asciidoc[] + +include::query-dsl/compound/boosting/boosting-query-usage.asciidoc[] + +include::query-dsl/compound/constant-score/constant-score-query-usage.asciidoc[] + +include::query-dsl/compound/dismax/dismax-query-usage.asciidoc[] + +include::query-dsl/compound/filtered/filtered-query-usage.asciidoc[] + +include::query-dsl/compound/function-score/function-score-query-usage.asciidoc[] + +include::query-dsl/compound/indices/indices-no-match-query-usage.asciidoc[] + +include::query-dsl/compound/indices/indices-query-usage.asciidoc[] + +include::query-dsl/compound/limit/limit-query-usage.asciidoc[] + +include::query-dsl/compound/not/not-query-usage.asciidoc[] + +include::query-dsl/compound/or/or-query-usage.asciidoc[] + +include::query-dsl/full-text/common-terms/common-terms-usage.asciidoc[] + +include::query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc[] + +include::query-dsl/full-text/match/match-phrase-usage.asciidoc[] + +include::query-dsl/full-text/match/match-usage.asciidoc[] + +include::query-dsl/full-text/multi-match/multi-match-usage.asciidoc[] + +include::query-dsl/full-text/query-string/query-string-usage.asciidoc[] + +include::query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc[] + +include::query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc[] + include::query-dsl/geo/distance/distance-units.asciidoc[] +include::query-dsl/geo/distance/geo-distance-query-usage.asciidoc[] + +include::query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc[] + +include::query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc[] + +include::query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc[] + +include::query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc[] + +include::query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc[] + +include::query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc[] + +include::query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc[] + +include::query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc[] + +include::query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc[] + +include::query-dsl/geo/shape/point/geo-point-usage.asciidoc[] + +include::query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc[] + +include::query-dsl/joining/has-child/has-child-query-usage.asciidoc[] + +include::query-dsl/joining/has-parent/has-parent-query-usage.asciidoc[] + +include::query-dsl/joining/nested/nested-query-usage.asciidoc[] + +include::query-dsl/nest-specific/raw/raw-combine-usage.asciidoc[] + +include::query-dsl/nest-specific/raw/raw-query-usage.asciidoc[] + +include::query-dsl/span/container/span-containing-query-usage.asciidoc[] + +include::query-dsl/span/first/span-first-query-usage.asciidoc[] + +include::query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc[] + +include::query-dsl/span/near/span-near-query-usage.asciidoc[] + +include::query-dsl/span/not/span-not-query-usage.asciidoc[] + +include::query-dsl/span/or/span-or-query-usage.asciidoc[] + +include::query-dsl/span/term/span-term-query-usage.asciidoc[] + +include::query-dsl/span/within/span-within-query-usage.asciidoc[] + +include::query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc[] + +include::query-dsl/specialized/script/script-query-usage.asciidoc[] + +include::query-dsl/specialized/template/template-query-usage.asciidoc[] + +include::query-dsl/term-level/exists/exists-query-usage.asciidoc[] + +include::query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc[] + +include::query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc[] + +include::query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc[] + +include::query-dsl/term-level/ids/ids-query-usage.asciidoc[] + +include::query-dsl/term-level/missing/missing-query-usage.asciidoc[] + +include::query-dsl/term-level/prefix/prefix-query-usage.asciidoc[] + +include::query-dsl/term-level/range/date-range-query-usage.asciidoc[] + +include::query-dsl/term-level/range/numeric-range-query-usage.asciidoc[] + +include::query-dsl/term-level/range/term-range-query-usage.asciidoc[] + +include::query-dsl/term-level/regexp/regexp-query-usage.asciidoc[] + +include::query-dsl/term-level/term/term-query-usage.asciidoc[] + +include::query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc[] + +include::query-dsl/term-level/terms/terms-query-usage.asciidoc[] + +include::query-dsl/term-level/type/type-query-usage.asciidoc[] + +include::query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc[] + +include::search/request/explain-usage.asciidoc[] + +include::search/request/fielddata-fields-usage.asciidoc[] + +include::search/request/fields-usage.asciidoc[] + +include::search/request/from-and-size-usage.asciidoc[] + +include::search/request/highlighting-usage.asciidoc[] + +include::search/request/index-boost-usage.asciidoc[] + +include::search/request/inner-hits-usage.asciidoc[] + +include::search/request/min-score-usage.asciidoc[] + +include::search/request/post-filter-usage.asciidoc[] + +include::search/request/query-usage.asciidoc[] + +include::search/request/script-fields-usage.asciidoc[] + +include::search/request/sort-usage.asciidoc[] + +include::search/request/source-filtering-usage.asciidoc[] + +include::search/request/suggest-usage.asciidoc[] + include::search/suggesters/suggest-api.asciidoc[] diff --git a/docs/asciidoc/low-level.asciidoc b/docs/asciidoc/low-level.asciidoc new file mode 100644 index 00000000000..5f282702bb0 --- /dev/null +++ b/docs/asciidoc/low-level.asciidoc @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc index 8ada21048bc..eea20759675 100644 --- a/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc +++ b/docs/asciidoc/query-dsl/bool-dsl/bool-dsl.asciidoc @@ -9,7 +9,7 @@ Writing boolean queries can grow verbose rather quickly when using the query DSL. For example, take a single {ref_current}/query-dsl-bool-query.html[`bool` query] with only two clauses -[source,csharp,method-name="verboseway"] +[source,csharp,method="verboseway"] ---- var searchResults = this.Client.Search(s => s .Query(q => q @@ -34,7 +34,7 @@ image::{imagesdir}/hadouken-indentation.jpg[dead indent] For this reason, NEST introduces **operator overloading** so complex bool queries become easier to write. The previous example now becomes the following with the fluent API -[source,csharp,method-name="usingoperator"] +[source,csharp,method="usingoperator"] ---- var searchResults = this.Client.Search(s => s .Query(q => q.Term(p => p.Name, "x") || q.Term(p => p.Name, "y")) @@ -43,7 +43,7 @@ var searchResults = this.Client.Search(s => s or, using the object initializer syntax -[source,csharp,method-name="usingoperator"] +[source,csharp,method="usingoperator"] ---- searchResults = this.Client.Search(new SearchRequest { @@ -98,7 +98,7 @@ bool |___term .... -[source,csharp,method-name="joinsmustwithmustnot"] +[source,csharp,method="joinsmustwithmustnot"] ---- Assert( q => q.Query() && q.Query() && q.Query() && !q.Query(), @@ -156,7 +156,7 @@ Here we demonstrate that two locked `bool` queries are not combined neither are two `bool` queries where either the left or the right query is locked -[source,csharp,method-name="assertdoesnotjoinontolockedbool"] +[source,csharp,method="assertdoesnotjoinontolockedbool"] ---- c.Bool.Should.Should().HaveCount(2); @@ -167,7 +167,7 @@ nestedBool.Bool.Should.Should().HaveCount(1); nestedBool.Bool.Name.Should().Be(firstName); ---- -[source,csharp,method-name="assert"] +[source,csharp,method="assert"] ---- assert(fluent.InvokeQuery(new QueryContainerDescriptor())); diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc new file mode 100644 index 00000000000..666762a5b2d --- /dev/null +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/and-operator-usage.asciidoc @@ -0,0 +1,93 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp,method="combiningmanyusingaggregate"] +---- +var lotsOfAnds = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q && Query, q => q); + +LotsOfAnds(lotsOfAnds); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +---- +QueryContainer container = null; + +container &= Query; + +LotsOfAnds(container); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +---- +var container = new QueryContainer(); + +container &= Query; + +LotsOfAnds(container); +---- + +[source,csharp,method="lotsofands"] +---- +lotsOfAnds.Should().NotBeNull(); + +lotsOfAnds.Bool.Should().NotBeNull(); + +lotsOfAnds.Bool.Must.Should().NotBeEmpty().And.HaveCount(100); +---- + +[source,csharp,method="and"] +---- +ReturnsBool(Query && Query, q => q.Query() && q.Query(), b => +{ + b.Must.Should().NotBeEmpty().And.HaveCount(2); + b.Should.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); +}); +b.Must.Should().NotBeEmpty().And.HaveCount(2); +b.Should.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.Filter.Should().BeNull(); +ReturnsBool(Query && Query && ConditionlessQuery, q => q.Query() && q.Query() && q.ConditionlessQuery(), b => +{ + b.Must.Should().NotBeEmpty().And.HaveCount(2); + b.Should.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); +}); +b.Must.Should().NotBeEmpty().And.HaveCount(2); +b.Should.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.Filter.Should().BeNull(); +ReturnsSingleQuery(Query && ConditionlessQuery, q => q.Query() && q.ConditionlessQuery(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(ConditionlessQuery && Query, q => q.ConditionlessQuery() && q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(Query && NullQuery, q => q.Query() && q.NullQuery(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(NullQuery && Query, q=> q.NullQuery() && q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(ConditionlessQuery && ConditionlessQuery && ConditionlessQuery && Query, + q => q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery( + NullQuery && NullQuery && ConditionlessQuery && Query, + q=>q.NullQuery() && q.NullQuery() && q.ConditionlessQuery() && q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsNull(NullQuery && ConditionlessQuery, q=> q.NullQuery() && q.ConditionlessQuery()); +ReturnsNull(ConditionlessQuery && NullQuery, q=>q.ConditionlessQuery() && q.NullQuery()); +ReturnsNull(ConditionlessQuery && ConditionlessQuery, q=>q.ConditionlessQuery() && q.ConditionlessQuery()); +ReturnsNull( + ConditionlessQuery && ConditionlessQuery && ConditionlessQuery && ConditionlessQuery, + q=>q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() + +); +ReturnsNull( + NullQuery && ConditionlessQuery && ConditionlessQuery && ConditionlessQuery, + q=>q.NullQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() && q.ConditionlessQuery() +); +---- + diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc new file mode 100644 index 00000000000..a23db433fe2 --- /dev/null +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/not-operator-usage.asciidoc @@ -0,0 +1,100 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp,method="combiningmanyusingaggregate"] +---- +var lotsOfNots = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q || Query, q => q); + +LotsOfNots(lotsOfNots); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +---- +QueryContainer container = null; + +container |= Query; + +LotsOfNots(container); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +---- +var container = new QueryContainer(); + +container |= Query; + +LotsOfNots(container); +---- + +[source,csharp,method="lotsofnots"] +---- +lotsOfNots.Should().NotBeNull(); + +lotsOfNots.Bool.Should().NotBeNull(); + +lotsOfNots.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); +---- + +[source,csharp,method="not"] +---- +ReturnsBool(!Query && !Query, q => !q.Query() && !q.Query(), b => +{ + b.MustNot.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.Should.Should().BeNull(); + b.Filter.Should().BeNull(); +}); +b.MustNot.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.Should.Should().BeNull(); +b.Filter.Should().BeNull(); +ReturnsBool(!Query || !Query || !ConditionlessQuery, q => !q.Query() || !q.Query() || !q.ConditionlessQuery(), b => +{ + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); + foreach (IQueryContainer q in b.Should) + { + q.Bool.Should().NotBeNull(); + q.Bool.MustNot.Should().NotBeEmpty().And.HaveCount(1); + } +}); +b.Should.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.Filter.Should().BeNull(); +q.Bool.Should().NotBeNull(); +q.Bool.MustNot.Should().NotBeEmpty().And.HaveCount(1); +ReturnsSingleQuery(!Query || !ConditionlessQuery, q => !q.Query() || !q.ConditionlessQuery(), + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(!ConditionlessQuery || !Query, q => !q.ConditionlessQuery() || !q.Query(), + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(!Query || !NullQuery, q => !q.Query() || !q.NullQuery(), + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(!NullQuery && !Query, q => !q.NullQuery() && !q.Query(), + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(!ConditionlessQuery || !ConditionlessQuery && !ConditionlessQuery || !Query, + q => !q.ConditionlessQuery() || !q.ConditionlessQuery() && !q.ConditionlessQuery() || !q.Query(), + c => c.Bool.MustNot.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery( + !NullQuery || !NullQuery || !ConditionlessQuery || !Query, + q => !q.NullQuery() || !q.NullQuery() || !q.ConditionlessQuery() || !q.Query(), + c => c.Bool.MustNot.Should().NotBeNull()); +ReturnsNull(!NullQuery || !ConditionlessQuery, q => !q.NullQuery() || !q.ConditionlessQuery()); +ReturnsNull(!ConditionlessQuery && !NullQuery, q => !q.ConditionlessQuery() && !q.NullQuery()); +ReturnsNull(!ConditionlessQuery || !ConditionlessQuery, q => !q.ConditionlessQuery() || !q.ConditionlessQuery()); +ReturnsNull( + !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery, + q => !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() + +); +ReturnsNull( + !NullQuery || !ConditionlessQuery || !ConditionlessQuery || !ConditionlessQuery, + q => !q.NullQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() || !q.ConditionlessQuery() +); +---- + diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc new file mode 100644 index 00000000000..a0e6642785d --- /dev/null +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/or-operator-usage.asciidoc @@ -0,0 +1,104 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp,method="combiningmanyusingaggregate"] +---- +var lotsOfOrs = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q || Query, q => q); + +LotsOfOrs(lotsOfOrs); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +---- +QueryContainer container = null; + +container |= Query; + +LotsOfOrs(container); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +---- +var container = new QueryContainer(); + +container |= Query; + +LotsOfOrs(container); +---- + +[source,csharp,method="lotsofors"] +---- +lotsOfOrs.Should().NotBeNull(); + +lotsOfOrs.Bool.Should().NotBeNull(); + +lotsOfOrs.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); +---- + +[source,csharp,method="or"] +---- +ReturnsBool(Query || Query, q => q.Query() || q.Query(), b => +{ + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); +}); +b.Should.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.Filter.Should().BeNull(); +ReturnsBool(Query || Query || ConditionlessQuery, q => q.Query() || q.Query() || q.ConditionlessQuery(), b => +{ + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); +}); +b.Should.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.Filter.Should().BeNull(); +ReturnsBool(Query || Query || ConditionlessQuery, q => q.Query() || q.Query() || q.ConditionlessQuery(), b => +{ + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.Filter.Should().BeNull(); +}); +b.Should.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.Filter.Should().BeNull(); +ReturnsSingleQuery(Query || ConditionlessQuery, q => q.Query() || q.ConditionlessQuery(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(ConditionlessQuery || Query, q => q.ConditionlessQuery() || q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(Query || NullQuery, q => q.Query() || q.NullQuery(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(NullQuery || Query, q=> q.NullQuery() || q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery(ConditionlessQuery || ConditionlessQuery || ConditionlessQuery || Query, + q => q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsSingleQuery( + NullQuery || NullQuery || ConditionlessQuery || Query, + q=>q.NullQuery() || q.NullQuery() || q.ConditionlessQuery() || q.Query(), + c => c.Term.Value.Should().NotBeNull()); +ReturnsNull(NullQuery || ConditionlessQuery, q=> q.NullQuery() || q.ConditionlessQuery()); +ReturnsNull(ConditionlessQuery || NullQuery, q=>q.ConditionlessQuery() || q.NullQuery()); +ReturnsNull(ConditionlessQuery || ConditionlessQuery, q=>q.ConditionlessQuery() || q.ConditionlessQuery()); +ReturnsNull( + ConditionlessQuery || ConditionlessQuery || ConditionlessQuery || ConditionlessQuery, + q=>q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() + +); +ReturnsNull( + NullQuery || ConditionlessQuery || ConditionlessQuery || ConditionlessQuery, + q=>q.NullQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() || q.ConditionlessQuery() +); +---- + diff --git a/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc new file mode 100644 index 00000000000..56c66b0128f --- /dev/null +++ b/docs/asciidoc/query-dsl/bool-dsl/operators/unary-add-operator-usage.asciidoc @@ -0,0 +1,111 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp,method="combiningmanyusingaggregate"] +---- +var lotsOfUnaryAdds = Enumerable.Range(0, 100).Aggregate(new QueryContainer(), (q, c) => q && +Query, q => q); + +LotsOfUnaryAdds(lotsOfUnaryAdds); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithnull"] +---- +QueryContainer container = null; + +container &= +Query; + +LotsOfUnaryAdds(container); +---- + +[source,csharp,method="combiningmanyusingforeachinitializingwithdefault"] +---- +var container = new QueryContainer(); + +container &= +Query; + +LotsOfUnaryAdds(container); +---- + +[source,csharp,method="lotsofunaryadds"] +---- +lotsOfUnaryAdds.Should().NotBeNull(); + +lotsOfUnaryAdds.Bool.Should().NotBeNull(); + +lotsOfUnaryAdds.Bool.Filter.Should().NotBeEmpty().And.HaveCount(100); +---- + +[source,csharp,method="combindingmanyboolfiltersusingorsshouldflatten"] +---- +var container = new QueryContainer(); + +container |= +Query; + +var c = container as IQueryContainer; + +c.Bool.Should.Should().NotBeEmpty().And.HaveCount(100); +---- + +[source,csharp,method="unaryadd"] +---- +ReturnsBool(+Query && +Query, q => +q.Query() && +q.Query(), b => +{ + b.Filter.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.Should.Should().BeNull(); + b.MustNot.Should().BeNull(); +}); +b.Filter.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.Should.Should().BeNull(); +b.MustNot.Should().BeNull(); +ReturnsBool(+Query || +Query || +ConditionlessQuery, q => +q.Query() || +q.Query() || +q.ConditionlessQuery(), b => +{ + b.Should.Should().NotBeEmpty().And.HaveCount(2); + b.Must.Should().BeNull(); + b.MustNot.Should().BeNull(); + b.MustNot.Should().BeNull(); + foreach (IQueryContainer q in b.Should) + { + q.Bool.Should().NotBeNull(); + q.Bool.Filter.Should().NotBeEmpty().And.HaveCount(1); + } +}); +b.Should.Should().NotBeEmpty().And.HaveCount(2); +b.Must.Should().BeNull(); +b.MustNot.Should().BeNull(); +b.MustNot.Should().BeNull(); +q.Bool.Should().NotBeNull(); +q.Bool.Filter.Should().NotBeEmpty().And.HaveCount(1); +ReturnsSingleQuery(+Query || +ConditionlessQuery, q => +q.Query() || +q.ConditionlessQuery(), + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(+ConditionlessQuery || +Query, q => +q.ConditionlessQuery() || +q.Query(), + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(+Query || +NullQuery, q => +q.Query() || +q.NullQuery(), + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(+NullQuery && +Query, q => +q.NullQuery() && +q.Query(), + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery(+ConditionlessQuery || +ConditionlessQuery && +ConditionlessQuery || +Query, + q => +q.ConditionlessQuery() || +q.ConditionlessQuery() && +q.ConditionlessQuery() || +q.Query(), + c => c.Bool.Filter.Should().NotBeNull().And.HaveCount(1)); +ReturnsSingleQuery( + +NullQuery || +NullQuery || +ConditionlessQuery || +Query, + q => +q.NullQuery() || +q.NullQuery() || +q.ConditionlessQuery() || +q.Query(), + c => c.Bool.Filter.Should().NotBeNull()); +ReturnsNull(+NullQuery || +ConditionlessQuery, q => +q.NullQuery() || +q.ConditionlessQuery()); +ReturnsNull(+ConditionlessQuery && +NullQuery, q => +q.ConditionlessQuery() && +q.NullQuery()); +ReturnsNull(+ConditionlessQuery || +ConditionlessQuery, q => +q.ConditionlessQuery() || +q.ConditionlessQuery()); +ReturnsNull( + +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery, + q => +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() + +); +ReturnsNull( + +NullQuery || +ConditionlessQuery || +ConditionlessQuery || +ConditionlessQuery, + q => +q.NullQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() || +q.ConditionlessQuery() +); +---- + diff --git a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc index 177cc9aa865..4e12c047d43 100644 --- a/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc +++ b/docs/asciidoc/query-dsl/compound/and/and-query-usage.asciidoc @@ -4,7 +4,7 @@ :imagesdir: ../../../images -[source,javascript,method-name="queryjson"] +[source,javascript,method="queryjson"] .Example json output ---- { @@ -29,7 +29,7 @@ === Object Initializer Syntax Example -[source,csharp,method-name="queryinitializer"] +[source,csharp,method="queryinitializer"] ---- new AndQuery() { diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc new file mode 100644 index 00000000000..b9bd6e4a5b2 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/bool/bool-dsl-complex-query-usage.asciidoc @@ -0,0 +1,135 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp,method="queryjson"] +---- +new + { +@bool = new +{ + should = new object[] { + new { + @bool = new { + must = new [] { + new { term = new { x = new { value = "y" } } }, + new { term = new { x = new { value = "y" } } } + } + } + }, + new { + @bool = new { + must = new object[] { + new { + @bool = new { + should = new object [] { + new { + @bool = new { + filter = new [] { + new { term = new { x = new { value = "y" } } } + } + } + }, + new { + @bool = new { + filter = new [] { + new { term = new { x = new { value = "y" } } } + } + } + }, + new { + @bool = new { + must_not = new [] { + new { term = new { x = new { value = "y" } } }, + new { term = new { x = new { value = "y" } } } + } + } + }, + new { term = new { x = new { value = "y" } } }, + new { term = new { x = new { value = "y" } } }, + new { term = new { x = new { value = "y" } } } + } + } + }, + base.QueryJson, + } + } + } + } +} + } +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +Query && Query +//second bool +|| ( + //complex nested bool + (+Query || +Query || !Query && (!Query && !ConditionlessQuery)) + // simple nested or + && (Query || Query || Query) + //all conditionless bool + && (NullQuery || +ConditionlessQuery || !ConditionlessQuery) + // actual bool query + && (base.QueryInitializer)) +---- + +[source,csharp,method="assertshape"] +---- +container.Bool.Should().NotBeNull(); + +container.Bool.Should.Should().HaveCount(2); + +container.Bool.MustNot.Should().BeNull(); + +container.Bool.Filter.Should().BeNull(); + +container.Bool.Must.Should().BeNull(); + +var firstBool = (container.Bool.Should.First() as IQueryContainer)?.Bool; + +firstBool.Should().NotBeNull(); + +firstBool.Must.Should().HaveCount(2); + +firstBool.MustNot.Should().BeNull(); + +firstBool.Filter.Should().BeNull(); + +firstBool.Should.Should().BeNull(); + +var secondBool = (container.Bool.Should.Last() as IQueryContainer)?.Bool; + +secondBool.Should().NotBeNull(); + +secondBool.Must.Should().HaveCount(2); //the last bool query was all conditionless + +secondBool.MustNot.Should().BeNull(); + +secondBool.Filter.Should().BeNull(); + +secondBool.Should.Should().BeNull(); + +var complexBool = (secondBool.Must.First() as IQueryContainer)?.Bool; + +complexBool.Should().NotBeNull(); + +complexBool.Should.Should().HaveCount(6); + +var mustNotsBool = (complexBool.Should.Cast().FirstOrDefault(q => q.Bool != null && q.Bool.MustNot != null))?.Bool; + +mustNotsBool.Should().NotBeNull(); + +mustNotsBool.MustNot.Should().HaveCount(2); //one of the three must nots was conditionless +---- + +[source,csharp,method="asssertshape"] +---- +this.AssertShape(this.QueryInitializer); +---- + diff --git a/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc new file mode 100644 index 00000000000..2e862c0ef25 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/bool/bool-query-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "bool": { + "must": [ + { + "match_all": {} + } + ], + "must_not": [ + { + "match_all": {} + } + ], + "should": [ + { + "match_all": {} + } + ], + "filter": [ + { + "match_all": {} + } + ], + "minimum_should_match": 1, + "boost": 2.0 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new BoolQuery() +{ + MustNot = new QueryContainer[] { new MatchAllQuery() }, + Should = new QueryContainer[] { new MatchAllQuery() }, + Must = new QueryContainer[] { new MatchAllQuery() }, + Filter = new QueryContainer[] { new MatchAllQuery() }, + MinimumShouldMatch = 1, + Boost = 2 +} +---- + diff --git a/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc new file mode 100644 index 00000000000..5e5b632f003 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/boosting/boosting-query-usage.asciidoc @@ -0,0 +1,42 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "boosting": { + "_name": "named_query", + "boost": 1.1, + "negative": { + "match_all": { + "_name": "query" + } + }, + "negative_boost": 1.12, + "positive": { + "match_all": { + "_name": "filter" + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new BoostingQuery() + { +Name = "named_query", +Boost = 1.1, +PositiveQuery = new MatchAllQuery { Name ="filter" }, +NegativeQuery= new MatchAllQuery() { Name = "query" }, +NegativeBoost = 1.12 + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc new file mode 100644 index 00000000000..be285d03cd1 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/constant-score/constant-score-query-usage.asciidoc @@ -0,0 +1,34 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "constant_score": { + "_name": "named_query", + "boost": 1.1, + "filter": { + "match_all": { + "_name": "filter" + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new ConstantScoreQuery() + { +Name = "named_query", +Boost = 1.1, +Filter = new MatchAllQuery { Name = "filter" }, + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc new file mode 100644 index 00000000000..8367b124d5c --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/dismax/dismax-query-usage.asciidoc @@ -0,0 +1,46 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "dis_max": { + "_name": "named_query", + "boost": 1.1, + "queries": [ + { + "match_all": { + "_name": "query1" + } + }, + { + "match_all": { + "_name": "query2" + } + } + ], + "tie_breaker": 1.11 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new DisMaxQuery() + { +Name = "named_query", +Boost = 1.1, +TieBreaker = 1.11, +Queries = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, +} + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc new file mode 100644 index 00000000000..2316168c8f2 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/filtered/filtered-query-usage.asciidoc @@ -0,0 +1,40 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "filtered": { + "_name": "named_query", + "boost": 1.1, + "filter": { + "match_all": { + "_name": "filter" + } + }, + "query": { + "match_all": { + "_name": "query" + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new FilteredQuery() + { +Name = "named_query", +Boost = 1.1, +Filter = new MatchAllQuery { Name ="filter" }, +Query = new MatchAllQuery() { Name = "query" }, + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc new file mode 100644 index 00000000000..62995ef5d37 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/function-score/function-score-query-usage.asciidoc @@ -0,0 +1,115 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "function_score": { + "_name": "named_query", + "boost": 1.1, + "boost_mode": "multiply", + "functions": [ + { + "exp": { + "numberOfCommits": { + "origin": 1.0, + "scale": 0.1, + "decay": 0.5 + } + }, + "weight": 2.1 + }, + { + "gauss": { + "lastActivity": { + "origin": "now", + "scale": "1d", + "decay": 0.5 + } + } + }, + { + "linear": { + "location": { + "origin": { + "lat": 70.0, + "lon": -70.0 + }, + "scale": "1.0mi" + }, + "multi_value_mode": "avg" + } + }, + { + "field_value_factor": { + "field": "x", + "factor": 1.1, + "missing": 0.1, + "modifier": "ln" + } + }, + { + "random_score": { + "seed": 1337 + } + }, + { + "random_score": { + "seed": "randomstring" + } + }, + { + "weight": 1.0 + }, + { + "script_score": { + "script": { + "file": "x" + } + } + } + ], + "max_boost": 20.0, + "min_score": 1.0, + "query": { + "match_all": {} + }, + "score_mode": "sum" + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new FunctionScoreQuery() + { +Name = "named_query", +Boost = 1.1, +Query = new MatchAllQuery { }, +BoostMode = FunctionBoostMode.Multiply, +ScoreMode = FunctionScoreMode.Sum, +MaxBoost = 20.0, +MinScore = 1.0, +Functions = new List +{ + new ExponentialDecayFunction { Origin = 1.0, Decay = 0.5, Field = Field(p=>p.NumberOfCommits), Scale = 0.1, Weight = 2.1 }, + new GaussDateDecayFunction { Origin = DateMath.Now, Field = Field(p=>p.LastActivity), Decay = 0.5, Scale = TimeSpan.FromDays(1) }, + new LinearGeoDecayFunction { Origin = new GeoLocation(70, -70), Field = Field(p=>p.Location), Scale = Distance.Miles(1), MultiValueMode = MultiValueMode.Average }, + new FieldValueFactorFunction + { + Field = "x", Factor = 1.1, Missing = 0.1, Modifier = FieldValueFactorModifier.Ln + }, + new RandomScoreFunction { Seed = 1337 }, + new RandomScoreFunction { Seed = "randomstring" }, + new WeightFunction { Weight = 1.0}, + new ScriptScoreFunction { Script = new ScriptQuery { File = "x" } } +} + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc new file mode 100644 index 00000000000..4d394c91250 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/indices/indices-no-match-query-usage.asciidoc @@ -0,0 +1,38 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "indices": { + "_name": "named_query", + "boost": 1.1, + "indices": [ + "_all" + ], + "no_match_query": "all", + "query": { + "match_all": {} + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new IndicesQuery() + { +Name = "named_query", +Boost = 1.1, +Indices = Nest.Indices.All, +Query = new MatchAllQuery(), +NoMatchQuery = new NoMatchQueryContainer { Shortcut = NoMatchShortcut.All } + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc new file mode 100644 index 00000000000..bf06e671e27 --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/indices/indices-query-usage.asciidoc @@ -0,0 +1,43 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "indices": { + "_name": "named_query", + "boost": 1.1, + "indices": [ + "project" + ], + "no_match_query": { + "match_all": { + "_name": "no_match" + } + }, + "query": { + "match_all": {} + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new IndicesQuery() + { +Name = "named_query", +Boost = 1.1, +Indices = Index(), +Query = new MatchAllQuery(), +NoMatchQuery = new MatchAllQuery { Name ="no_match" } + + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc new file mode 100644 index 00000000000..068c28c9e5a --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/limit/limit-query-usage.asciidoc @@ -0,0 +1,30 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "limit": { + "_name": "named_query", + "boost": 1.1, + "limit": 100 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new LimitQuery + { +Name = "named_query", +Boost = 1.1, +Limit = 100 + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc new file mode 100644 index 00000000000..f98832a1ccb --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/not/not-query-usage.asciidoc @@ -0,0 +1,44 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "not": { + "_name": "named_query", + "boost": 1.1, + "filters": [ + { + "match_all": { + "_name": "query1" + } + }, + { + "match_all": { + "_name": "query2" + } + } + ] + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new NotQuery() + { +Name = "named_query", +Boost = 1.1, +Filters = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, +} + } +---- + diff --git a/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc new file mode 100644 index 00000000000..06b1dbbf33d --- /dev/null +++ b/docs/asciidoc/query-dsl/compound/or/or-query-usage.asciidoc @@ -0,0 +1,44 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "or": { + "_name": "named_query", + "boost": 1.1, + "filters": [ + { + "match_all": { + "_name": "query1" + } + }, + { + "match_all": { + "_name": "query2" + } + } + ] + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new OrQuery() + { +Name = "named_query", +Boost = 1.1, +Filters = new QueryContainer[] { + new MatchAllQuery() { Name = "query1" }, + new MatchAllQuery() { Name = "query2" }, +} + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc new file mode 100644 index 00000000000..355154730ec --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/common-terms/common-terms-usage.asciidoc @@ -0,0 +1,45 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "common": { + "description": { + "_name": "named_query", + "boost": 1.1, + "query": "nelly the elephant not as a", + "cutoff_frequency": 0.001, + "low_freq_operator": "or", + "high_freq_operator": "and", + "minimum_should_match": 1, + "analyzer": "standard", + "disable_coord": true + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new CommonTermsQuery() + { +Field = Field(p => p.Description), +Analyzer = "standard", +Boost = 1.1, +CutoffFrequency = 0.001, +DisableCoord = true, +HighFrequencyOperator = Operator.And, +LowFrequencyOperator = Operator.Or, +MinimumShouldMatch = 1, +Name = "named_query", +Query = "nelly the elephant not as a" + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc new file mode 100644 index 00000000000..f3ecf1e3413 --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-prefix-usage.asciidoc @@ -0,0 +1,56 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "match": { + "description": { + "_name": "named_query", + "boost": 1.1, + "query": "hello worl", + "analyzer": "standard", + "fuzzy_rewrite": "constant_score_boolean", + "fuzziness": "AUTO", + "fuzzy_transpositions": true, + "cutoff_frequency": 0.001, + "prefix_length": 2, + "max_expansions": 2, + "slop": 2, + "lenient": true, + "minimum_should_match": 2, + "operator": "or", + "type": "phrase_prefix" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new MatchPhrasePrefixQuery + { +Field = Field(p => p.Description), +Analyzer = "standard", +Boost = 1.1, +Name = "named_query", +CutoffFrequency = 0.001, +Query = "hello worl", +Fuzziness = Fuzziness.Auto, +FuzzyTranspositions = true, +MinimumShouldMatch = 2, +FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, +MaxExpansions = 2, +Slop = 2, +Lenient = true, +Operator = Operator.Or, +PrefixLength = 2 + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc new file mode 100644 index 00000000000..4417d715009 --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/match/match-phrase-usage.asciidoc @@ -0,0 +1,56 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "match": { + "description": { + "_name": "named_query", + "boost": 1.1, + "query": "hello world", + "analyzer": "standard", + "fuzzy_rewrite": "constant_score_boolean", + "fuzziness": "AUTO", + "fuzzy_transpositions": true, + "cutoff_frequency": 0.001, + "prefix_length": 2, + "max_expansions": 2, + "slop": 2, + "lenient": true, + "minimum_should_match": 2, + "operator": "or", + "type": "phrase" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new MatchPhraseQuery + { +Field = Field(p=>p.Description), +Analyzer = "standard", +Boost = 1.1, +Name = "named_query", +CutoffFrequency = 0.001, +Query = "hello world", +Fuzziness = Fuzziness.Auto, +FuzzyTranspositions = true, +MinimumShouldMatch = 2, +FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, +MaxExpansions = 2, +Slop = 2, +Lenient = true, +Operator = Operator.Or, +PrefixLength = 2 + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc new file mode 100644 index 00000000000..5bfcba2737b --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/match/match-usage.asciidoc @@ -0,0 +1,55 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "match": { + "description": { + "_name": "named_query", + "boost": 1.1, + "query": "hello world", + "analyzer": "standard", + "fuzzy_rewrite": "constant_score_boolean", + "fuzziness": "AUTO", + "fuzzy_transpositions": true, + "cutoff_frequency": 0.001, + "prefix_length": 2, + "max_expansions": 2, + "slop": 2, + "lenient": true, + "minimum_should_match": 2, + "operator": "or" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new MatchQuery + { +Field = Field(p=>p.Description), +Analyzer = "standard", +Boost = 1.1, +Name = "named_query", +CutoffFrequency = 0.001, +Query = "hello world", +Fuzziness = Fuzziness.Auto, +FuzzyTranspositions = true, +MinimumShouldMatch = 2, +FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, +MaxExpansions = 2, +Slop = 2, +Lenient = true, +Operator = Operator.Or, +PrefixLength = 2 + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc new file mode 100644 index 00000000000..58a5ac6be80 --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/multi-match/multi-match-usage.asciidoc @@ -0,0 +1,59 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "multi_match": { + "_name": "named_query", + "boost": 1.1, + "query": "hello world", + "analyzer": "standard", + "fuzzy_rewrite": "constant_score_boolean", + "fuzziness": "AUTO", + "cutoff_frequency": 0.001, + "prefix_length": 2, + "max_expansions": 2, + "slop": 2, + "lenient": true, + "tie_breaker": 1.1, + "minimum_should_match": 2, + "operator": "or", + "fields": [ + "description", + "myOtherField" + ], + "zero_terms_query": "all" + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new MultiMatchQuery + { +Fields = Field(p=>p.Description).And("myOtherField"), +Query = "hello world", +Analyzer = "standard", +Boost = 1.1, +Slop = 2, +Fuzziness = Fuzziness.Auto, +PrefixLength = 2, +MaxExpansions = 2, +Operator = Operator.Or, +MinimumShouldMatch = 2, +FuzzyRewrite = RewriteMultiTerm.ConstantScoreBoolean, +TieBreaker = 1.1, +CutoffFrequency = 0.001, +Lenient = true, +ZeroTermsQuery = ZeroTermsQuery.All, +Name = "named_query", + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc new file mode 100644 index 00000000000..0922949d9c4 --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/query-string/query-string-usage.asciidoc @@ -0,0 +1,81 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "query_string": { + "_name": "named_query", + "boost": 1.1, + "query": "hello world", + "default_field": "description", + "default_operator": "or", + "analyzer": "standard", + "quote_analyzer": "quote-an", + "allow_leading_wildcard": true, + "lowercase_expanded_terms": true, + "enable_position_increments": true, + "fuzzy_max_expansions": 3, + "fuziness": "AUTO", + "fuzzy_prefix_length": 2, + "analyze_wildcard": true, + "auto_generate_phrase_queries": true, + "max_determinized_states": 2, + "minimum_should_match": 2, + "lenient": true, + "locale": "en_US", + "time_zone": "root", + "fields": [ + "description", + "myOtherField" + ], + "use_dis_max": true, + "tie_breaker": 1.2, + "rewrite": "constant_score", + "fuzzy_rewrite": "constant_score", + "quote_field_suffix": "'", + "escape": true + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new QueryStringQuery + { +Fields = Field(p=>p.Description).And("myOtherField"), +Boost = 1.1, +Name = "named_query", +Query = "hello world", +DefaultField = Field(p=>p.Description), +DefaultOperator = Operator.Or, +Analyzer = "standard", +QuoteAnalyzer = "quote-an", +AllowLeadingWildcard = true, +AutoGeneratePhraseQueries = true, +MaximumDeterminizedStates = 2, +LowercaseExpendedTerms = true, +EnablePositionIncrements = true, +Escape = true, +UseDisMax = true, +FuzzyPrefixLength = 2, +FuzzyMaxExpansions = 3, +FuzzyRewrite = RewriteMultiTerm.ConstantScore, +Rewrite = RewriteMultiTerm.ConstantScore, +Fuzziness = Fuzziness.Auto, +TieBreaker = 1.2, +AnalyzeWildcard = true, +MinimumShouldMatch = 2, +QuoteFieldSuffix = "'", +Lenient = true, +Locale = "en_US", +Timezone = "root" + } +---- + diff --git a/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc new file mode 100644 index 00000000000..e4ac092d9ce --- /dev/null +++ b/docs/asciidoc/query-dsl/full-text/simple-query-string/simple-query-string-usage.asciidoc @@ -0,0 +1,51 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "simple_query_string": { + "_name": "named_query", + "boost": 1.1, + "fields": [ + "description", + "myOtherField" + ], + "query": "hello world", + "analyzer": "standard", + "default_operator": "or", + "flags": "AND|NEAR", + "locale": "en_US", + "lowercase_expanded_terms": true, + "lenient": true, + "analyze_wildcard": true, + "minimum_should_match": "30%" + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SimpleQueryStringQuery + { +Name = "named_query", +Boost = 1.1, +Fields = Field(p=>p.Description).And("myOtherField"), +Query = "hello world", +Analyzer = "standard", +DefaultOperator = Operator.Or, +Flags = SimpleQueryStringFlags.And|SimpleQueryStringFlags.Near, +Locale = "en_US", +LowercaseExpendedTerms = true, +Lenient = true, +AnalyzeWildcard = true, +MinimumShouldMatch = "30%" + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc new file mode 100644 index 00000000000..78fab700a05 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/bounding-box/geo-bounding-box-query-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "geo_bounding_box": { + "type": "indexed", + "coerce": true, + "ignore_malformed": true, + "validation_method": "strict", + "_name": "named_query", + "boost": 1.1, + "location": { + "top_left": { + "lat": 34.0, + "lon": -34.0 + }, + "bottom_right": { + "lat": -34.0, + "lon": 34.0 + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoBoundingBoxQuery + { +Boost = 1.1, +Name = "named_query", +Field = Infer.Field(p => p.Location), +BoundingBox = new Nest.BoundingBox +{ + TopLeft = new GeoLocation(34,-34), + BottomRight = new GeoLocation(-34,34), +}, +Type = GeoExecution.Indexed, +Coerce = true, +IgnoreMalformed = true, +ValidationMethod = GeoValidationMethod.Strict + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc new file mode 100644 index 00000000000..63a33838b55 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/distance-range/geo-distance-range-query-usage.asciidoc @@ -0,0 +1,52 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "geo_distance_range": { + "gt": "200.0km", + "gte": "200.0km", + "lt": "400.0mi", + "lte": "400.0mi", + "distance_type": "arc", + "optimize_bbox": "indexed", + "coerce": true, + "ignore_malformed": true, + "validation_method": "strict", + "_name": "named_query", + "boost": 1.1, + "location": { + "lat": 40.0, + "lon": -70.0 + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoDistanceRangeQuery + { +Boost = 1.1, +Name = "named_query", +Field = Infer.Field(p=>p.Location), +DistanceType = GeoDistanceType.Arc, +Coerce = true, +GreaterThanOrEqualTo = Nest.Distance.Kilometers(200), +IgnoreMalformed = true, +GreaterThan = Nest.Distance.Kilometers(200), +LessThan = Nest.Distance.Miles(400), +Location = new GeoLocation(40, -70), +OptimizeBoundingBox = GeoOptimizeBBox.Indexed, +LessThanOrEqualTo = Nest.Distance.Miles(400), +ValidationMethod = GeoValidationMethod.Strict + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc index 5a81f873703..f4b5efc0edc 100644 --- a/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc +++ b/docs/asciidoc/query-dsl/geo/distance/distance-units.asciidoc @@ -18,7 +18,7 @@ NEST uses `Distance` to strongly type distance units and there are several ways The most straight forward way to construct a `Distance` is through its constructor -[source,csharp,method-name="constructor"] +[source,csharp,method="constructor"] ---- var unitComposed = new Nest.Distance(25); var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); @@ -26,7 +26,7 @@ var unitComposedWithUnits = new Nest.Distance(25, DistanceUnit.Meters); `Distance` serializes to a string composed of a factor and distance unit -[source,csharp,method-name="constructor"] +[source,csharp,method="constructor"] ---- Expect("25.0m") .WhenSerializing(unitComposed) @@ -38,7 +38,7 @@ Expect("25.0m") Alternatively a distance unit `string` can be assigned to a `Distance`, resulting in an implicit conversion to a new `Distance` instance. If no `DistanceUnit` is specified, the default distance unit is meters -[source,csharp,method-name="implicitconversion"] +[source,csharp,method="implicitconversion"] ---- Nest.Distance distanceString = "25"; @@ -57,28 +57,28 @@ A number of distance units are supported, from millimeters to nautical miles `mm` (Millimeters) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("2.0mm").WhenSerializing(new Nest.Distance(2, DistanceUnit.Millimeters)); ---- `cm` (Centimeters) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("123.456cm").WhenSerializing(new Nest.Distance(123.456, DistanceUnit.Centimeters)); ---- `m` (Meters) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("400.0m").WhenSerializing(new Nest.Distance(400, DistanceUnit.Meters)); ---- `km` (Kilometers) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)); ---- @@ -87,35 +87,35 @@ Expect("0.1km").WhenSerializing(new Nest.Distance(0.1, DistanceUnit.Kilometers)) `in` (Inches) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("43.23in").WhenSerializing(new Nest.Distance(43.23, DistanceUnit.Inch)); ---- `ft` (Feet) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("3.33ft").WhenSerializing(new Nest.Distance(3.33, DistanceUnit.Feet)); ---- `yd` (Yards) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("9.0yd").WhenSerializing(new Nest.Distance(9, DistanceUnit.Yards)); ---- `mi` (Miles) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("0.62mi").WhenSerializing(new Nest.Distance(0.62, DistanceUnit.Miles)); ---- `nmi` or `NM` (Nautical Miles) -[source,csharp,method-name="usingdifferentunits"] +[source,csharp,method="usingdifferentunits"] ---- Expect("45.5nmi").WhenSerializing(new Nest.Distance(45.5, DistanceUnit.NauticalMiles)); ---- diff --git a/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc new file mode 100644 index 00000000000..ac15514acd4 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/distance/geo-distance-query-usage.asciidoc @@ -0,0 +1,46 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "geo_distance": { + "_name": "named_query", + "boost": 1.1, + "distance": "200.0m", + "optimize_bbox": "memory", + "distance_type": "arc", + "coerce": true, + "ignore_malformed": true, + "validation_method": "strict", + "location": { + "lat": 34.0, + "lon": -34.0 + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoDistanceQuery + { +Boost = 1.1, +Name = "named_query", +Field = Infer.Field(p => p.Location), +DistanceType = GeoDistanceType.Arc, +Coerce = true, +Location = new GeoLocation(34,-34), +Distance = "200.0m", +IgnoreMalformed = true, +OptimizeBoundingBox = GeoOptimizeBBox.Memory, +ValidationMethod = GeoValidationMethod.Strict + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc new file mode 100644 index 00000000000..b08cd786607 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/hash-cell/geo-hash-cell-query-usage.asciidoc @@ -0,0 +1,38 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "geohash_cell": { + "_name": "named_query", + "boost": 1.1, + "precision": "3.0m", + "neighbors": true, + "location": { + "lat": 13.408, + "lon": 52.5186 + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoHashCellQuery + { +Boost = 1.1, +Name = "named_query", +Field = Infer.Field(p=>p.Location), +Location = new GeoLocation(13.4080, 52.5186), +Neighbors = true, +Precision = Nest.Distance.Meters(3) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc new file mode 100644 index 00000000000..f44402f8008 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/polygon/geo-polygon-query-usage.asciidoc @@ -0,0 +1,48 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "geo_polygon": { + "_name": "named_query", + "boost": 1.1, + "coerce": true, + "ignore_malformed": true, + "validation_method": "strict", + "location": { + "points": [ + { + "lat": 45.0, + "lon": -45.0 + }, + { + "lat": -34.0, + "lon": 34.0 + } + ] + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoPolygonQuery + { +Boost = 1.1, +Name = "named_query", +ValidationMethod = GeoValidationMethod.Strict, +Coerce = true, +IgnoreMalformed = true, +Points = new [] { new GeoLocation(45,-45), new GeoLocation(-34,34), }, +Field = Field(p=>p.Location) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc new file mode 100644 index 00000000000..44ef9c04e76 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/circle/geo-shape-circle-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapeCircleQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +Shape = new CircleGeoShape(this._coordinates) { Radius = "100m" } + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc new file mode 100644 index 00000000000..ad56fd20b61 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/envelope/geo-envelope-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapeEnvelopeQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +Shape = new EnvelopeGeoShape(this._coordinates) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc new file mode 100644 index 00000000000..c4db674d238 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/indexed-shape/geo-indexed-shape-usage.asciidoc @@ -0,0 +1,44 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "geo_shape": { + "location": { + "_name": "named_query", + "boost": 1.1, + "indexed_shape": { + "id": 2, + "type": "project", + "index": "project", + "path": "location" + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoIndexedShapeQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +IndexedShape = new FieldLookup +{ + Id = 2, + Index = Index(), + Type = Type(), + Path = Field(p=>p.Location) +} + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc new file mode 100644 index 00000000000..d50e8a09890 --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/line-string/geo-line-string-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapeLineStringQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +Shape = new LineStringGeoShape(this._coordinates) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc new file mode 100644 index 00000000000..0bd741f1eaf --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/multi-line-string/geo-multi-line-string-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapeMultiLineStringQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +Shape = new MultiLineStringGeoShape(this._coordinates) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc new file mode 100644 index 00000000000..7221a432c1d --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/multi-point/geo-multi-point-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapeMultiPointQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +Shape = new MultiPointGeoShape(this._coordinates) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc new file mode 100644 index 00000000000..5a868d095ef --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/point/geo-point-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapePointQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p=>p.Location), +Shape = new PointGeoShape(this._coordinates) + } +---- + diff --git a/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc new file mode 100644 index 00000000000..502ff1543fb --- /dev/null +++ b/docs/asciidoc/query-dsl/geo/shape/polygon/geo-polygon-usage.asciidoc @@ -0,0 +1,19 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../../images + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new GeoShapePolygonQuery + { +Name = "named_query", +Boost = 1.1, +Field = Field(p => p.Location), +Shape = new PolygonGeoShape(this._coordinates) { } + } +---- + diff --git a/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc new file mode 100644 index 00000000000..ef6c4a1e153 --- /dev/null +++ b/docs/asciidoc/query-dsl/joining/has-child/has-child-query-usage.asciidoc @@ -0,0 +1,44 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "has_child": { + "_name": "named_query", + "boost": 1.1, + "type": "developer", + "score_mode": "avg", + "min_children": 1, + "max_children": 5, + "query": { + "match_all": {} + }, + "inner_hits": { + "explain": true + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new HasChildQuery + { +Name = "named_query", +Boost = 1.1, +Type = Infer.Type(), +InnerHits = new InnerHits { Explain = true }, +MaxChildren = 5, +MinChildren = 1, +Query = new MatchAllQuery(), +ScoreMode = ChildScoreMode.Average + } +---- + diff --git a/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc new file mode 100644 index 00000000000..851a772c9b8 --- /dev/null +++ b/docs/asciidoc/query-dsl/joining/has-parent/has-parent-query-usage.asciidoc @@ -0,0 +1,40 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "has_parent": { + "_name": "named_query", + "boost": 1.1, + "type": "developer", + "score_mode": "score", + "query": { + "match_all": {} + }, + "inner_hits": { + "explain": true + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new HasParentQuery + { +Name = "named_query", +Boost = 1.1, +Type = Infer.Type(), +InnerHits = new InnerHits { Explain = true }, +Query = new MatchAllQuery(), +ScoreMode = ParentScoreMode.Score + } +---- + diff --git a/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc new file mode 100644 index 00000000000..f1a5a6c09ab --- /dev/null +++ b/docs/asciidoc/query-dsl/joining/nested/nested-query-usage.asciidoc @@ -0,0 +1,38 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "nested": { + "_name": "named_query", + "boost": 1.1, + "query": { + "match_all": {} + }, + "path": "curatedTags", + "inner_hits": { + "explain": true + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new NestedQuery + { +Name = "named_query", +Boost = 1.1, +InnerHits = new InnerHits { Explain = true }, +Query = new MatchAllQuery(), +Path = Field(p=>p.CuratedTags) + } +---- + diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc new file mode 100644 index 00000000000..a503969d916 --- /dev/null +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-combine-usage.asciidoc @@ -0,0 +1,37 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "bool": { + "must": [ + { + "term": { + "fieldname": "value" + } + }, + { + "term": { + "x": { + "value": "y" + } + } + } + ] + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new RawQuery(RawTermQuery) +&& new TermQuery { Field = "x", Value = "y" } +---- + diff --git a/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc new file mode 100644 index 00000000000..b6efae1f799 --- /dev/null +++ b/docs/asciidoc/query-dsl/nest-specific/raw/raw-query-usage.asciidoc @@ -0,0 +1,23 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "term": { + "fieldname": "value" + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new RawQuery(RawTermQuery) +---- + diff --git a/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc new file mode 100644 index 00000000000..50300f582a2 --- /dev/null +++ b/docs/asciidoc/query-dsl/span/container/span-containing-query-usage.asciidoc @@ -0,0 +1,44 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_containing": { + "_name": "named_query", + "boost": 1.1, + "little": { + "span_term": { + "field1": { + "value": "hoya" + } + } + }, + "big": { + "span_term": { + "field1": { + "value": "hoya2" + } + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanContainingQuery + { +Name = "named_query", +Boost = 1.1, +Little = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya"} }, +Big = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2"} }, + } +---- + diff --git a/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc new file mode 100644 index 00000000000..54c202ce107 --- /dev/null +++ b/docs/asciidoc/query-dsl/span/first/span-first-query-usage.asciidoc @@ -0,0 +1,41 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_first": { + "_name": "named_query", + "boost": 1.1, + "match": { + "span_term": { + "name": { + "value": "value" + } + } + }, + "end": 3 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanFirstQuery + { +Name = "named_query", +Boost = 1.1, +End = 3, +Match = new SpanQuery +{ + SpanTerm = new SpanTermQuery { Field = "name", Value = "value" } +} + } +---- + diff --git a/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc new file mode 100644 index 00000000000..eeddaabb649 --- /dev/null +++ b/docs/asciidoc/query-dsl/span/multi-term/span-multi-term-query-usage.asciidoc @@ -0,0 +1,36 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_multi": { + "_name": "named_query", + "boost": 1.1, + "match": { + "prefix": { + "name": { + "value": "pre-*" + } + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanMultiTermQuery + { +Name = "named_query", +Boost = 1.1, +Match = new PrefixQuery { Field = "name", Value = "pre-*" } + } +---- + diff --git a/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc new file mode 100644 index 00000000000..2befab4cd46 --- /dev/null +++ b/docs/asciidoc/query-dsl/span/near/span-near-query-usage.asciidoc @@ -0,0 +1,63 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_near": { + "clauses": [ + { + "span_term": { + "field": { + "value": "value1" + } + } + }, + { + "span_term": { + "field": { + "value": "value2" + } + } + }, + { + "span_term": { + "field": { + "value": "value3" + } + } + } + ], + "slop": 12, + "in_order": false, + "collect_payloads": false, + "_name": "named_query", + "boost": 1.1 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanNearQuery + { +Name = "named_query", +Boost = 1.1, +Clauses = new List +{ + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value1" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value2" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value3" } } +}, +Slop = 12, +InOrder = false, +CollectPayloads = false + } +---- + diff --git a/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc new file mode 100644 index 00000000000..5f70aa41eb2 --- /dev/null +++ b/docs/asciidoc/query-dsl/span/not/span-not-query-usage.asciidoc @@ -0,0 +1,50 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_not": { + "_name": "named_query", + "boost": 1.1, + "include": { + "span_term": { + "field1": { + "value": "hoya" + } + } + }, + "exclude": { + "span_term": { + "field1": { + "value": "hoya2" + } + } + }, + "pre": 14, + "post": 13, + "dist": 12 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanNotQuery + { +Name = "named_query", +Boost = 1.1, +Dist = 12, +Post = 13, +Pre = 14, +Include = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya" } }, +Exclude = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2" } }, + } +---- + diff --git a/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc new file mode 100644 index 00000000000..69e055081db --- /dev/null +++ b/docs/asciidoc/query-dsl/span/or/span-or-query-usage.asciidoc @@ -0,0 +1,57 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_or": { + "_name": "named_query", + "boost": 1.1, + "clauses": [ + { + "span_term": { + "field": { + "value": "value1" + } + } + }, + { + "span_term": { + "field": { + "value": "value2" + } + } + }, + { + "span_term": { + "field": { + "value": "value3" + } + } + } + ] + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanOrQuery + { +Name = "named_query", +Boost = 1.1, +Clauses = new List +{ + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value1" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value2" } }, + new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field", Value = "value3" } } +}, + } +---- + diff --git a/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc new file mode 100644 index 00000000000..bfa964de25b --- /dev/null +++ b/docs/asciidoc/query-dsl/span/term/span-term-query-usage.asciidoc @@ -0,0 +1,33 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_term": { + "user": { + "_name": "named_query", + "boost": 1.1, + "value": "kimchy" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanTermQuery + { +Name = "named_query", +Boost = 1.1, +Value = "kimchy", +Field = "user" + } +---- + diff --git a/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc new file mode 100644 index 00000000000..111a48780bc --- /dev/null +++ b/docs/asciidoc/query-dsl/span/within/span-within-query-usage.asciidoc @@ -0,0 +1,44 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "span_within": { + "_name": "named_query", + "boost": 1.1, + "little": { + "span_term": { + "field1": { + "value": "hoya" + } + } + }, + "big": { + "span_term": { + "field1": { + "value": "hoya2" + } + } + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new SpanWithinQuery + { +Name = "named_query", +Boost = 1.1, +Little = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya"} }, +Big = new SpanQuery { SpanTerm = new SpanTermQuery { Field = "field1", Value = "hoya2"} }, + } +---- + diff --git a/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc new file mode 100644 index 00000000000..0bd3e4835d6 --- /dev/null +++ b/docs/asciidoc/query-dsl/specialized/more-like-this/more-like-this-query-usage.asciidoc @@ -0,0 +1,77 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "mlt": { + "fields": [ + "name" + ], + "minimum_should_match": 1, + "stop_words": [ + "and", + "the" + ], + "min_term_freq": 1, + "max_query_terms": 12, + "min_doc_freq": 1, + "max_doc_freq": 12, + "min_word_len": 10, + "max_word_len": 300, + "boost_terms": 1.1, + "analyzer": "some_analyzer", + "include": true, + "like": [ + { + "_index": "project", + "_type": "project", + "_id": "Durgan LLC" + }, + "some long text" + ], + "unlike": [ + "not like this text" + ], + "_name": "named_query", + "boost": 1.1 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new MoreLikeThisQuery + { +Name = "named_query", +Boost = 1.1, +Fields = Fields(p=>p.Name), +Like = new List +{ + new LikeDocument(Project.Instance.Name), + "some long text" +}, +Analyzer = "some_analyzer", +BoostTerms = 1.1, +Include = true, +MaxDocumentFrequency = 12, +MaxQueryTerms = 12, +MaxWordLength = 300, +MinDocumentFrequency = 1, +MinTermFrequency = 1, +MinWordLength = 10, +MinimumShouldMatch = 1, +StopWords = new [] { "and", "the"}, +Unlike = new List +{ + "not like this text" +} + } +---- + diff --git a/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc new file mode 100644 index 00000000000..654c900579d --- /dev/null +++ b/docs/asciidoc/query-dsl/specialized/script/script-query-usage.asciidoc @@ -0,0 +1,37 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "script": { + "_name": "named_query", + "boost": 1.1, + "inline": "doc['num1'].value > param1", + "params": { + "param1": 1 + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new ScriptQuery + { +Name = "named_query", +Boost = 1.1, +Inline = _templateString, +Params = new Dictionary +{ + { "param1", 1 } +} + } +---- + diff --git a/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc new file mode 100644 index 00000000000..4a7d1bce749 --- /dev/null +++ b/docs/asciidoc/query-dsl/specialized/template/template-query-usage.asciidoc @@ -0,0 +1,41 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,csharp,method="queryjson"] +---- +new + { +template = new +{ + _name = "named_query", + boost = 1.1, + inline = _templateString, + @params = new + { + query_string = "all about search" + } +} + + + } +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new TemplateQuery + { +Name = "named_query", +Boost = 1.1, +Inline = _templateString, +Params = new Dictionary +{ + { "query_string", "all about search" } +} + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc new file mode 100644 index 00000000000..b583946f91c --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/exists/exists-query-usage.asciidoc @@ -0,0 +1,30 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "exists": { + "_name": "named_query", + "boost": 1.1, + "field": "description" + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new ExistsQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc new file mode 100644 index 00000000000..dea6f12b329 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-date-query-usage.asciidoc @@ -0,0 +1,43 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "fuzzy": { + "description": { + "_name": "named_query", + "boost": 1.1, + "fuzziness": "2d", + "max_expansions": 100, + "prefix_length": 3, + "rewrite": "constant_score", + "transpositions": true, + "value": "2015-01-01T00:00:00" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new FuzzyDateQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Fuzziness = TimeSpan.FromDays(2), +Value = Project.Instance.StartedOn, +MaxExpansions = 100, +PrefixLength = 3, +Rewrite = RewriteMultiTerm.ConstantScore, +Transpositions = true + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc new file mode 100644 index 00000000000..ea5f3760e86 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-numeric-query-usage.asciidoc @@ -0,0 +1,43 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "fuzzy": { + "description": { + "_name": "named_query", + "boost": 1.1, + "fuzziness": 2.0, + "max_expansions": 100, + "prefix_length": 3, + "rewrite": "constant_score", + "transpositions": true, + "value": 12.0 + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new FuzzyNumericQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Fuzziness = 2, +Value = 12, +MaxExpansions = 100, +PrefixLength = 3, +Rewrite = RewriteMultiTerm.ConstantScore, +Transpositions = true + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc new file mode 100644 index 00000000000..0c163dfda1a --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/fuzzy/fuzzy-query-usage.asciidoc @@ -0,0 +1,43 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "fuzzy": { + "description": { + "_name": "named_query", + "boost": 1.1, + "fuzziness": "AUTO", + "max_expansions": 100, + "prefix_length": 3, + "rewrite": "constant_score", + "transpositions": true, + "value": "ki" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new FuzzyQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Fuzziness = Fuzziness.Auto, +Value = "ki", +MaxExpansions = 100, +PrefixLength = 3, +Rewrite = RewriteMultiTerm.ConstantScore, +Transpositions = true + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc new file mode 100644 index 00000000000..e6c35860e59 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/ids/ids-query-usage.asciidoc @@ -0,0 +1,40 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "ids": { + "_name": "named_query", + "boost": 1.1, + "types": [ + "project", + "developer" + ], + "values": [ + 1, + 2, + 3, + 4 + ] + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new IdsQuery + { +Name = "named_query", +Boost = 1.1, +Values = new List { 1, 2,3,4 }, +Types = Type().And() + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc new file mode 100644 index 00000000000..b2a986dc887 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/missing/missing-query-usage.asciidoc @@ -0,0 +1,34 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "missing": { + "_name": "named_query", + "boost": 1.1, + "existence": true, + "field": "description", + "null_value": true + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new MissingQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +NullValue = true, +Existence = true + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc new file mode 100644 index 00000000000..1eb44e7166d --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/prefix/prefix-query-usage.asciidoc @@ -0,0 +1,35 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "prefix": { + "description": { + "_name": "named_query", + "boost": 1.1, + "rewrite": "top_terms_boost_N", + "value": "proj" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new PrefixQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Value = "proj", +Rewrite = RewriteMultiTerm.TopTermsBoostN + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc new file mode 100644 index 00000000000..695ceb388c7 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/range/date-range-query-usage.asciidoc @@ -0,0 +1,43 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "range": { + "description": { + "_name": "named_query", + "boost": 1.1, + "format": "dd/MM/yyyy||yyyy", + "gt": "2015-06-06T12:01:02.123", + "gte": "2015-06-06T12:01:02.123||/M", + "lt": "01/01/2012", + "lte": "now", + "time_zone": "+01:00" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new DateRangeQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +GreaterThan = FixedDate, +GreaterThanOrEqualTo = DateMath.Anchored(FixedDate).RoundTo(TimeUnit.Month), +LessThan = "01/01/2012", +LessThanOrEqualTo = DateMath.Now, +TimeZone = "+01:00", +Format = "dd/MM/yyyy||yyyy" + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc new file mode 100644 index 00000000000..4f34c36c316 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/range/numeric-range-query-usage.asciidoc @@ -0,0 +1,39 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "range": { + "description": { + "_name": "named_query", + "boost": 1.1, + "gt": 1.0, + "gte": 1.1, + "lt": 2.1, + "lte": 2.0 + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new NumericRangeQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +GreaterThan = 1.0, +GreaterThanOrEqualTo = 1.1, +LessThan = 2.1, +LessThanOrEqualTo = 2.0 + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc new file mode 100644 index 00000000000..b855877009c --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/range/term-range-query-usage.asciidoc @@ -0,0 +1,39 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "range": { + "description": { + "_name": "named_query", + "boost": 1.1, + "gt": "foo", + "gte": "foof", + "lt": "bar", + "lte": "barb" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new TermRangeQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +GreaterThan = "foo", +GreaterThanOrEqualTo = "foof", +LessThan = "bar", +LessThanOrEqualTo = "barb" + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc new file mode 100644 index 00000000000..cfd4962e491 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/regexp/regexp-query-usage.asciidoc @@ -0,0 +1,37 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "regexp": { + "description": { + "_name": "named_query", + "boost": 1.1, + "flags": "INTERSECTION|COMPLEMENT|EMPTY", + "max_determinized_states": 20000, + "value": "s.*y" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new RegexpQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Value = "s.*y", +Flags = "INTERSECTION|COMPLEMENT|EMPTY", +MaximumDeterminizedStates = 20000 + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc new file mode 100644 index 00000000000..40868d0848f --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/term/term-query-usage.asciidoc @@ -0,0 +1,33 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "term": { + "description": { + "_name": "named_query", + "boost": 1.1, + "value": "project description" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new TermQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Value = "project description" + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc new file mode 100644 index 00000000000..5caa1d8d51a --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-lookup-query-usage.asciidoc @@ -0,0 +1,42 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "terms": { + "_name": "named_query", + "boost": 1.1, + "description": { + "id": 12, + "index": "devs", + "path": "lastName", + "type": "developer" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new TermsQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +TermsLookup = new FieldLookup +{ + Id = 12, + Index = Index(), + Type = Type(), + Path = Field(p=>p.LastName) +} + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc new file mode 100644 index 00000000000..1f8fa5eddbf --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/terms/terms-query-usage.asciidoc @@ -0,0 +1,38 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "terms": { + "_name": "named_query", + "boost": 1.1, + "description": [ + "term1", + "term2" + ], + "disable_coord": true, + "minimum_should_match": 2 + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new TermsQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Terms = new [] { "term1", "term2" }, +DisableCoord = true, +MinimumShouldMatch = 2 + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc new file mode 100644 index 00000000000..87fbedfc0fd --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/type/type-query-usage.asciidoc @@ -0,0 +1,30 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "type": { + "_name": "named_query", + "boost": 1.1, + "value": "developer" + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new TypeQuery + { +Name = "named_query", +Boost = 1.1, +Value = Type() + } +---- + diff --git a/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc new file mode 100644 index 00000000000..6bc1df39f96 --- /dev/null +++ b/docs/asciidoc/query-dsl/term-level/wildcard/wildcard-query-usage.asciidoc @@ -0,0 +1,35 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../../images + +[source,javascript,method="queryjson"] +.Example json output +---- +{ + "wildcard": { + "description": { + "_name": "named_query", + "boost": 1.1, + "rewrite": "top_terms_boost_N", + "value": "p*oj" + } + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="queryinitializer"] +---- +new WildcardQuery + { +Name = "named_query", +Boost = 1.1, +Field = "description", +Value = "p*oj", +Rewrite = RewriteMultiTerm.TopTermsBoostN + } +---- + diff --git a/docs/asciidoc/search/request/explain-usage.asciidoc b/docs/asciidoc/search/request/explain-usage.asciidoc new file mode 100644 index 00000000000..b23ea90500d --- /dev/null +++ b/docs/asciidoc/search/request/explain-usage.asciidoc @@ -0,0 +1,31 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +Enables explanation for each hit on how its score was computed. + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "explain": true +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Explain() +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest { Explain = true } +---- + diff --git a/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc new file mode 100644 index 00000000000..9104f7cc80a --- /dev/null +++ b/docs/asciidoc/search/request/fielddata-fields-usage.asciidoc @@ -0,0 +1,40 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "fielddata_fields": [ + "name", + "leadDeveloper", + "startedOn" + ] +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.FielddataFields(fs => fs + .Field(p => p.Name) + .Field(p => p.LeadDeveloper) + .Field(p => p.StartedOn) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + FielddataFields = new string [] { "name", "leadDeveloper", "startedOn" } +} +---- + diff --git a/docs/asciidoc/search/request/fields-usage.asciidoc b/docs/asciidoc/search/request/fields-usage.asciidoc new file mode 100644 index 00000000000..86f70bde929 --- /dev/null +++ b/docs/asciidoc/search/request/fields-usage.asciidoc @@ -0,0 +1,38 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "fields": [ + "name", + "startedOn" + ] +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Fields(fs => fs + .Field(p => p.Name) + .Field(p => p.StartedOn) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + Fields = Fields(p => p.Name, p => p.StartedOn) +} +---- + diff --git a/docs/asciidoc/search/request/from-and-size-usage.asciidoc b/docs/asciidoc/search/request/from-and-size-usage.asciidoc new file mode 100644 index 00000000000..cb0fd3e4ea4 --- /dev/null +++ b/docs/asciidoc/search/request/from-and-size-usage.asciidoc @@ -0,0 +1,35 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "from": 10, + "size": 12 +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest() +{ + From = 10, + Size = 12 +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s + .From(10) + .Size(12) +---- + diff --git a/docs/asciidoc/search/request/highlighting-usage.asciidoc b/docs/asciidoc/search/request/highlighting-usage.asciidoc new file mode 100644 index 00000000000..f139c394047 --- /dev/null +++ b/docs/asciidoc/search/request/highlighting-usage.asciidoc @@ -0,0 +1,190 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "query": { + "match": { + "name.standard": { + "query": "Upton Sons Shield Rice Rowe Roberts" + } + } + }, + "highlight": { + "pre_tags": [ + "" + ], + "post_tags": [ + "" + ], + "fields": { + "name.standard": { + "type": "plain", + "force_source": true, + "fragment_size": 150, + "number_of_fragments": 3, + "no_match_size": 150 + }, + "leadDeveloper.firstName": { + "type": "fvh", + "pre_tags": [ + "" + ], + "post_tags": [ + "" + ], + "highlight_query": { + "match": { + "leadDeveloper.firstName": { + "query": "Kurt Edgardo Naomi Dariana Justice Felton" + } + } + } + }, + "state.offsets": { + "type": "postings", + "pre_tags": [ + "" + ], + "post_tags": [ + "" + ], + "highlight_query": { + "terms": { + "state.offsets": [ + "stable", + "bellyup" + ] + } + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Query(q => q + .Match(m => m + .Field(f => f.Name.Suffix("standard")) + .Query("Upton Sons Shield Rice Rowe Roberts") + ) +) +.Highlight(h => h + .PreTags("") + .PostTags("") + .Fields( + fs => fs + .Field(p => p.Name.Suffix("standard")) + .Type(HighlighterType.Plain) + .ForceSource() + .FragmentSize(150) + .NumberOfFragments(3) + .NoMatchSize(150), + fs => fs + .Field(p => p.LeadDeveloper.FirstName) + .Type(HighlighterType.Fvh) + .PreTags("") + .PostTags("") + .HighlightQuery(q => q + .Match(m => m + .Field(p => p.LeadDeveloper.FirstName) + .Query("Kurt Edgardo Naomi Dariana Justice Felton") + ) + ), + fs => fs + .Field(p => p.State.Suffix("offsets")) + .Type(HighlighterType.Postings) + .PreTags("") + .PostTags("") + .HighlightQuery(q => q + .Terms(t => t + .Field(f => f.State.Suffix("offsets")) + .Terms( + StateOfBeing.Stable.ToString().ToLowerInvariant(), + StateOfBeing.BellyUp.ToString().ToLowerInvariant() + ) + ) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + Query = new MatchQuery + { + Query = "Upton Sons Shield Rice Rowe Roberts", + Field = "name.standard" + }, + Highlight = new Highlight + { + PreTags = new[] { "" }, + PostTags = new[] { "" }, + Fields = new Dictionary + { + { "name.standard", new HighlightField + { + Type = HighlighterType.Plain, + ForceSource = true, + FragmentSize = 150, + NumberOfFragments = 3, + NoMatchSize = 150 + } + }, + { "leadDeveloper.firstName", new HighlightField + { + Type = HighlighterType.Fvh, + PreTags = new[] { ""}, + PostTags = new[] { ""}, + HighlightQuery = new MatchQuery + { + Field = "leadDeveloper.firstName", + Query = "Kurt Edgardo Naomi Dariana Justice Felton" + } + } + }, + { "state.offsets", new HighlightField + { + Type = HighlighterType.Postings, + PreTags = new[] { ""}, + PostTags = new[] { ""}, + HighlightQuery = new TermsQuery + { + Field = "state.offsets", + Terms = new [] { "stable", "bellyup" } + } + } + } + } + } +} +---- + +=== Handling Responses + +[source,csharp,method="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +highlight.Should().Contain(""); +highlight.Should().Contain(""); +highlight.Should().Contain(""); +highlight.Should().Contain(""); +highlight.Should().Contain(""); +highlight.Should().Contain(""); +Assert.True(false, $"highlights contains unexpected key {highlightHit.Key}"); +---- + diff --git a/docs/asciidoc/search/request/index-boost-usage.asciidoc b/docs/asciidoc/search/request/index-boost-usage.asciidoc new file mode 100644 index 00000000000..d0ce262c5a6 --- /dev/null +++ b/docs/asciidoc/search/request/index-boost-usage.asciidoc @@ -0,0 +1,42 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "indices_boost": { + "index1": 1.4, + "index2": 1.3 + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.IndicesBoost(b => b + .Add("index1", 1.4) + .Add("index2", 1.3) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + IndicesBoost = new Dictionary + { + { "index1", 1.4 }, + { "index2", 1.3 } + } +} +---- + diff --git a/docs/asciidoc/search/request/inner-hits-usage.asciidoc b/docs/asciidoc/search/request/inner-hits-usage.asciidoc new file mode 100644 index 00000000000..9ddaed19556 --- /dev/null +++ b/docs/asciidoc/search/request/inner-hits-usage.asciidoc @@ -0,0 +1,150 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,csharp,method="unknown"] +---- +public interface IRoyal + { +string Name { get; set; } + } +---- + +[source,csharp,method="indexall"] +---- +var current = create(); + +var royals = current.ToList(); + +var royal1 = royal; + +bulk.Index(i => i.Document(royal1).Index(this._index).Parent(parent)); + +indexChildren(royal); +---- + +[source,csharp,method="seed"] +---- +var create = this._client.CreateIndex(this._index, c => c + .Settings(s => s + .NumberOfReplicas(0) + .NumberOfShards(1) + ) + .Mappings(map => map + .Map(m => m.AutoMap() + .Properties(props => + RoyalProps(props) + .Nested(n => n.Name(p => p.Foes).AutoMap()) + ) + ) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + .Map(m => m.AutoMap().Properties(RoyalProps).Parent()) + ) +); +var kings = King.Generator.Generate(2) + .Select(k => + { + k.Foes = King.Generator.Generate(2).ToList(); + return k; + }); +k.Foes = King.Generator.Generate(2).ToList(); +var bulk = new BulkDescriptor(); +IndexAll(bulk, () => kings, indexChildren: king => + IndexAll(bulk, () => Prince.Generator.Generate(2), king.Name, prince => + IndexAll(bulk, () => Duke.Generator.Generate(3), prince.Name, duke => + IndexAll(bulk, () => Earl.Generator.Generate(5), duke.Name, earl => + IndexAll(bulk, () => Baron.Generator.Generate(1), earl.Name) + ) + ) + ) +); +this._client.Bulk(bulk); +this._client.Refresh(this._index); +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Index(Index) +.InnerHits(ih => ih + .Type("earls", g => g + .Size(5) + .InnerHits(iih => iih + .Type("barons") + ) + .FielddataFields(p => p.Name) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest(Index, typeof(Duke)) + { +InnerHits = new NamedInnerHits +{ + { "earls", new InnerHitsContainer + { + Type = new TypeInnerHit + { + InnerHit = new GlobalInnerHit + { + Size = 5, + FielddataFields = new Field[]{ "name" }, + InnerHits = new NamedInnerHits + { + { "barons", new TypeInnerHit() } + } + } + } + } } +} + } +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Index(Index) +.Query(q => + q.HasChild(hc => hc + .Query(hcq => hcq.MatchAll()) + .InnerHits(ih => ih.Name("princes")) + ) || q.Nested(n => n + .Path(p => p.Foes) + .Query(nq => nq.MatchAll()) + .InnerHits() + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest(Index, typeof(King)) + { +Query = new HasChildQuery +{ + Type = typeof(Prince), + Query = new MatchAllQuery(), + InnerHits = new InnerHits { Name = "princes" } +} || new NestedQuery +{ + Path = Field(p => p.Foes), + Query = new MatchAllQuery(), + InnerHits = new InnerHits() +} + } +---- + diff --git a/docs/asciidoc/search/request/min-score-usage.asciidoc b/docs/asciidoc/search/request/min-score-usage.asciidoc new file mode 100644 index 00000000000..aa498f9c4ba --- /dev/null +++ b/docs/asciidoc/search/request/min-score-usage.asciidoc @@ -0,0 +1,47 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "min_score": 0.5, + "query": { + "term": { + "name": { + "value": "elasticsearch" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.MinScore(0.5) +.Query(q => q + .Term(p => p.Name, "elasticsearch") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + MinScore = 0.5, + Query = new TermQuery + { + Field = "name", + Value = "elasticsearch" + } +} +---- + diff --git a/docs/asciidoc/search/request/post-filter-usage.asciidoc b/docs/asciidoc/search/request/post-filter-usage.asciidoc new file mode 100644 index 00000000000..2cf572360f8 --- /dev/null +++ b/docs/asciidoc/search/request/post-filter-usage.asciidoc @@ -0,0 +1,34 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "post_filter": { + "match_all": {} + } +} +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest() +{ + PostFilter = new QueryContainer(new MatchAllQuery()) +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.PostFilter(f => f.MatchAll()) +---- + diff --git a/docs/asciidoc/search/request/query-usage.asciidoc b/docs/asciidoc/search/request/query-usage.asciidoc new file mode 100644 index 00000000000..22aed59b61e --- /dev/null +++ b/docs/asciidoc/search/request/query-usage.asciidoc @@ -0,0 +1,46 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +The query element within the search request body allows to define a query using the Query DSL. + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "query": { + "term": { + "name": { + "value": "elasticsearch" + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Query(q => q + .Term(p => p.Name, "elasticsearch") +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + Query = new TermQuery + { + Field = "name", + Value = "elasticsearch" + } +} +---- + diff --git a/docs/asciidoc/search/request/script-fields-usage.asciidoc b/docs/asciidoc/search/request/script-fields-usage.asciidoc new file mode 100644 index 00000000000..fe62277e700 --- /dev/null +++ b/docs/asciidoc/search/request/script-fields-usage.asciidoc @@ -0,0 +1,69 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "script_fields": { + "test1": { + "script": { + "inline": "doc['my_field_name'].value * 2" + } + }, + "test2": { + "script": { + "inline": "doc['my_field_name'].value * factor", + "params": { + "factor": 2.0 + } + } + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.ScriptFields(sf=>sf + .ScriptField("test1", sc=>sc + .Inline("doc['my_field_name'].value * 2") + ) + .ScriptField("test2", sc=>sc + .Inline("doc['my_field_name'].value * factor") + .Params(p=>p + .Add("factor", 2.0) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + ScriptFields = new ScriptFields + { + { "test1", new ScriptField + { + Script = new InlineScript("doc['my_field_name'].value * 2") + } }, + { "test2", new InlineScript("doc['my_field_name'].value * factor") + { + Params = new FluentDictionary + { + { "factor", 2.0 } + } + } } + } +} +---- + diff --git a/docs/asciidoc/search/request/sort-usage.asciidoc b/docs/asciidoc/search/request/sort-usage.asciidoc new file mode 100644 index 00000000000..b18e2c361a1 --- /dev/null +++ b/docs/asciidoc/search/request/sort-usage.asciidoc @@ -0,0 +1,162 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +Allows to add one or more sort on specific fields. Each sort can be reversed as well. +The sort is defined on a per field level, with special field name for score to sort by score. + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "sort": [ + { + "startedOn": { + "order": "asc" + } + }, + { + "name": { + "order": "desc" + } + }, + { + "_score": { + "order": "desc" + } + }, + { + "_doc": { + "order": "asc" + } + }, + { + "lastActivity": { + "missing": "_last", + "order": "desc", + "mode": "avg", + "nested_filter": { + "match_all": {} + }, + "nested_path": "tags", + "unmapped_type": "date" + } + }, + { + "_geo_distance": { + "location": [ + { + "lat": 70.0, + "lon": -70.0 + }, + { + "lat": -12.0, + "lon": 12.0 + } + ], + "order": "asc", + "mode": "min" + } + }, + { + "_script": { + "order": "asc", + "type": "number", + "script": { + "params": { + "factor": 1.1 + }, + "inline": "doc['numberOfCommits'].value * factor" + } + } + } + ] +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Sort(ss => ss + .Ascending(p => p.StartedOn) + .Descending(p => p.Name) + .Descending(SortSpecialField.Score) + .Ascending(SortSpecialField.DocumentIndexOrder) + .Field(f => f + .Field(p => p.LastActivity) + .Order(SortOrder.Descending) + .MissingLast() + .UnmappedType(FieldType.Date) + .Mode(SortMode.Average) + .NestedPath(p => p.Tags) + .NestedFilter(q => q.MatchAll()) + ) + .GeoDistance(g => g + .Field(p => p.Location) + .DistanceType(GeoDistanceType.SloppyArc) + .Order(SortOrder.Ascending) + .Unit(DistanceUnit.Centimeters) + .Mode(SortMode.Min) + .PinTo(new GeoLocation(70, -70), new GeoLocation(-12, 12)) + ) + .Script(sc => sc + .Type("number") + .Ascending() + .Script(script => script + .Inline("doc['numberOfCommits'].value * factor") + .Params(p => p.Add("factor", 1.1)) + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + Sort = new List + { + new SortField { Field = "startedOn", Order = SortOrder.Ascending }, + new SortField { Field = "name", Order = SortOrder.Descending }, + new SortField { Field = "_score", Order = SortOrder.Descending }, + new SortField { Field = "_doc", Order = SortOrder.Ascending }, + new SortField { + Field = Field(p=>p.LastActivity), + Order = SortOrder.Descending, + Missing = "_last", + UnmappedType = FieldType.Date, + Mode = SortMode.Average, + NestedPath = Field(p=>p.Tags), + NestedFilter = new MatchAllQuery(), + }, + new GeoDistanceSort + { + Field = "location", + Order = SortOrder.Ascending, + DistanceType = GeoDistanceType.Arc, + GeoUnit = DistanceUnit.Centimeters, + Mode = SortMode.Min, + Points = new [] {new GeoLocation(70, -70), new GeoLocation(-12, 12) } + }, + new ScriptSort + { + Type = "number", + Order = SortOrder.Ascending, + Script = new InlineScript("doc['numberOfCommits'].value * factor") + { + Params = new Dictionary + { + { "factor", 1.1 } + } + } + } + } +} +---- + diff --git a/docs/asciidoc/search/request/source-filtering-usage.asciidoc b/docs/asciidoc/search/request/source-filtering-usage.asciidoc new file mode 100644 index 00000000000..5f5e249338c --- /dev/null +++ b/docs/asciidoc/search/request/source-filtering-usage.asciidoc @@ -0,0 +1,116 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +Allows to control how the _source field is returned with every hit. +By default operations return the contents of the _source field unless + you have used the fields parameter or if the source field is disabled. + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "_source": { + "include": [ + "name", + "startedOn" + ] + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Source(so => so + .Include(f => f + .Fields( + p => p.Name, + p => p.StartedOn + ) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + Source = new SourceFilter + { + Include = Fields(p => p.Name, prop => prop.StartedOn) + } +} +---- + +=== Handling Responses + +[source,csharp,method="expectresponse"] +---- +response.IsValid.Should().BeTrue(); +document.Name.Should().NotBeNull(); +document.StartedOn.Should().NotBe(default(DateTime)); +document.Description.Should().BeNull(); +---- + +[source,csharp,method="unknown"] +---- +internal class WithSourceFilterProperty +{ + [JsonProperty("_source")] + public ISourceFilter SourceFilter { get; set; } +} +---- + +[source,csharp,method="candeserializeboolean"] +---- +var o = base.Deserialize("{ \"_source\": false }"); + +o.Should().NotBeNull(); + +o.SourceFilter.Should().NotBeNull(); + +o.SourceFilter.Exclude.Should().Contain("*"); +---- + +[source,csharp,method="candeserializearray"] +---- +var o = base.Deserialize("{ \"_source\": [\"obj.*\"] }"); + +o.Should().NotBeNull(); + +o.SourceFilter.Should().NotBeNull(); + +o.SourceFilter.Include.Should().Contain("obj.*"); +---- + +[source,csharp,method="candeserializestring"] +---- +var o = base.Deserialize("{ \"_source\": \"obj.*\" }"); + +o.Should().NotBeNull(); + +o.SourceFilter.Should().NotBeNull(); + +o.SourceFilter.Include.Should().Contain("obj.*"); +---- + +[source,csharp,method="candeserializeobject"] +---- +var o = base.Deserialize("{ \"_source\": { \"include\": [\"obj.*\"], \"exclude\": [\"foo.*\"] } }"); + +o.Should().NotBeNull(); + +o.SourceFilter.Should().NotBeNull(); + +o.SourceFilter.Include.Should().Contain("obj.*"); + +o.SourceFilter.Exclude.Should().Contain("foo.*"); +---- + diff --git a/docs/asciidoc/search/request/suggest-usage.asciidoc b/docs/asciidoc/search/request/suggest-usage.asciidoc new file mode 100644 index 00000000000..35308563d6f --- /dev/null +++ b/docs/asciidoc/search/request/suggest-usage.asciidoc @@ -0,0 +1,227 @@ +:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/current + +:github: https://github.com/elastic/elasticsearch-net + +:imagesdir: ../../images + +Allows to add one or more sort on specific fields. Each sort can be reversed as well. +The sort is defined on a per field level, with special field name for score to sort by score. + +=== Handling Responses + +[source,csharp,method="expectresponse"] +---- +var myCompletionSuggest = response.Suggest["my-completion-suggest"]; +myCompletionSuggest.Should().NotBeNull(); +var suggest = myCompletionSuggest.First(); +suggest.Text.Should().Be(Project.Instance.Name); +suggest.Length.Should().BeGreaterThan(0); +var option = suggest.Options.First(); +option.Text.Should().NotBeNullOrEmpty(); +option.Score.Should().BeGreaterThan(0); +var payload = option.Payload(); +payload.Should().NotBeNull(); +payload.Name.Should().Be(Project.Instance.Name); +payload.State.Should().NotBeNull(); +---- + +[source,javascript,method="expectjson"] +.Example json output +---- +{ + "suggest": { + "my-completion-suggest": { + "completion": { + "analyzer": "simple", + "context": { + "color": "red" + }, + "field": "suggest", + "fuzzy": { + "fuzziness": "AUTO", + "min_length": 1, + "prefix_length": 2, + "transpositions": true, + "unicode_aware": false + }, + "shard_size": 7, + "size": 8 + }, + "text": "Durgan LLC" + }, + "my-phrase-suggest": { + "phrase": { + "collate": { + "query": { + "inline": "{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}", + "params": { + "field_name": "title" + } + }, + "prune": true + }, + "confidence": 10.1, + "direct_generator": [ + { + "field": "description" + } + ], + "field": "name", + "gram_size": 1, + "real_word_error_likelihood": 0.5 + }, + "text": "hello world" + }, + "my-term-suggest": { + "term": { + "analyzer": "standard", + "field": "name", + "max_edits": 1, + "max_inspections": 2, + "max_term_freq": 3.0, + "min_doc_freq": 4.0, + "min_word_len": 5, + "prefix_len": 6, + "shard_size": 7, + "size": 8, + "suggest_mode": "always" + }, + "text": "hello world" + } + } +} +---- + +=== Fluent DSL Example + +[source,csharp,method="fluent"] +---- +s => s +.Suggest(ss => ss + .Term("my-term-suggest", t => t + .MaxEdits(1) + .MaxInspections(2) + .MaxTermFrequency(3) + .MinDocFrequency(4) + .MinWordLength(5) + .PrefixLength(6) + .SuggestMode(SuggestMode.Always) + .Analyzer("standard") + .Field(p => p.Name) + .ShardSize(7) + .Size(8) + .Text("hello world") + ) + .Completion("my-completion-suggest", c => c + .Context(ctx => ctx + .Add("color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First()) + ) + .Fuzzy(f => f + .Fuzziness(Fuzziness.Auto) + .MinLength(1) + .PrefixLength(2) + .Transpositions() + .UnicodeAware(false) + ) + .Analyzer("simple") + .Field(p => p.Suggest) + .ShardSize(7) + .Size(8) + .Text(Project.Instance.Name) + ) + .Phrase("my-phrase-suggest", ph => ph + .Collate(c => c + .Query(q => q + .Inline("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + .Params(p => p.Add("field_name", "title")) + ) + .Prune() + ) + .Confidence(10.1) + .DirectGenerator(d => d + .Field(p => p.Description) + ) + .GramSize(1) + .Field(p => p.Name) + .Text("hello world") + .RealWordErrorLikelihood(0.5) + ) +) +---- + +=== Object Initializer Syntax Example + +[source,csharp,method="initializer"] +---- +new SearchRequest +{ + Suggest = new SuggestContainer + { + { "my-term-suggest", new SuggestBucket + { + Text = "hello world", + Term = new TermSuggester + { + MaxEdits = 1, + MaxInspections = 2, + MaxTermFrequency = 3, + MinDocFrequency = 4, + MinWordLen = 5, + PrefixLen = 6, + SuggestMode = SuggestMode.Always, + Analyzer = "standard", + Field = Field(p=>p.Name), + ShardSize = 7, + Size = 8 + } + } }, + { "my-completion-suggest", new SuggestBucket + { + Text = Project.Instance.Name, + Completion = new CompletionSuggester + { + Context = new Dictionary { { "color", Project.Projects.First().Suggest.Context.Values.SelectMany(v => v).First() } }, + Fuzzy = new FuzzySuggester + { + Fuzziness = Fuzziness.Auto, + MinLength = 1, + PrefixLength = 2, + Transpositions = true, + UnicodeAware = false + }, + Analyzer = "simple", + Field = Field(p=>p.Suggest), + ShardSize = 7, + Size = 8 + } + } }, + { "my-phrase-suggest", new SuggestBucket + { + Text = "hello world", + Phrase = new PhraseSuggester + { + Collate = new PhraseSuggestCollate + { + Query = new InlineScript("{ \"match\": { \"{{field_name}}\": \"{{suggestion}}\" }}") + { + Params = new Dictionary + { + { "field_name", "title" } + } + }, + Prune = true + }, + Confidence = 10.1, + DirectGenerator = new List + { + new DirectGenerator { Field = "description" } + }, + GramSize = 1, + Field = "name", + RealWordErrorLikelihood = 0.5 + } + } }, + } +} +---- + diff --git a/docs/asciidoc/search/suggesters/suggest-api.asciidoc b/docs/asciidoc/search/suggesters/suggest-api.asciidoc index cf28136a0b2..bfd0aeca2b3 100644 --- a/docs/asciidoc/search/suggesters/suggest-api.asciidoc +++ b/docs/asciidoc/search/suggesters/suggest-api.asciidoc @@ -6,7 +6,7 @@ == Suggest API -[source,javascript,method-name="expectjson"] +[source,javascript,method="expectjson"] .Example json output ---- { @@ -73,7 +73,7 @@ === Fluent DSL Example -[source,csharp,method-name="fluent"] +[source,csharp,method="fluent"] ---- s => s .Term("my-term-suggest", t => t @@ -128,7 +128,7 @@ s => s === Object Initializer Syntax Example -[source,csharp,method-name="initializer"] +[source,csharp,method="initializer"] ---- new SuggestRequest { @@ -207,7 +207,7 @@ new SuggestRequest Get the suggestions for a suggester by indexing into the `.Suggestions` on the response -[source,csharp,method-name="expectresponse"] +[source,csharp,method="expectresponse"] ---- var myCompletionSuggest = response.Suggestions["my-completion-suggest"]; diff --git a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs index 32cb480f930..2cb624ff0ed 100644 --- a/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs +++ b/src/CodeGeneration/Nest.Litterateur/AsciiDoc/AsciiVisitor.cs @@ -9,12 +9,16 @@ namespace Nest.Litterateur.AsciiDoc { + ///