View Source ExAliyunOts.Search (ex_aliyun_ots v0.15.2)

Use the multiple efficient index schemas of search index to solve complex query problems.

Here are links to the search section of Alibaba official document: Chinese | English

To use ExAliyunOts, a module that calls use ExAliyunOts has to be defined:

defmodule MyApp.Tablestore do
  use ExAliyunOts, instance: :my_instance
end

This automatically defines some search functions in MyApp.Tablestore module, we can use them as helpers when invoke MyApp.Tablestore.search/3, here are some examples:

import MyApp.Tablestore

search "table", "index_name",
  search_query: [
    query: match_query("age", 28),
    sort: [
      field_sort("age", order: :desc)
    ]
  ]

search "table", "index_name",
  search_query: [
    query: exists_query("column_a"),
    group_bys: [
      group_by_field("group_name", "column_b",
        sub_group_bys: [
          group_by_range("group_name_1", "column_d", [{0, 10}, {10, 20}])
        ],
        sort: [
          group_key_sort(:desc)
        ]
      ),
      group_by_field("group_name2", "column_c")
    ],
    aggs: [
      agg_min("aggregation_name", "column_e")
    ]
  ]

Please notice:

  • The statistics(via :aggs) and GroupBy type aggregations(via :group_bys) can be used at the same time.
  • The GroupBy type aggregations support the nested sub statistics(via :sub_aggs) and sub GroupBy type aggregations(via :sub_group_bys).
  • To ensure the performance and reduce the complexity of aggregations, there is a limitation with a certain number of levels for nesting.
  • If you are only care about using :aggs or :group_bys, meanwhile do not need the returned rows, you can set :limit as 0 to ignore the matched rows return, there will have a better query performance.

Summary

Query

Use BoolQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use ExistsQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use GeoBoundingBoxQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use GeoDistanceQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use GeoPolygonQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use MatchAllQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use MatchPhraseQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use MatchQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use NestedQuery as the nested :query option of :search_query option in ExAliyunOts.search/4, the target field need to be a nested type, it is used to query sub documents of nested type.

Use PrefixQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use RangeQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use RangeQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use TermQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use TermsQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Use WildcardQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Sort

Sort by the value of a column, use it in the nested :sort option of :search_query option in ExAliyunOts.search/4.

Geographic distance sorting, according to the sum of distances between to the input geographical points, sort by the minimum/maximum/average summation value.

Use for the nested type field in field_sort/2 as :nested_filter option, the input filter is a Query to filter results.

Sort by the primary key(s) of row, use it in the nested :sort option of :search_query option in ExAliyunOts.search/4.

Sort by the relevance score to apply the full-text indexing properly, use it in the nested :sort option of :search_query option in ExAliyunOts/search/4.

Aggregation

Calculate the average value of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Calculate the count of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Calculate the distinct count of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Calculate the maximum value of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Calculate the minimum value of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

A percentile value indicates the relative position of a value in a dataset. For example, when you collect statistics for the response time of each request during the routine O&M of your system, you must analyze the response time distribution by using percentiles such as p25, p50, p90, and p99.

Calculate the summation of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

After you group query results, you can query the rows in each group. This method can be used in a similar manner as ANY_VALUE(field) in MySQL.

GroupBy

The :group_bys results are grouped according to the value of a field, the same value will be put into a group, finally, the value of each group and the number corresponding to the value will be returned.

On the query results, group by filters (they're Query usecase), and then get the number of matched filters, the order of the returned results is the same as that of the added filter(s).

The query results are grouped according to the range from a certain center Geo point, if the distance difference is within a certain range, it will be put into a group, and finally the number of corresponding items in each range will be returned.

The aggregation method that can be used to group query results based on specific data intervals. Field values that are within the same range are grouped together. The value range of each group and the number of values in each group are returned.

The :group_bys results are grouped according to the range of a field, if the field value is within a range, it will be put into a group, finally, the number corresponding to the value will be returned.

Sort in GroupByField

Use in group_by_field/3 scenario, in ascending/descending order of field literal.

Use in group_by_field/3 scenario, in ascending/descending order of row(s) count.

Use in group_by_field/3 scenario, in ascending/descending order of the value from sub statistics.

Query

@spec bool_query(options()) :: map()

Use BoolQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: bool_query(
      must: range_query("age", from: 20, to: 32),
      must_not: term_query("age", 28)
    )
  ]

The following options can be a single Query or a list of Query to combine the "And | Or | At least" search condition.

Options

  • :must, specifies the Queries that the query result must match, this option is equivalent to the AND operator.
  • :must_not, specifies the Queries that the query result must not match, this option is equivalent to the NOT operator.
  • :should, specifies the Queries that the query result may or may not match, this option is equivalent to the OR operator.
  • :minimum_should_match, specifies the minimum number of :should that the query result must match.
Link to this function

exists_query(field_name)

View Source
@spec exists_query(field_name()) :: map()

Use ExistsQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: exists_query("values")
  ]
Link to this function

geo_bounding_box_query(field_name, top_left, bottom_right)

View Source
@spec geo_bounding_box_query(
  field_name(),
  top_left :: String.t(),
  bottom_right :: String.t()
) :: map()

Use GeoBoundingBoxQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore
search "table", "index_name",
  search_query: [
    query: geo_bounding_box_query("location", "10,-10", "-10,10")
  ]

Please notice that all geographic coordinates are in "$latitude,$longitude" format.

Link to this function

geo_distance_query(field_name, distance, center_point)

View Source
@spec geo_distance_query(
  field_name(),
  distance :: float() | integer(),
  center_point :: String.t()
) :: map()

Use GeoDistanceQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore
search "table", "index_name",
  search_query: [
    query: geo_distance_query("location", 500_000, "5,5")
  ]

Please notice that all geographic coordinates are in "$latitude,$longitude" format.

Link to this function

geo_polygon_query(field_name, geo_points)

View Source
@spec geo_polygon_query(field_name(), geo_points :: list()) :: map()

Use GeoPolygonQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: geo_polygon_query("location", ["11,11", "0,0", "1,5"])
  ]

Please notice that all geographic coordinates are in "$latitude,$longitude" format.

@spec match_all_query() :: map()

Use MatchAllQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: match_all_query()
  ]

Official document in Chinese | English

Link to this function

match_phrase_query(field_name, text)

View Source
@spec match_phrase_query(field_name(), text :: String.t()) :: map()

Use MatchPhraseQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Similar to MatchQuery, however, the location relationship of multiple terms after word segmentation will be considered, multiple terms after word segmentation must exist in the same order and location in the row data to be hit this query.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: match_phrase_query("content", "tablestore")
  ]
Link to this function

match_query(field_name, text, options \\ [])

View Source
@spec match_query(field_name(), text :: String.t(), options()) :: map()

Use MatchQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Example

import MyApp.TableStore
search "table", "index_name",
  search_query: [
    query: match_query("age", 28)
  ]

Official document in Chinese | English

Options

  • :minimum_should_match, the minimum number of terms that the value of the fieldName field in a row contains when Table Store returns this row in the query result, by default it's 1.
  • :operator, the operator used in a logical operation, by default it's Or, it means that as long as several terms after the participle are partially hit, they are considered hit this query.
Link to this function

nested_query(path, query, options \\ [])

View Source
@spec nested_query(path :: String.t(), query :: map() | Keyword.t(), options()) ::
  map()

Use NestedQuery as the nested :query option of :search_query option in ExAliyunOts.search/4, the target field need to be a nested type, it is used to query sub documents of nested type.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: nested_query(
      "content",
      term_query("content.header", "header1")
    )
  ]

Options

  • :score_mode, available options have :none | :avg | :max | :total | :min, by default it's :none.

Link to this function

prefix_query(field_name, prefix)

View Source
@spec prefix_query(field_name(), prefix :: String.t()) :: map()

Use PrefixQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: prefix_query("name", "n")
  ]
Link to this macro

range_query(arg)

View Source (macro)

Use RangeQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: range_query(1 <= "score" and "score" <= 10)
  ]

Supports

range_query("score" > 1)
range_query("score" >= 1)
range_query("score" < 10)
range_query("score" <= 10)
range_query(1 < "score" and "score" < 10)
range_query(1 <= "score" and "score" <= 10)
Link to this function

range_query(field_name, options)

View Source
@spec range_query(field_name(), Range.t() | options()) :: map()

Use RangeQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: range_query(
      "score",
      from: 60,
      to: 80,
      include_upper: false,
      include_lower: false
    )
  ]

# or support Range

search "table", "index_name",

search_query: [
  query: range_query("score", 60..80)
]

# equal to

search "table", "index_name",

search_query: [
  query: range_query("score", from: 60, to: 80)
]

Options

  • :from, the value of the start position.
  • :to, the value of the end position.
  • :include_lower, specifies whether to include the :from value in the result, available options are true | false, by default it's true.

  • :include_upper, specifies whether to include the :to value in the result, available options are true | false, by default it's true.

Link to this function

term_query(field_name, term)

View Source
@spec term_query(field_name(), term :: String.t()) :: map()

Use TermQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: term_query("age", 28)
  ]
Link to this function

terms_query(field_name, terms)

View Source
@spec terms_query(field_name(), terms :: list()) :: map()

Use TermsQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore
search "table", "index_name",
  search_query: [
    query: terms_query("age", [28, 29, 30])
  ]
Link to this function

wildcard_query(field_name, value)

View Source
@spec wildcard_query(field_name(), value :: String.t()) :: map()

Use WildcardQuery as the nested :query option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: wildcard_query("name", "n*")
  ]

Sort

Link to this function

field_sort(field_name, options \\ [])

View Source
@spec field_sort(field_name(), options()) :: map()

Sort by the value of a column, use it in the nested :sort option of :search_query option in ExAliyunOts.search/4.

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    sort: [
      field_sort("field_a", order: :desc)
    ]
  ]

If there's a nested type of search index, and they are a integer or float list, we can use :mode to sort according to the minimum/maximum/average value of the list, by default it's :nil.

For example, there's a nested type as "values" field, the following query will find "values" field existed as matched rows, and sort by the minimum value of list items.

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: exists_query("values"),
    sort: [
      field_sort("values", mode: :min)
    ]
  ]

Still for nested type of search index, we can sort by the nested value via :nested_filter option, for example, sort by the value of "content.header" in :desc order.

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: nested_query(
      "content",
      [
        exists_query("content.header")
      ]
    ),
    sort: [
      field_sort("content.header",
        order: :desc,
        nested_filter: nested_filter(
          "content",
          prefix_query("content.header", "header")
        )
      )
    ]
  ]

Please ensure that the query criteria matched will participate in sorting, if there exists any not matched case will lead to uncertainty of sorting results.

Options

  • :mode, optional, available options are :min | :max | :avg, by default it's :nil;

  • :order, optional, available options are :asc | :desc, by default it's :asc;

  • :nested_filter, optional, see nested_filter/2 for details.
Link to this function

geo_distance_sort(field_name, points, options)

View Source
@spec geo_distance_sort(field_name(), points :: list(), options()) :: map()

Geographic distance sorting, according to the sum of distances between to the input geographical points, sort by the minimum/maximum/average summation value.

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: geo_distance_query("location", 500_000, "5,5"),
    sort: [
      geo_distance_sort("location", ["5.14,5.21"], order: :asc)
    ]
  ]

The input points are a list of string, each format as "$latitude,$longitude".

Options

  • :order, optional, available options are :asc | :desc;

  • :mode, optional, used for nested type field within integer or float, as :min will sort by the minimum value of items, as :max will sort by the maximum value of items, as :avg will sort by the average value of items, by default it's :nil;
  • :distance_type, optional, available options are :arc | :plane, as :arc means distance calculated by arc surface, as :plane means distance calculated by plane.

Link to this function

nested_filter(path, filter)

View Source
@spec nested_filter(path :: String.t(), filter :: map()) :: map()

Use for the nested type field in field_sort/2 as :nested_filter option, the input filter is a Query to filter results.

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: nested_query(
      "content",
      [
        exists_query("content.header")
      ]
    ),
    sort: [
      field_sort("content.header",
        order: :desc,
        nested_filter: nested_filter(
          "content",
          prefix_query("content.header", "header")
        )
      )
    ]
  ]

Please ensure that the query criteria matched will participate in sorting, if there exists any not matched case will lead to uncertainty of sorting results.

@spec pk_sort(order()) :: map()

Sort by the primary key(s) of row, use it in the nested :sort option of :search_query option in ExAliyunOts.search/4.

Each search request use this sort by default.

@spec score_sort(order()) :: map()

Sort by the relevance score to apply the full-text indexing properly, use it in the nested :sort option of :search_query option in ExAliyunOts/search/4.

Aggregation

Link to this function

agg_avg(aggregation_name, field_name, options \\ [])

View Source
@spec agg_avg(aggregation_name(), field_name(), options()) :: map()

Calculate the average value of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_avg("agg_name", "score")
    ]
  ]

The aggregation_name can be any business description string, when get the calculated results, we need to use it to fetch them.

Options

  • :missing, when the field is not existed in a row of data, if :missing is not set, the row will be ignored in statistics; if :missing is set, the row will use :missing value to participate in the statistics of average value, by default it's nil (not-set).
Link to this function

agg_count(aggregation_name, field_name)

View Source
@spec agg_count(aggregation_name(), field_name()) :: map()

Calculate the count of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_sum("agg_name", "score")
    ]
  ]

The aggregation_name can be any business description string, when get the calculated results, we need to use it to fetch them.

If the field is not existed in a row of data, then this row does not participate in the statistics of count.

Link to this function

agg_distinct_count(aggregation_name, field_name, options \\ [])

View Source
@spec agg_distinct_count(aggregation_name(), field_name(), options()) :: map()

Calculate the distinct count of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_distinct_count("agg_name", "score")
    ]
  ]

The aggregation_name can be any business description string, when get the calculated results, we need to use it to fetch them.

Options

  • :missing, when the field is not existed in a row of data, if :missing is not set, the row will be ignored in statistics; if :missing is set, the row will use :missing value to participate in the statistics of distinct count, by default it's nil (not-set).
Link to this function

agg_max(aggregation_name, field_name, options \\ [])

View Source
@spec agg_max(aggregation_name(), field_name(), options()) :: map()

Calculate the maximum value of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_max("agg_name", "score")
    ]
  ]

The aggregation_name can be any business description string, when get the calculated results, we need to use it to fetch them.

Options

  • :missing, when the field is not existed in a row of data, if :missing is not set, the row will be ignored in statistics; if :missing is set, the row will use :missing value to participate in the statistics of maximum value, by default it's nil (not-set).
Link to this function

agg_min(aggregation_name, field_name, options \\ [])

View Source
@spec agg_min(aggregation_name(), field_name(), options()) :: map()

Calculate the minimum value of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_min("agg_name", "score")
    ]
  ]

The aggregation_name can be any business description string, when get the calculated results, we need to use it to fetch them.

Options

  • :missing, when the field is not existed in a row of data, if :missing is not set, the row will be ignored in statistics; if :missing is set, the row will use :missing value to participate in the statistics of minimum value, by default it's nil (not-set).
Link to this function

agg_percentiles(aggregation_name, field_name, percentiles, options \\ [])

View Source
@spec agg_percentiles(
  aggregation_name(),
  field_name(),
  percentiles :: [number()],
  options()
) :: map()

A percentile value indicates the relative position of a value in a dataset. For example, when you collect statistics for the response time of each request during the routine O&M of your system, you must analyze the response time distribution by using percentiles such as p25, p50, p90, and p99.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_percentiles("agg_name", "score", [0, 30, 50, 100], missing: 0.0)
    ]
  ]

Options

  • :missing, when the field is not existed in a row of data, if :missing is not set, the row will be ignored in statistics; if :missing is set, the row will use :missing value to participate in the statistics of distinct count, by default it's nil (not-set).
Link to this function

agg_sum(aggregation_name, field_name, options \\ [])

View Source
@spec agg_sum(aggregation_name(), field_name(), options()) :: map()

Calculate the summation of the assigned field by aggregation in the nested :aggs option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    aggs: [
      agg_sum("agg_name", "score")
    ]
  ]

The aggregation_name can be any business description string, when get the calculated results, we need to use it to fetch them.

Options

  • :missing, when the field is not existed in a row of data, if :missing is not set, the row will be ignored in statistics; if :missing is set, the row will use :missing value to participate in the statistics of summation value, by default it's nil (not-set).
Link to this function

agg_top_rows(aggregation_name, options \\ [])

View Source
@spec agg_top_rows(aggregation_name(), options()) :: map()

After you group query results, you can query the rows in each group. This method can be used in a similar manner as ANY_VALUE(field) in MySQL.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
    search_query: [
      query: match_all_query(),
      limit: 0,
      group_bys: [
        group_by_field(group_name, "type",
          sub_aggs: [
            agg_top_rows(sub_agg_name,
              limit: 2,
              sort: [
                field_sort("price", order: :asc)
              ]
            )
          ]
        )
      ]
   ]

Options

  • :limit, the maximum number of rows that can be returned for each group. By default, only 1 row of data is returned.
  • :sort, the sorting method that is used to sort data in groups.

GroupBy

Link to this function

group_by_field(group_name, field_name, options \\ [])

View Source
@spec group_by_field(group_name(), field_name(), options()) :: map()

The :group_bys results are grouped according to the value of a field, the same value will be put into a group, finally, the value of each group and the number corresponding to the value will be returned.

We can set it in the nested :group_bys option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_field("group_name", "type",
        size: 3,
        sub_group_bys: [
          group_by_field("sub_gn1", "is_actived")
        ],
        sort: [
          row_count_sort(:asc),
          group_key_sort(:desc)
        ]
      ),
      group_by_field("group_name2", "is_actived")
    ]
  ]

The group_name can be any business description string, when get the grouped results, we need to use it to fetch them.

Options

  • :sort, optional, add sorting rules for items in a group, by default, sort in descending order according to the quantity of items in the group. Support group_key_sort/1 | row_count_sort/1 | sub_agg_sort/2 sort.
  • :size, optional, the number of returned groups.
  • :sub_group_bys, optional, add sub GroupBy type aggregations.
  • :sub_aggs, optional, add sub statistics.
Link to this function

group_by_filter(group_name, filters, options \\ [])

View Source
@spec group_by_filter(group_name(), filters :: list(), options()) :: map()

On the query results, group by filters (they're Query usecase), and then get the number of matched filters, the order of the returned results is the same as that of the added filter(s).

We can set it in the nested :group_bys option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_filter(
        "group_name",
        [
          term_query("is_actived", true),
          range_query("price", from: 50)
        ]
      )
    ]
  ]

Options

  • :sub_group_bys, optional, add sub GroupBy type aggregations.
  • :sub_aggs, optional, add sub statistics.
Link to this function

group_by_geo_distance(group_name, field_name, ranges, options \\ [])

View Source
@spec group_by_geo_distance(group_name(), field_name(), ranges :: list(), options()) ::
  map()

The query results are grouped according to the range from a certain center Geo point, if the distance difference is within a certain range, it will be put into a group, and finally the number of corresponding items in each range will be returned.

We can set it in the nested :group_bys option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_geo_distance("test", "location",
        [
          {0, 100_000},
          {100_000, 500_000},
          {500_000, 1000_000},
        ],
        lon: 0,
        lat: 0,
        sub_aggs: [
          agg_sum("test_sum", "value")
        ]
      )
    ]
  ]

Options

  • :lon, required, the longitude of the origin center point, integer or float.
  • :lat, required, the latitude of the origin center point, integer or float.
  • :sub_group_bys, optional, add sub GroupBy type aggregations.
  • :sub_aggs, optional, add sub statistics.
Link to this function

group_by_histogram(group_name, field_name, interval, field_range, options \\ [])

View Source
@spec group_by_histogram(
  group_name(),
  field_name(),
  interval :: number(),
  field_range :: {number(), number()},
  options()
) :: map()

The aggregation method that can be used to group query results based on specific data intervals. Field values that are within the same range are grouped together. The value range of each group and the number of values in each group are returned.

We can set it in the nested :group_bys option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_histogram(
        "group_name",
        "price",        # histogram by field `price(double)`
        10.0,           # every `10.0` is a group
        {0.0, 100.0},   # from `0.0` to `100.0`
        missing: 0.0    # if `price` of a row is missing, the value will be treated as `0.0`
      )
    ]
  ]

Options

  • :missing, optional, the default value for the field that is used to perform the aggregation operation on a row when the field value is empty.
  • :min_doc_count, optional, the minimum number of rows. If the number of rows in a group is less than the minimum number of rows, the aggregation results for the group are not returned.
Link to this function

group_by_range(group_name, field_name, ranges, options \\ [])

View Source
@spec group_by_range(group_name(), field_name(), ranges :: list(), options()) :: map()

The :group_bys results are grouped according to the range of a field, if the field value is within a range, it will be put into a group, finally, the number corresponding to the value will be returned.

We can set it in the nested :group_bys option of :search_query option in ExAliyunOts.search/4.

Official document in Chinese | English

Example

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_range("group_name", "price",
        [
          {0, 18},
          {18, 50}
        ],
        sub_group_bys: [
          group_by_field("sorted_by_type", "type",
            sort: [
              group_key_sort(:asc)
            ]
          )
        ],
        sub_aggs: [
          agg_distinct_count("distinct_price", "price")
        ]
      )
    ]
  ]

The group_name can be any business description string, when get the grouped results, we need to use it to fetch them.

Please notice that each range item(as a tuple, according to {from, to}) of ranges, its start is greater than or equal to from, and its ending is less than to, the range interval value can be integer or float.

Options

  • :sub_group_bys, optional, add sub GroupBy type aggregations.
  • :sub_aggs, optional, add sub statistics.

Define Field Schema

Link to this function

field_schema_boolean(field_name, options \\ [])

View Source
@spec field_schema_boolean(field_name(), options()) :: map()

Official document in Chinese | English

Example

field_schema_boolean("status")

Options

  • :index, specifies whether to set as index, by default it is true;
  • :enable_sort_and_agg, specifies whether to support sort and statistics, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :is_array, specifies whether the stored data is a JSON encoded list as a string, e.g. "[false,true,false]".
  • :is_virtual_field, specifies whether the field is a virtual column, by default it is false. This parameter is required only when you use virtual columns.
  • :source_field_name, specifies the name of the source field to which the virtual column is mapped in the data table. This parameter is required when :is_virtual_field is set to true.
Link to this function

field_schema_float(field_name, options \\ [])

View Source
@spec field_schema_float(field_name(), options()) :: map()

Official document in Chinese | English

Example

field_schema_float("price")

Options

  • :index, specifies whether to set as index, by default it is true;
  • :enable_sort_and_agg, specifies whether to support sort and statistics, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :is_array, specifies whether the stored data is a JSON encoded list as a string, e.g. "[1.0,2.0]".
  • :is_virtual_field, specifies whether the field is a virtual column, by default it is false. This parameter is required only when you use virtual columns.
  • :source_field_name, specifies the name of the source field to which the virtual column is mapped in the data table. This parameter is required when :is_virtual_field is set to true.
Link to this function

field_schema_geo_point(field_name, options \\ [])

View Source

Official document in Chinese | English

Example

field_schema_geo_point("location")

Options

  • :index, specifies whether to set as index, by default it is true;
  • :enable_sort_and_agg, specifies whether to support sort and statistics, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :is_array, specifies whether the stored data is a JSON encoded list as a string, e.g. "["10.21,10","10.31,9.98"]".
  • :is_virtual_field, specifies whether the field is a virtual column, by default it is false. This parameter is required only when you use virtual columns.
  • :source_field_name, specifies the name of the source field to which the virtual column is mapped in the data table. This parameter is required when :is_virtual_field is set to true.
Link to this function

field_schema_integer(field_name, options \\ [])

View Source
@spec field_schema_integer(field_name(), options()) :: map()

Official document in Chinese | English

Example

field_schema_integer("age")

Options

  • :index, specifies whether to set as index, by default it is true;
  • :enable_sort_and_agg, specifies whether to support sort and statistics, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :is_array, specifies whether the stored data is a JSON encoded list as a string, e.g. "[1,2]".
  • :is_virtual_field, specifies whether the field is a virtual column, by default it is false. This parameter is required only when you use virtual columns.
  • :source_field_name, specifies the name of the source field to which the virtual column is mapped in the data table. This parameter is required when :is_virtual_field is set to true.
Link to this function

field_schema_keyword(field_name, options \\ [])

View Source

Official document in Chinese | English

Example

field_schema_keyword("status")

Options

  • :index, specifies whether to set as index, by default it is true;
  • :enable_sort_and_agg, specifies whether to support sort and statistics, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :is_array, specifies whether the stored data is a JSON encoded list as a string, e.g. "["a","b"]".
  • :is_virtual_field, specifies whether the field is a virtual column, by default it is false. This parameter is required only when you use virtual columns.
  • :source_field_name, specifies the name of the source field to which the virtual column is mapped in the data table. This parameter is required when :is_virtual_field is set to true.
Link to this function

field_schema_nested(field_name, options \\ [])

View Source

Official document in Chinese | English

Example

field_schema_nested(
  "content",
  field_schemas: [
    field_schema_keyword("header"),
    field_schema_keyword("body"),
  ]

Options

  • :field_schemas, required, the nested field schema(s);
  • :index, specifies whether to set as index, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :enable_sort_and_agg, specifies whether to support sort and statistics, by default it is true.
Link to this function

field_schema_text(field_name, options \\ [])

View Source

Official document in Chinese | English

Example

field_schema_text("content")

Options

  • :index, specifies whether to set as index, by default it is true;
  • :store, specifies whether to store the origin value in search index for a better read performance, by default it is true;
  • :is_array, specifies whether the stored data is a JSON encoded list as a string, e.g. "["a","b"]".
  • :analyzer, optional, please see analyzer document in Chinese | English.
  • :analyzer_parameter, optional, please see analyzer document in Chinese | English.
  • :is_virtual_field, specifies whether the field is a virtual column, by default it is false. This parameter is required only when you use virtual columns.
  • :source_field_name, specifies the name of the source field to which the virtual column is mapped in the data table. This parameter is required when :is_virtual_field is set to true.

Sort in GroupByField

@spec group_key_sort(order()) :: map()

Use in group_by_field/3 scenario, in ascending/descending order of field literal.

Official document in Chinese | English

Example

In the following example, the returned results will be sorted in descending order of the "type" field:

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_field(
        "group_name",
        "type",
        sub_group_bys: [
          ...
        ],
        sort: [
          group_key_sort(:desc)
        ]
      )
    ]
  ]
@spec row_count_sort(order()) :: %ExAliyunOts.Var.Search.RowCountSort{order: term()}

Use in group_by_field/3 scenario, in ascending/descending order of row(s) count.

Official document in Chinese | English

Example

In the following example, the returned results will be sorted in ascending order of the matched row(s):

import MyApp.TableStore

search "table", "index_name",
  search_query: [
    query: ...,
    group_bys: [
      group_by_field(
        "group_name",
        "type",
        sub_group_bys: [
          ...
        ],
        sort: [
          row_count_sort(:asc)
        ]
      )
    ]
  ]
Link to this function

sub_agg_sort(sub_agg_name, order)

View Source
@spec sub_agg_sort(sub_agg_name :: String.t(), order()) :: map()

Use in group_by_field/3 scenario, in ascending/descending order of the value from sub statistics.

Official document in Chinese | English

Types

@type aggregation_name() :: String.t()
@type field_name() :: String.t()
@type group_name() :: String.t()
@type options() :: Keyword.t()
@type order() :: :asc | :desc

Functions

Link to this function

map_scan_options(var, options)

View Source