All Products
Search
Document Center

PolarDB:Agtype

Last Updated:Mar 25, 2025

Agtype is a custom data type used by AGE and is the only data type returned. Agtype is a superset of JSON and a custom implementation of JSONB.

Simple data types

Simple data types (also known as basic data types) refer to the most basic data units. In most cases, they are directly supported by programming languages, and can be stored directly in variables. Simple data types include integers, floating-point numbers, characters, and Boolean values. The following list introduces simple data types:

  • NULL: represents missing or undefined values.

  • Integer: represents numbers without decimal parts. For example, in Python you can use int to declare a variable of the integer type.

  • Float: represents numbers that contain decimal parts. For example, in Python you can use float to represent the floating-point number data type.

  • Numeric: stores numbers with a very large number of digits.

  • Bool: indicates the true or false state. Most programming languages use the bool data type to represent Boolean values. The values include True and False.

  • String: represents a single character. In many programming languages, such as C and Java, the character data type is usually represented by char.

NULL

In Cypher, a null is used to represent a missing or undefined value. Conceptually, null represents "a missing unknown value" and it is treated differently from other values. For example, if you try to get a property from a vertex but that property does not exist, null is returned. Most expressions that take null as input produce null. This includes Boolean expressions used as predicates in WHERE clauses. In this case, anything that is not true is interpreted as being false. Note that null is not equal to null. Not knowing two values does not mean that they are the same value. Therefore, the expression null = null returns null instead of true.

Input and output formats

SELECT * FROM cypher('graph_name', $$
    RETURN NULL
$$) AS (null_result agtype);

A null is returned as an empty space. Sample result:

 null_result 
-------------
 
(1 row)

Agtype NULL and Postgres NULL

The concept of NULL in Agtype and Postgres is the same as it is in Cypher.

Integer

The integer data type stores whole numbers (numbers without decimal parts). The integer data type is a 64-bit field that can store values ranging from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. Attempts to store values outside this range result in errors.

The integer type is commonly used because it offers the best balance between range, storage size, and performance. The smallint type is generally used only if disk space is insufficient. The bigint type is designed to be used when the range of the integer type is insufficient.

Input and output formats

SELECT * FROM cypher('graph_name', $$
    RETURN 1
$$) AS (int_result agtype);

Sample result:

 int_result 
------------
 1
(1 row)

Float

The Float data type is an inexact, variable-precision numeric type, conforming to the IEEE-754 Standard.

Inexact means that some values cannot be converted exactly to the internal format and are stored as approximations, so that storing and retrieving a value might show slight discrepancies. Managing these errors and how they propagate through calculations is the subject of an entire branch of mathematics and computer science and will not be discussed here, except for the following points:

  • If you require exact storage and calculations (such as for monetary amounts), use the numeric data type.

  • If you want to perform complicated calculations with these types for important tasks, especially if you rely on certain behavior in boundary cases (infinity, underflow), you must evaluate the implementation carefully.

  • Comparing two floating-point values for equality might not always work as expected.

Values that are too large or too small cause errors. Rounding may occur if the precision of an input number is too high Numbers too close to zero that are not representable as distinct from zero cause underflow errors.

In addition to ordinary numeric values, the float data type have several special values:

  • Infinity

  • -Infinity

  • NaN

When writing these values as constants in a Cypher command, you must put quotes around them and typecast them, for example:

SET x.float_value = '-Infinity'::float

On input, these strings are recognized in a case-insensitive manner.

Note

Note IEEE754 specifies that NaN should not compare equal to any other floating-point value (including NaN). However, in order to allow floats to be sorted correctly, AGE evaluates 'NaN'::float = 'NaN'::float to true. For more information, see Comparability, Equality, Orderliness and Equivalence.

Input and output formats

Use the float type to represent a number with a decimal part.

SELECT * FROM cypher('graph_name', $$
    RETURN 1.0
$$) AS (float_result agtype);

Sample result:

 float_result 
--------------
 1.0
(1 row)

Numeric

The numeric data type is used to store numbers with a very large number of digits. It is especially recommended for storing monetary amounts and other quantities where exactness is required. Calculations with numeric values yield exact results via basic calculations including addition, subtraction, and multiplication. However, calculations on numeric values are very slow compared to the integer or float data types.

Terms

  • Precision: The precision of a numeric is the total count of significant digits in the whole number, that is, the number of digits to both sides of the decimal point.

  • Scale: The scale of a numeric is the count of decimal digits in the fractional part (to the right of the decimal point).

So the number 23.5141 has a precision of 6 and a scale of 4. Integers can be considered to have a scale of zero.

Without any precision or scale creates a column in which numeric values of any precision and scale can be stored, up to the implementation limit on precision. A column of this kind will not coerce input values to any particular scale, whereas numeric columns with a declared scale will coerce input values to that scale.

Note
  • The SQL standard requires a default scale of 0, which means coercion to integer precision. This is considered useless by Apache. If you are concerned about portability, always specify the precision and scale explicitly.

  • The maximum allowed precision when explicitly specified in the type declaration is 1000; NUMERIC without a specified precision is subject to the limits described in Table 8.2.

If the scale of a value to be stored is greater than the declared scale of the column, the system will round the value to the specified number of fractional digits. Then, if the number of digits to the left of the decimal point exceeds the declared precision minus the declared scale, an error is returned.

numeric values are physically stored without any extra leading or trailing zeroes. Therefore, the declared precision and scale of a column are maximums, not fixed allocations. (In this sense the numeric type is more akin to varchar(n) than to char(n)). The actual storage requirement is two bytes for each group of four decimal digits, plus three to eight bytes overhead.

In addition to ordinary numeric values, the numeric type allows the special value NaN, meaning not-a-number. Any operation on NaN yields another NaN. When writing this value as a constant in an SQL command, you must put quotes around it, for example:

UPDATE table SET x = 'NaN'
Note

IEEE754 specifies that NaN is considered not equal to any other numeric value (including NaN). However, in order to allow floats to be sorted correctly, AGE evaluates 'NaN'::float = 'NaN'::float to true. For more information, see Comparability, Equality, Orderliness and Equivalence.

When rounding values, the numeric type rounds ties away from zero, while (on most machines) the real and double types round ties to the nearest even number.

Input and output formats

When you create data of the numeric type, the ::numeric annotation is required.

SELECT * FROM cypher('graph_name', $$
    RETURN 1.0::numeric
$$) AS (numeric_result agtype);

Sample result:

 numeric_result 
----------------
 1::numeric
(1 row)

Bool

AGE provides the standard Cypher type boolean. The boolean type can have several states: "true", "false", and a third state, "unknown", which is represented by the Agtype null value.

Boolean constants can be represented in Cypher queries by the keywords TRUE, FALSE, and NULL.

Input and output formats

SELECT * FROM cypher('graph_name', $$
    RETURN TRUE
$$) AS (boolean_result agtype);

Unlike PostgreSQL, AGE's boolean outputs as the full word such as true and false, rather than t and f. Sample result:

 boolean_result 
----------------
 true
(1 row)

String

An Agtype string literal can contain the following escape sequences:

Escape sequence

Character

\t

Tab

\b

Backspace

\n

Newline

\r

Carriage return

\f

Form feed

\'

Single quote

\"

Double quote

\\

Backslash

\uXXXX

Unicode UTF-16 code point (\u must be followed by 4 hexadecimal digits).

Input and output formats

Use single quotes 'to identify a string. The output uses double quotes ".

SELECT * FROM cypher('graph_name', $$
    RETURN 'This is a string'
$$) AS (string_result agtype);

Sample result:

   string_result    
--------------------
 "This is a string"
(1 row)

Composite data types

A composite data type is a data structure composed of one or more simple data types that can store and manage more complex information. See the following common composite data types:

  • Array: a linear data structure whose elements have the same type and can be accessed by index.

  • List: similar to arrays, but allows more flexible insert and delete operations.

  • Dictionary /Map: a collection of key-value pairs. You can use a unique key to access the corresponding value.

  • Set: an unordered collection that contains no duplicate elements.

  • Tuple: a fixed-size ordered collection that can contain multiple types of elements.

Each composite data type provides specific benefits and can play an important role in specific scenarios. Choosing the right data type is critical to writing efficient and maintainable code.

List

Note

All examples use the WITH clause and RETURN clause.

Lists in general

A literal list is created by using brackets and separating the elements in the list with commas.

Example
SELECT * FROM cypher('graph_name', $$
    WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst
$$) AS (lst agtype);

Sample result:

                lst                 
------------------------------------
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(1 row)

NULL in a List

A list can hold the value NULL, unlike when a NULL is an independent value, it will appear as the word null in the list.

Example
SELECT * FROM cypher('graph_name', $$
    WITH [null] as lst
    RETURN lst
$$) AS (lst agtype);

Sample result:

  lst   
--------
 [null]
(1 row)

Access individual elements

To access individual elements in the list, the square brackets are used. This extracts from the start index and up to but not including the end index.

Example
SELECT * FROM cypher('graph_name', $$
    WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst[3]
$$) AS (element agtype);

Sample result:

 element 
---------
 3
(1 row)

Map elements in Lists

Example
SELECT * FROM cypher('graph_name', $$
   WITH [0, {key: 'key_value'}, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst
$$) AS (map_value agtype);

Sample result:

                       map_value                       
-------------------------------------------------------
 [0, {"key": "key_value"}, 2, 3, 4, 5, 6, 7, 8, 9, 10]
(1 row)

Access map elements in Lists

Example
SELECT * FROM cypher('graph_name', $$
   WITH [0, {key: 'key_value'}, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst[1].key
$$) AS (map_value agtype);

Sample result:

  map_value  
-------------
 "key_value"
(1 row)

Negative index access

You can also use negative numbers to start from the end of the list instead.

Example
SELECT * FROM cypher('graph_name', $$
    WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst[-3]
$$) AS (element agtype);

Sample result:

 element 
---------
 8
(1 row)

Index ranges

You can use ranges inside the brackets to return ranges of the list.

Example
SELECT * FROM cypher('graph_name', $$
    WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst[0..3]
$$) AS (element agtype);

Sample result:

  element  
-----------
 [0, 1, 2]
(1 row)

Negative index ranges

Example
SELECT * FROM cypher('graph_name', $$
    WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst[0..-5]
$$) AS (element agtype);

Sample result:

      element       
--------------------
 [0, 1, 2, 3, 4, 5]
(1 row)

Positive slices

Example
SELECT * FROM cypher('graph_name', $$
    WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
    RETURN lst[..4]
$$) AS (lst agtype);

Sample result:

     lst      
--------------
 [0, 1, 2, 3]
(1 row)

Negative slices

Example
  • SELECT * FROM cypher('graph_name', $$
        WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
        RETURN lst[-5..]
    $$) AS (lst agtype);

    Sample result:

           lst        
    ------------------
     [6, 7, 8, 9, 10]
    (1 row)
  • Out-of-bound slices are simply truncated, but out-of-bound single elements return null.

    • SELECT * FROM cypher('graph_name', $$
          WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
          RETURN lst[15]
      $$) AS (element agtype);

      Sample result:

       element 
      ---------
       
      (1 row)
    • SELECT * FROM cypher('graph_name', $$
          WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
          RETURN lst[5..15]
      $$) AS (element agtype);

      Sample result:

             element       
      ---------------------
       [5, 6, 7, 8, 9, 10]
      (1 row)

Map

Maps can be constructed by using Cypher.

Maps with simple data types

You can construct a simple map with simple agtypes

Example
SELECT * FROM cypher('graph_name', $$
    WITH {int_key: 1, float_key: 1.0, numeric_key: 1::numeric, bool_key: true, string_key: 'Value'} as m
    RETURN m
$$) AS (m agtype);

Sample result:

                                                  m                                                   
------------------------------------------------------------------------------------------------------
 {"int_key": 1, "bool_key": true, "float_key": 1.0, "string_key": "Value", "numeric_key": 1::numeric}
(1 row)

Maps with composite data types

A map can also contain composite data types, such as lists and other maps.

Example
SELECT * FROM cypher('graph_name', $$
    WITH {listKey: [{inner: 'Map1'}, {inner: 'Map2'}], mapKey: {i: 0}} as m
    RETURN m
$$) AS (m agtype);

Sample result:

                                    m                                    
-------------------------------------------------------------------------
 {"mapKey": {"i": 0}, "listKey": [{"inner": "Map1"}, {"inner": "Map2"}]}
(1 row)

Access map properties

Example
SELECT * FROM cypher('graph_name', $$
    WITH {int_key: 1, float_key: 1.0, numeric_key: 1::numeric, bool_key: true, string_key: 'Value'} as m
    RETURN m.int_key
$$) AS (int_key agtype);

Sample result:

 int_key 
---------
 1
(1 row)

Access list elements in map

Examples
SELECT * FROM cypher('graph_name', $$
    WITH {listKey: [{inner: 'Map1'}, {inner: 'Map2'}], mapKey: {i: 0}} as m
    RETURN m.listKey[0]
$$) AS (m agtype);

Sample result:

         m         
-------------------
 {"inner": "Map1"}
(1 row)

Simple entities

An entity has a unique, comparable identity which defines whether or not two entities are equal.

An entity is assigned a set of properties, each of which are uniquely identified in the set by the irrespective property keys.

GraphId

Simple entities are assigned a unique graphid. A graphid is a unique composition of the entity's label ID and a unique sequence assigned to each label. Note that there will be ID overlaps when comparing entities from different graphs.

Labels

A label is an identifier that classifies vertices and edges into certain categories.

  • Edges must have labels, but vertices do not.

  • The names of labels between vertices and edges cannot overlap.

For more information about how to create entities with labels, see CREATE.

Properties

Both vertices and edges can have properties. Properties are attribute values, and each attribute name should be defined only as a string type.

Vertex

  • A vertex is the basic entity of the graph, with the unique attribute of being able to exist independently.

  • A vertex can be assigned a label.

  • A vertex may have zero or more outgoing edges.

  • A vertex may have zero or more incoming edges.

Data format:

Property

Description

id

The graphid of this vertex.

label

The label name of this vertex.

properties

The properties associated with this vertex.

Output:

{id:1; label: 'label_name'; properties: {prop1: value1, prop2: value2}}::vertex

Type cast a map to a vertex

Example

SELECT * FROM cypher('graph_name', $$
 WITH {id: 0, label: "label_name", properties: {i: 0}}::vertex as v
 RETURN v
$$) AS (v agtype);

Sample result:

                                v                                 
------------------------------------------------------------------
 {"id": 0, "label": "label_name", "properties": {"i": 0}}::vertex
(1 row)

Edge

An edge is an entity that encodes a directed connection between exactly two nodes, the source node and the target node. An outgoing edge is a directed relationship from the point of view of its source node. An incoming edge is a directed relationship from the point of view of its target node. An edge is assigned only one edge type.

Data format:

Property

Description

id

The graphid of this vertex.

startid

The graphid of the source node.

endid

The graphid of the target node.

label

The label name of this vertex.

properties

The properties associated with this vertex.

Output:

{id: 3; startid: 1; endid: 2; label: 'edge_label' properties{prop1: value1, prop2: value2}}::edge

Type cast a map to an edge

Example

SELECT * FROM cypher('graph_name', $$
 WITH {id: 2, start_id: 0, end_id: 1, label: "label_name", properties: {i: 0}}::edge as e
 RETURN e
$$) AS (e agtype);

Sample result:

                                             e                                              
--------------------------------------------------------------------------------------------
 {"id": 2, "label": "label_name", "end_id": 1, "start_id": 0, "properties": {"i": 0}}::edge
(1 row)

Composite entities

A composite entity is an entity composed of multiple parts or child entities. These child entities can be simple data types or other composite entities. In programming and data structures, composite entities are often used to represent complex data models, such as objects, arrays, and records.

Path

A path is a series of alternating vertices and edges. A path must start with a vertex, and have at least one edge.

Type cast a List to a Path

Example
SELECT * FROM cypher('graph_name', $$
 WITH [{id: 0, label: "label_name_1", properties: {i: 0}}::vertex,
            {id: 2, start_id: 0, end_id: 1, label: "edge_label", properties: {i: 0}}::edge,
           {id: 1, label: "label_name_2", properties: {}}::vertex
           ]::path as p
 RETURN p
$$) AS (p agtype);

The result is formatted to improve readability. Sample result:

                                                                                                                  p                                                                                                                  
 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
 [{"id": 0, "label": "label_name_1", "properties": {"i": 0}}::vertex, {"id": 2, "label": "edge_label", "end_id": 1, "start_id": 0, "properties": {"i": 0}}::edge, {"id": 1, "label": "label_name_2", "properties": {}}::vertex]::path
(1 row)