Sort Usage

edit

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.

Fluent DSL example

edit
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.Tags.First().Added)
        .Order(SortOrder.Descending)
        .MissingLast()
        .UnmappedType(FieldType.Date)
        .Mode(SortMode.Average)
        .Nested(n => n
            .Path(p => p.Tags)
            .Filter(q => q.MatchAll())
        )
    )
    .Field(f => f
        .Field(p => p.NumberOfCommits)
        .Order(SortOrder.Descending)
        .Missing(-1)
    )
    .GeoDistance(g => g
        .Field(p => p.LocationPoint)
        .DistanceType(GeoDistanceType.Arc)
        .Order(SortOrder.Ascending)
        .Unit(DistanceUnit.Centimeters)
        .Mode(SortMode.Min)
        .Points(new GeoLocation(70, -70), new GeoLocation(-12, 12))
    )
    .GeoDistance(g => g
        .Field(p => p.LocationPoint)
        .Points(new GeoLocation(70, -70), new GeoLocation(-12, 12))
    )
    .Script(sc => sc
        .Type("number")
        .Ascending()
        .Script(script => script
            .Source("doc['numberOfCommits'].value * params.factor")
            .Params(p => p.Add("factor", 1.1))
        )
    )
)

Object Initializer syntax example

edit
new SearchRequest<Project>
{
    Sort = new List<ISort>
    {
        new FieldSort { Field = "startedOn", Order = SortOrder.Ascending },
        new FieldSort { Field = "name", Order = SortOrder.Descending },
        new FieldSort { Field = "_score", Order = SortOrder.Descending },
        new FieldSort { Field = "_doc", Order = SortOrder.Ascending },
        new FieldSort
        {
            Field = Field<Project>(p => p.Tags.First().Added),
            Order = SortOrder.Descending,
            Missing = "_last",
            UnmappedType = FieldType.Date,
            Mode = SortMode.Average,
            Nested = new NestedSort
            {
                Path = Field<Project>(p => p.Tags),
                Filter = new MatchAllQuery()
            }
        },
        new FieldSort
        {
            Field = Field<Project>(p => p.NumberOfCommits),
            Order = SortOrder.Descending,
            Missing = -1
        },
        new GeoDistanceSort
        {
            Field = "locationPoint",
            Order = SortOrder.Ascending,
            DistanceType = GeoDistanceType.Arc,
            Unit = DistanceUnit.Centimeters,
            Mode = SortMode.Min,
            Points = new[] { new GeoLocation(70, -70), new GeoLocation(-12, 12) }
        },
        new GeoDistanceSort
        {
            Field = "locationPoint",
            Points = new[] { new GeoLocation(70, -70), new GeoLocation(-12, 12) }
        },
        new ScriptSort
        {
            Type = "number",
            Order = SortOrder.Ascending,
            Script = new InlineScript("doc['numberOfCommits'].value * params.factor")
            {
                Params = new Dictionary<string, object>
                {
                    { "factor", 1.1 }
                }
            }
        }
    }
}

Example json output.

{
  "sort": [
    {
      "startedOn": {
        "order": "asc"
      }
    },
    {
      "name": {
        "order": "desc"
      }
    },
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "_doc": {
        "order": "asc"
      }
    },
    {
      "tags.added": {
        "missing": "_last",
        "order": "desc",
        "mode": "avg",
        "nested": {
          "path": "tags",
          "filter": {
            "match_all": {}
          }
        },
        "unmapped_type": "date"
      }
    },
    {
      "numberOfCommits": {
        "missing": -1,
        "order": "desc"
      }
    },
    {
      "_geo_distance": {
        "locationPoint": [
          {
            "lat": 70.0,
            "lon": -70.0
          },
          {
            "lat": -12.0,
            "lon": 12.0
          }
        ],
        "order": "asc",
        "mode": "min",
        "distance_type": "arc",
        "unit": "cm"
      }
    },
    {
      "_geo_distance": {
        "locationPoint": [
          {
            "lat": 70.0,
            "lon": -70.0
          },
          {
            "lat": -12.0,
            "lon": 12.0
          }
        ]
      }
    },
    {
      "_script": {
        "order": "asc",
        "type": "number",
        "script": {
          "params": {
            "factor": 1.1
          },
          "source": "doc['numberOfCommits'].value * params.factor"
        }
      }
    }
  ]
}

Nested sort usage

edit

In Elasticsearch 6.1.0+, using nested_path and nested_filter for sorting on fields mapped as nested types is deprecated. Instead, you should use the nested sort instead.

s => s
.Sort(ss => ss
    .Field(f => f
        .Field(p => p.Tags.First().Added)
        .Order(SortOrder.Descending)
        .MissingLast()
        .UnmappedType(FieldType.Date)
        .Mode(SortMode.Average)
        .Nested(n => n
            .Path(p => p.Tags)
            .Filter(ff => ff
                .MatchAll()
            )
            .MaxChildren(50)
        )
    )
)

Object Initializer syntax example

edit
new SearchRequest<Project>
{
    Sort = new List<ISort>
    {
        new FieldSort
        {
            Field = Field<Project>(p => p.Tags.First().Added),
            Order = SortOrder.Descending,
            Missing = "_last",
            UnmappedType = FieldType.Date,
            Mode = SortMode.Average,
            Nested = new NestedSort
            {
                Path = Field<Project>(p => p.Tags),
                Filter = new MatchAllQuery(),
                MaxChildren = 50
            }
        }
    }
}

Example json output.

{
  "sort": [
    {
      "tags.added": {
        "missing": "_last",
        "order": "desc",
        "mode": "avg",
        "nested": {
          "path": "tags",
          "filter": {
            "match_all": {}
          },
          "max_children": 50
        },
        "unmapped_type": "date"
      }
    }
  ]
}