数据类型

DataFrame

DataFrame 表示具有相同命名列的逻辑行集,类似于 Pandas DataFrameSpark DataFrame

可以从 sql 创建一个 DataFrame:

python

  1. from greptime import PyDataFrame, col
  2. @copr(returns = ["value"])
  3. def query_numbers() -> vector[f64]:
  4. df = PyDataFrame.from_sql("select number from numbers")
  5. return df.filter(col('number') <= 5).collect()[0]

这与 select number from numbers where number <=5 相同,但使用了 DataFrame API。

事实上,协处理器的 DataFrame API 是 Apache Datafusion DataFrame API 的一个封装器。请参考 API 文档以获得完整的 DataFrame API。

向量

向量是协处理器中的主要数据类型,它是同类值的向量。通常,它是查询结果中提取的一列,但也可以在 Python 脚本中构建它。

向量就像编程语言中的数组类型,Apache Arrow 中的 ArrayNumPy 中的 NDArray

向量类型

协处理器引擎支持以下类型的向量:

TypeDescription
vector[str]The string type
vector[bool]The boolean type
vector[u8]The 8-bit unsigned integer type
vector[u16]The 16-bit unsigned integer type
vector[u32]The 32-bit unsigned integer type
vector[u64]The 64-bit unsigned integer type
vector[i8]The 8-bit signed integer type
vector[i16]The 16-bit signed integer type
vector[i32]The 32-bit signed integer type
vector[i64]The 64-bit signed integer type
vector[f32]The 32-bit floating point type
vector[f64]The 64-bit floating point type
vector[none]The any type

正如我们在 Hello, world 的例子中看到的那样,如果我们想把它作为 SQL UDF 使用,我们可以为协处理器定义返回向量类型。否则,我们可以忽略返回向量类型的声明:

python

  1. @coprocessor(returns=['msg'])
  2. def hello() -> vector[str]:
  3. return "hello, GreptimeDB"

协处理器引擎会根据结果推断出返回向量的类型。但是如果没有声明,除非通过 HTTP API,不然就不能在 SQL 中调用它。

构建一个向量

之前已经展示了在函数中通过执行 @coprocessor 中的 sql 属性从查询结果中提取向量的例子。

我们可以从字面意义上创建一个向量:

python

  1. @copr(returns=["value"])
  2. def answer() -> vector[i64]:
  3. return 42

结果 42 将被包装成 vector[i64] 的一个元素的向量。

sql

  1. mysql> select answer();
  2. +----------+
  3. | answer() |
  4. +----------+
  5. | 42 |
  6. +----------+
  7. 1 row in set (0.01 sec)

我们可以从一个 Python 列表中创建一个向量:

python

  1. from greptime import vector
  2. @copr(returns=["value"])
  3. def answer() -> vector[i64]:
  4. return vector([42, 43, 44])

greptime 是一个内置模块,请参考 API 文档。

sql

  1. mysql> select answer();
  2. +----------+
  3. | answer() |
  4. +----------+
  5. | 42 |
  6. | 43 |
  7. | 44 |
  8. +----------+
  9. 3 rows in set (0.02 sec)

事实上,vector 函数可以从 Python 的任何可迭代对象中创建一个向量。但是它要求所有的元素类型必须相同,而且它选择第一个元素的类型作为它的向量类型。

向量操作

向量支持很多操作:

  1. 支持基本的算术运算,包括 +-*/
  2. 支持基本的逻辑运算,包括 &, |, ~
  3. 也支持基本的比较操作,包括 >, <, >=, <=, ==, !=

注意:这里我们覆盖了 bitwise 和 &,bitwise 或 |,bitwise 不是 ~ 的逻辑运算符,因为 Python 不支持逻辑运算符的覆盖(不能覆盖 and or not)。 PEP335 提出了一个建议,最终被拒绝。但是位操作符的优先级比比较操作符高,所以记得使用一对小括号来确保结果是想要的。 即如果想过滤一个在 0 和 100 之间的向量,应该使用 (vector[i32] >= 0) & (vector[i32] <= 100) 而不是 vector[i32] >= 0 & vector[i32] <= 100。后者将被评估为 vector[i32] >= (0 & vector[i32]) <= 100

例如,可以将两个向量相加:

python

  1. @copr(args=["n1", "n2"],
  2. returns=["value"],
  3. sql="select number as n1,number as n2 from numbers limit 5")
  4. def add_vectors(n1, n2) -> vector[i32]:
  5. return n1 + n2

或者用 Numpy 的方式对一个 bool 数组做比较:

python

  1. from greptime import vector
  2. @copr(returns=["value"])
  3. def compare() -> vector[bool]:
  4. # This returns a vector([False, False, True])
  5. return vector([1.0, 2.0, 3.0]) > 2.0

并使用 bool 数组的索引:

python

  1. from greptime import vector
  2. @copr(returns=["value"])
  3. def boolean_array() -> vector[f64]:
  4. v = vector([1.0, 2.0, 3.0])
  5. # This returns a vector([2.0])
  6. return v[(v > 1) & (v< 3)]

也支持两个向量之间的比较:

python

  1. from greptime import vector
  2. @copr(returns=["value"])
  3. def compare_vectors() -> vector[bool]:
  4. # This returns a vector([False, False, True])
  5. return vector([1.0, 2.0, 3.0]) > vector([1.0, 2.0, 2.0])

使用一个有索引的 bool 数组从一个向量中选择元素:

python

  1. from greptime import vector
  2. @copr(returns=["value"])
  3. def select_elements() -> (vector[f64]):
  4. a = vector([1.0, 2.0, 3.0])
  5. # This returns a vector([2.0, 3.0])
  6. return a[a>=2.0]

当然,我们可以使用列表理解法来构造一个新的向量:

python

  1. from greptime import vector
  2. @copr(returns=["value"])
  3. def list_comprehension() -> (vector[f64]):
  4. a = vector([1.0, 2.0, 3.0])
  5. # This returns a vector([3.0, 4.0])
  6. return [x+1 for x in a if a >= 2.0]