{#scalar-scalar-functions} # 스칼라 함수 값을 받아 하나의 값을 반환하는 함수들입니다. 그래프 요소의 각 부분, `graphid`의 조각들, 그리고 문자열이나 리스트의 길이를 다룹니다. 여기 있는 서버 정보 함수들은 이 빌드가 무엇인지, 마지막 쓰기가 무엇을 했는지 보고합니다. 예제는 [예제 데이터셋](../../get_started/example-dataset.md)에서 실행됩니다. {#scalar-agversion} ## agversion ``` agversion ( ) -> text ``` 실행 중인 서버의 AgensGraph 버전을 반환하며, `version()`이 함께 담는 PostgreSQL 부분은 빼고 반환합니다. **고려할 점** - `agversion`은 읽기 전용 설정이기도 하므로 `SHOW agversion`이 같은 문자열을 반환합니다. 함수 쪽은 표현식 안에서 쓸 수 있는 형태입니다. - 그 값은 PostgreSQL의 버전이 아니라 이 포크 자신의 버전입니다. 둘 다 보려면 `version()`을 읽으십시오. ```sql SELECT agversion(); ``` ``` agversion ------------ 2.18.6.0 ``` {#scalar-ag_get_graphconstraintdef} ## ag_get_graphconstraintdef ``` ag_get_graphconstraintdef ( constraint oid ) -> text ``` OID를 주면 그래프 제약에 대한 `CREATE CONSTRAINT` 명령을 재구성합니다. `pg_get_constraintdef`의 그래프 쪽 대응 함수이고, `pg_dump`가 쓰는 것입니다. {#scalar-ag_get_propindexdef} ## ag_get_propindexdef ``` ag_get_propindexdef ( index oid ) -> text ``` OID를 주면 속성 인덱스에 대한 `CREATE PROPERTY INDEX` 명령을 재구성합니다. **고려할 점** - 속성 인덱스는 `properties` 컬럼에 대한 표현식 인덱스이므로 `pg_get_indexdef`는 그것을 SQL로 출력합니다. 이 함수는 그 대신 Cypher 형태로 출력합니다. {#scalar-coalesce} ## coalesce ``` coalesce ( value [, value ] ... ) -> jsonb ``` null이 아닌 첫 인자를 반환합니다. **고려할 점** - 이것은 함수가 아니라 표현식 형태이므로, 카탈로그의 함수 목록에는 나타나지 않습니다. - 속성 참조는 언제나 `jsonb`입니다. 인자 중 하나라도 `jsonb`이면 모든 인자가 `jsonb`로 변환되고 결과도 `jsonb`입니다. 그렇지 않으면 인자들이 공통 타입으로 정해져 그것을 유지하므로, 정점 둘에 대한 `coalesce(v1, v2)`는 `vertex`를 반환합니다. - 그래서 그래프 요소를 다른 것과 섞으면 실패합니다. 그 요소를 감쌀 수 없기 때문입니다. 대신 `m::jsonb`를 넘기십시오. - null이 아닌 첫 인자 뒤의 인자들은 평가되지 않습니다. ```cypher MATCH (m:movie {title:'Inception'}) RETURN coalesce(m, 0); ``` ``` ERROR: COALESCE types vertex and integer cannot be matched LINE 1: MATCH (m:movie {title:'Inception'}) RETURN coalesce(m, 0); ^ ``` ```cypher MATCH (m:movie {title:'Inception'}) RETURN coalesce(m.budget, m.year, 0) AS first_present; ``` ``` first_present --------------- 2010 ``` {#scalar-datetime} ## datetime ``` datetime ( ) -> timestamp with time zone datetime ( timezone "any" ) -> timestamp without time zone datetime ( year integer, month integer, mday integer, hour integer, min integer, sec integer, millisec integer, nanosec integer, timezone "any" ) -> timestamp without time zone ``` 현재 트랜잭션의 타임스탬프, 지정한 시간대의 현재 시각, 또는 각 부분으로 만든 타임스탬프를 반환합니다. | 이름 | 타입 | 설명 | | --- | --- | --- | | `year`, `month`, `mday` | `integer` | 달력상의 날짜입니다. | | `hour`, `min`, `sec` | `integer` | 하루 중 시각입니다. | | `millisec`, `nanosec` | `integer` | 1초 미만 부분입니다. 마이크로초 해상도를 넘는 나노초는 버려집니다. | | `timezone` | `"any"` | 시간대 이름이나 약어입니다. 예를 들어 `'Asia/Seoul'`입니다. | **고려할 점** - 인자 없는 형태는 안정 함수이므로, 한 쿼리의 모든 행이 같은 시점을 보고 트랜잭션 사이에서는 값이 바뀝니다. - 시간대 형태는 `timestamp without time zone`을 반환합니다. 그 시간대의 벽시계 값이고 시간대 자체는 버려집니다. - `RETURN`은 결과를 ISO 8601 형태의 `jsonb` 문자열로 감쌉니다. ```sql SELECT datetime('Asia/Seoul'), datetime(2020, 1, 2, 3, 4, 5, 0, 0, 'UTC'); ``` ``` datetime | datetime ----------------------------+--------------------- 2026-09-02 16:52:34.625259 | 2020-01-02 03:04:05 ``` {#scalar-endnode} ## endNode ``` endNode ( e edge ) -> vertex ``` 간선이 가리키는 정점을 반환합니다. `end_vertex`가 다른 이름으로 부른 같은 함수입니다. 경로 페이지의 [`end_vertex`](#path-end_vertex)를 참고하십시오. {#scalar-end_id} ## end_id ``` end_id ( e edge ) -> graphid ``` 그 정점을 읽지 않고, 간선이 가리키는 정점의 `graphid`를 반환합니다. **고려할 점** - 간선 테이블은 `start`와 `end`를 컬럼으로 저장하므로, 이 함수는 간선 행 자체를 읽는 것 말고는 비용이 없습니다. `endNode()`는 그 정점을 가져와야 합니다. - 식별자를 비교하거나 그룹화하기만 하면 될 때는 언제든 이것을 쓰십시오. ```cypher MATCH ()-[e:acted_in]->() WITH e ORDER BY id(e) LIMIT 1 RETURN start_id(e) AS from_id, end_id(e) AS to_id; ``` ``` from_id | to_id ---------+------- 4.1 | 3.1 ``` {#scalar-get_last_graph_write_stats} ## get_last_graph_write_stats ``` get_last_graph_write_stats ( ) -> record ``` 이 세션의 가장 최근 그래프 쓰기가 무엇을 바꿨는지 카운터 다섯 개로 된 한 행으로 보고합니다. `insertedvertices`, `insertededges`, `deletedvertices`, `deletededges`, `updatedproperties`입니다. **고려할 점** - 이 카운터는 세션 전체가 아니라 마지막 그래프 쓰기 문장만 설명합니다. - 아무것도 쓰지 않은 문장은 앞 문장의 카운터를 0으로 만들지 않고 그대로 남기므로, 관심 있는 쓰기 바로 뒤에 그 행을 읽으십시오. - SQL에서 호출하십시오. 이 함수는 레코드를 반환하고, Cypher에는 레코드를 펼칠 방법이 없습니다. ```sql SELECT * FROM get_last_graph_write_stats(); ``` ``` insertedvertices | insertededges | deletedvertices | deletededges | updatedproperties ------------------+---------------+-----------------+--------------+------------------- 1 | 0 | 0 | 0 | 0 ``` {#scalar-get_time} ## get_time ``` get_time ( ) -> time without time zone get_time ( timezone "any" ) -> time without time zone ``` 하루 중 현재 시각을 로컬 기준으로, 또는 지정한 시간대 기준으로 반환합니다. **고려할 점** - 두 형태 모두 불변으로 표시돼 있어서 플래너가 그 호출을 상수로 접습니다. 쿼리의 모든 행이 같은 시각을 보고, 준비된 문장의 모든 실행도 그렇습니다. 시각이 흘러가야 한다면 안정 함수인 `localdatetime()`이나 SQL의 `localtime`에서 읽으십시오. ```sql SELECT get_time(), get_time('Asia/Seoul'); ``` ``` get_time | get_time ----------------+----------------- 12:52:34.62488 | 16:52:34.625259 ``` {#scalar-graphid} ## graphid ``` graphid ( labid integer, locid bigint ) -> graphid graphid ( id numeric ) -> graphid ``` 레이블 id와 로컬 id로, 또는 `graphid`가 출력되는 형태인 `labid.locid` 숫자로 `graphid`를 만듭니다. **고려할 점** - 레이블의 `id` 컬럼 기본값이 이렇게 적혀 있습니다. [그래프가 어떻게 저장되는가](../../concepts/graph-on-postgresql.md)를 참고하십시오. - 숫자 형태는 손으로 쓰는 SQL을 위한 편의입니다. 그 레이블이 존재하는지 확인하지 않습니다. ```sql SELECT graphid(4, 1), graphid(4.1::numeric); ``` ``` graphid | graphid ---------+--------- 4.1 | 4.1 ``` {#scalar-graph_labid} ## graph_labid ``` graph_labid ( qualified_label cstring ) -> integer ``` `graph.label` 형태로 지정한 레이블의 레이블 id를 반환합니다. ```sql SELECT graph_labid('moviekb.person'); ``` ``` graph_labid ------------- 4 ``` {#scalar-graphid_labid} ## graphid_labid ``` graphid_labid ( id graphid ) -> integer ``` `graphid`의 레이블 부분, 즉 점 앞의 숫자를 반환합니다. **고려할 점** - `graphid`는 상위 16비트에 레이블 id를, 나머지에 로컬 id를 담습니다. 그래서 하나의 레이블 전체가 `graphid` 값의 연속된 한 구간을 차지하고, 레이블 검사를 카탈로그를 건드리지 않고 인덱스 범위 스캔으로 답할 수 있습니다. {#scalar-graphid_locid} ## graphid_locid ``` graphid_locid ( id graphid ) -> bigint ``` `graphid`의 로컬 부분, 즉 점 뒤의 숫자를 반환하며, 그 값은 그 레이블의 시퀀스에서 나온 것입니다. ```cypher MATCH (n:person {name:'Keanu Reeves'}) RETURN id(n) AS id, graphid_labid(id(n)) AS label_id, graphid_locid(id(n)) AS local_id; ``` ``` id | label_id | local_id -----+----------+---------- 4.1 | 4 | 1 ``` {#scalar-id} ## id ``` id ( v vertex ) -> graphid id ( e edge ) -> graphid ``` 그래프 요소의 식별자를 반환합니다. **고려할 점** - 이것은 카탈로그 함수가 아닙니다. `vertex`는 복합 타입 `(id, properties)`이고 `edge`는 `(id, start, end, properties)`입니다. 그래서 `id(v)`는 필드 선택을 PostgreSQL이 함수 형태로 표기한 것입니다(`parse_func.c:1961`). `properties(v)`도 같은 장치로 얻습니다. - `n.id`는 같은 것이 **아닙니다.** 그것은 `id`라는 이름의 *속성*을 읽는데, 예제 데이터셋에는 그런 속성이 없으므로 null을 반환합니다. `id(n)`으로 쓰십시오. - `RETURN`은 결과를 `jsonb`로 감싸지 않고 `graphid`로 둡니다. 집계하면 감싸집니다. `min(id(n))`은 `jsonb` 문자열 `"4.1"`로 돌아옵니다. ```cypher MATCH (n:person {name:'Keanu Reeves'}) RETURN id(n) AS identity, n.id AS property_named_id; ``` ``` identity | property_named_id ----------+------------------- 4.1 | ``` {#scalar-label} ## label ``` label ( v vertex ) -> jsonb label ( e edge ) -> jsonb ``` 그래프 요소가 만들어질 때의 레이블 이름을 `jsonb` 문자열로 반환합니다. **고려할 점** - `label`과 [`labels`](#scalar-labels)는 하나를 다르게 표기한 것이 아니라 서로 다른 함수입니다. `label`은 문자열 하나, 그 요소 자신의 레이블을 반환합니다. `labels`는 그 레이블 뒤에 그것이 상속하는 레이블들을 붙인 리스트를 반환합니다. - `label`은 정점뿐 아니라 간선에서도 동작하고, `labels`는 그렇지 않습니다. 간선에 대해서는 `label(e)`와 [`type(e)`](#scalar-type)가 같은 호출입니다. ```cypher MATCH (n:person {name:'Keanu Reeves'}) RETURN label(n) AS own, labels(n) AS own_and_inherited; ``` ``` own | own_and_inherited ----------+------------------- "person" | ["person"] ``` 두 답이 갈라지는 것은 레이블이 상속할 때뿐입니다. 부모가 있는 레이블을 하나 추가합니다: ```cypher CREATE VLABEL creature; CREATE VLABEL dragon INHERITS (creature); CREATE (:dragon {name: 'Smaug'}); ``` ```cypher MATCH (d:dragon) RETURN label(d) AS own, labels(d) AS own_and_inherited; ``` ``` own | own_and_inherited ----------+------------------------ "dragon" | ["dragon", "creature"] ``` 그다음 그것을 다시 없앱니다: ```cypher MATCH (d:dragon) DETACH DELETE d; DROP VLABEL dragon; DROP VLABEL creature; ``` 간선에는 `labels()`가 없습니다: ```cypher MATCH ()-[e:acted_in]->() WITH e LIMIT 1 RETURN labels(e); ``` ``` ERROR: function labels(edge) does not exist LINE 1: MATCH ()-[e:acted_in]->() WITH e LIMIT 1 RETURN labels(e); ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. ``` {#scalar-labels} ## labels ``` labels ( v vertex ) -> jsonb ``` 정점 자신의 레이블과 그것이 상속하는 모든 레이블을 가까운 것부터 담은 리스트를 반환합니다. **고려할 점** - 정점만 받습니다. `labels(edge)`는 없습니다. - 부모가 없는 레이블에서는 리스트에 요소가 하나이고, 그것이 흔한 경우입니다. {#scalar-length} ## length ``` length ( value jsonb ) -> jsonb ``` 문자열의 글자 수, 리스트의 요소 수, 또는 맵의 키 수를 반환합니다. **고려할 점** - [`size`](#scalar-size)가 이 함수의 Cypher 쪽 표기입니다. 파서가 그것을 다시 쓰므로 결과 컬럼의 이름이 `length`가 됩니다. - 경로나 그래프 요소의 배열에 대한 `length`는 뜻이 다른 별개의 함수입니다. 그 경로의 간선 개수입니다. 경로 페이지의 [`length`](#path-length)를 참고하십시오. - 숫자를 주면 오류를 내지 않고 그 텍스트 형태의 길이를 반환합니다. ```cypher RETURN length('The Matrix') AS characters, length([1,2,3]) AS elements, length({a:1,b:2}) AS keys; ``` ``` characters | elements | keys ------------+----------+------ 10 | 3 | 2 ``` {#scalar-localdatetime} ## localdatetime ``` localdatetime ( ) -> timestamp with time zone localdatetime ( timezone "any" ) -> timestamp without time zone ``` 현재 트랜잭션의 타임스탬프, 또는 지정한 시간대의 현재 벽시계 값을 반환합니다. **고려할 점** - 인자 없는 형태는 타입까지 포함해 `datetime()`과 같은 값을 반환합니다. 두 이름이 있는 것은 GQL 호환을 위한 것이며, 어느 쪽도 시간대를 버리지 않습니다. - 시간대 형태는 `datetime(zone)`과 마찬가지로 `timestamp without time zone`을 반환합니다. - 두 형태 모두 안정 함수이므로, [`get_time`](#scalar-get_time)과 달리 여기서 얻은 값은 트랜잭션 사이에서 흘러갑니다. {#scalar-properties} ## properties ``` properties ( v vertex ) -> jsonb properties ( e edge ) -> jsonb ``` 그래프 요소의 `properties` 전체를 맵으로 반환합니다. **고려할 점** - [`id`](#scalar-id)와 마찬가지로 이것은 카탈로그 함수가 아니라 복합 타입에 대한 필드 선택이므로, 그 컬럼을 읽는 것 이상의 비용이 들지 않습니다. - `vertex_to_jsonb`와 `edge_to_jsonb`가 같은 맵을 반환하며, 형 변환 `v::jsonb`가 쓰는 함수입니다. - `properties`를 읽으면 그것을 전부 detoast 합니다. 키 하나만 원한다면 그 키를 읽으십시오. ```cypher MATCH (n:person {name:'Keanu Reeves'}) RETURN properties(n) AS bag; ``` ``` bag ---------------------------------------- {"born": 1964, "name": "Keanu Reeves"} ``` {#scalar-regather_graphmeta} ## regather_graphmeta ``` regather_graphmeta ( ) -> boolean ``` `ag_graphmeta`를 비우고, 현재 그래프의 모든 간선 레이블을 스캔해 다시 만듭니다. `ag_graphmeta`는 어떤 레이블 세 쌍이 나타나는지와 각각을 이루는 간선이 몇 개인지를 기록하며, 플래너는 그것으로 패턴이 일치시킬 수 없는 레이블 테이블을 건너뜁니다. **고려할 점** - 이 스캔은 그래프의 모든 간선을 읽으므로 비용이 그래프 크기와 함께 커집니다. - `auto_gather_graphmeta`는 쓰기가 일어날 때마다 그 테이블을 최신으로 유지합니다. 그 설정을 끈 채로 대량 적재를 했다면 손으로 다시 만드십시오. - `NOTICE: regathering graphmeta...` 를 내고 참을 반환합니다. ```sql SELECT regather_graphmeta(); ``` ``` NOTICE: regathering graphmeta... regather_graphmeta -------------------- t ``` {#scalar-size} ## size ``` size ( value ) -> jsonb size ( pattern ) -> bigint ``` 값을 주면 그 길이를 반환합니다. 패턴을 주면 그 패턴이 일치하는 횟수를 반환합니다. **고려할 점** - 두 형태는 첫 글자로 구별됩니다. 패턴은 언제나 `(`로 시작하므로, 그럴 수 없는 것은 값으로 읽힙니다. 값 형태는 [`length`](#scalar-length)가 되므로 결과 컬럼의 이름이 `length`입니다. 패턴 형태는 개수를 세는 서브쿼리가 되므로 이름이 `count`입니다. - `shortestpath`나 `allshortestpaths`를 인자로 주면 패턴으로 읽히지 않고, 찾아낸 경로의 개수라는 기존 뜻을 유지합니다. ```cypher MATCH (a:person {name:'Keanu Reeves'}) RETURN size((a)-[]->()) AS edges, size(a.name) AS name_length; ``` ``` edges | name_length -------+------------- 4 | 12 ``` {#scalar-startnode} ## startNode ``` startNode ( e edge ) -> vertex ``` 간선이 떠나는 정점을 반환합니다. `start_vertex`가 다른 이름으로 부른 같은 함수입니다. 경로 페이지의 [`start_vertex`](#path-start_vertex)를 참고하십시오. {#scalar-start_id} ## start_id ``` start_id ( e edge ) -> graphid ``` 그 정점을 읽지 않고, 간선이 떠나는 정점의 `graphid`를 반환합니다. [`end_id`](#scalar-end_id)의 고려할 점이 그대로 적용됩니다. {#scalar-type} ## type ``` type ( e edge ) -> jsonb ``` 간선의 레이블 이름을 `jsonb` 문자열로 반환합니다. `label(e)`와 같은 값이며, Cypher가 관계 타입에 쓰는 이름으로 부른 것입니다. **고려할 점** - 간선만 받습니다. 정점에 쓰면 거부됩니다. [`label`](#scalar-label)을 쓰십시오. ```cypher MATCH (m:movie {title:'Inception'}) RETURN type(m); ``` ``` ERROR: function type(vertex) does not exist LINE 1: MATCH (m:movie {title:'Inception'}) RETURN type(m); ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. ``` ```cypher MATCH ()-[e:acted_in]->() WITH e LIMIT 1 RETURN type(e) AS relationship_type; ``` ``` relationship_type ------------------- "acted_in" ``` {#scalar-compatibility} ## 호환성 {#scalar-opencypher} ### openCypher `id()`는 openCypher가 반환하는 정수가 아니라 `graphid`, 즉 레이블 id와 시퀀스 번호를 반환합니다. 그 요소가 살아 있는 동안 변하지 않고 그래프 전체에서 고유합니다. 그러나 작고 촘촘한 정수가 아니며, 그것에 대한 산술은 뜻이 없습니다. openCypher의 `labels()`는 정점이 지닌 모든 레이블을 반환합니다. 거기서는 정점이 여러 개를 지닐 수 있기 때문입니다. 여기서 정점은 정확히 하나의 레이블을 가지며, `labels()`는 그 레이블에 그것이 상속하는 레이블들을 더해 반환합니다. {#scalar-see-also} ## 관련 항목 - [모든 함수](all-functions.md) — 모든 함수를 한 표에 - [경로 함수](path.md) — 경로에 대한 `nodes`, `relationships`, `length` - [jsonb 연산자와 함수](jsonb.md) — `properties()`가 반환하는 맵 읽기 - [그래프 메타데이터 함수](../../system_catalogs/graph-metadata.md) — `meta.*` 스키마