Couchbase N1QL tutorial

15 minute read

N1QL Basic

  • N1QL data model 이름은 비1차 정규형(Non-first normal form(NF2 or N1NF))에서 파생

Start

Query

SELECT 'Hello World' AS Greeting

Result

{
  "results": [
    {
      "Greeting": "Hello World"
    }
  ]
}

User-friendly language

  • 반면 필드 키를 지정하면 각 필드가
{
  "results": [
    {
      "age": 56,
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "email": "ian@gmail.com",
      "fname": "Ian",
      "hobbies": ["golf", "surfing"],
      "lname": "Taylor",
      "relation": "cousin",
      "title": "Mr.",
      "type": "contact"
    }
  ]
}

Query

  • Couchbase N1QL에는 스키마가 없으며, 구조가 상이하더라도 N1QL은 쿼리에 매치되는 모든 결과를 반환할 만큼 유연하다

Query with asterisk

SELECT *            -- 반환할 문서일 일부
FROM tutorial       -- data bucket
WHERE fname = 'Ian' -- 조건

Result with asterisk

  • *(asterisk) 사용하면 데이터를 버킷의 이름(tutorial)이 실제 데이터를 한번 감싼다
{
  "results": [
    {
      "tutorial": {
        "type": "contact",
        "title": "Mr.",
        "fname": "Ian",
        "lname": "Taylor",
        "age": 56,
        "email": "ian@gmail.com",
        "children": [
          {
            "fname": "Abama",
            "age": 17,
            "gender": "m"
          },
          {
            "fname": "Bebama",
            "age": 21,
            "gender": "m"
          }
        ],
        "hobbies": ["golf", "surfing"],
        "relation": "cousin"
      }
    }
  ]
}

Query with specific fields

  • 필드를 지정하여 사용하면 버킷 이름으로 감싸지 않고 반환된다
SELECT
    type,
    title,
    fname,
    lname,
    age,
    email,
    children,
    hobbies,
    relation
FROM tutorial
WHERE fname = 'Ian'

Result with specific fields

{
  "results": [
    {
      "type": "contact",
      "title": "Mr.",
      "fname": "Ian",
      "lname": "Taylor",
      "age": 56,
      "email": "ian@gmail.com",
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "cousin"
    }
  ]
}

Documents, not rows

  • Couchbase는 데이터를 row/column이 아닌 documents 형태로 저장
  • 문서는 문서 안에 요소나 배열을 가질 수 있기 때문에, 몇 가지 추가적인 연산이 필요하다
    • . 연산자는 자식 요소를 참조에 사용
    • [] 연산자는 배열의 요소를 참조에 사용

Query

SELECT children[0].fname AS child_name
FROM tutorial
WHERE fname = 'Dave'

Result

{
  "results": [
    {
      "child_name": "Aiden"
    }
  ]
}

Pattern matching with LIKE

  • LIKE 키워드 사용하여 패턴 매칭 가능
  • % 와일드 카드 → 0개 이상의 문자가 매치
  • _ 와일드 카드 → 정확히 한 문자 매치

Query

SELECT
    fname,
    email
FROM tutorial
WHERE email LIKE '%@yahoo.com'

Result

{
  "results": [
    {
      "email": "harry@yahoo.com",
      "fname": "Harry"
    }
  ]
}

Matching elements in nested arrays with ANY

  • 문서 안의 배열에 기반하여 필터하고 싶을 때 사용

Structure

  • ANY|EVERY
  • IN ..
  • SATISFIES ...
  • > | = | < ...
  • END

Query

SELECT *
FROM tutorial
WHERE
    ANY child IN tutorial.children
    SATISFIES child.age > 10  END

Result

{
  "results": [
    {
      "tutorial": {
        "type": "contact",
        "title": "Mr.",
        "fname": "Dave",
        "lname": "Smith",
        "age": 46,
        "email": "dave@gmail.com",
        "children": [
          {
            "fname": "Aiden",
            "age": 17,
            "gender": "m"
          },
          {
            "fname": "Bill",
            "age": 2,
            "gender": "f"
          }
        ],
        "hobbies": ["golf", "surfing"],
        "relation": "friend"
      }
    },
    {
      "tutorial": {
        "type": "contact",
        "title": "Mr.",
        "fname": "Earl",
        "lname": "Johnson",
        "age": 46,
        "email": "earl@gmail.com",
        "children": [
          {
            "fname": "Xena",
            "age": 17,
            "gender": "f"
          },
          {
            "fname": "Yuri",
            "age": 2,
            "gender": "m"
          }
        ],
        "hobbies": ["surfing"],
        "relation": "friend"
      }
    },
    {
      "tutorial": {
        "type": "contact",
        "title": "Mr.",
        "fname": "Ian",
        "lname": "Taylor",
        "age": 56,
        "email": "ian@gmail.com",
        "children": [
          {
            "fname": "Abama",
            "age": 17,
            "gender": "m"
          },
          {
            "fname": "Bebama",
            "age": 21,
            "gender": "m"
          }
        ],
        "hobbies": ["golf", "surfing"],
        "relation": "cousin"
      }
    }
  ]
}

Combining multiple conditions with AND

Query

SELECT
    fname,
    email,
    children
FROM tutorial
WHERE
    ARRAY_LENGTH(children) > 0 AND
    email LIKE '%@gmail.com'

Result

{
  "results": [
    {
      "children": [
        {
          "fname": "Aiden",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bill",
          "age": 2,
          "gender": "f"
        }
      ],
      "email": "dave@gmail.com",
      "fname": "Dave"
    },
    {
      "children": [
        {
          "fname": "Xena",
          "age": 17,
          "gender": "f"
        },
        {
          "fname": "Yuri",
          "age": 2,
          "gender": "m"
        }
      ],
      "email": "earl@gmail.com",
      "fname": "Earl"
    },
    {
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "email": "ian@gmail.com",
      "fname": "Ian"
    }
  ]
}

Querying primary keys

  • USE KEYS 구문 사용하여 버킷의 특정한 primary key를 조회할 수 있다
  • ["dave", "ian"], ["dave"], "dave" 모두 가능

Query

SELECT
    fname,
    lname,
    children,
    email
FROM tutorial
USE KEYS ["dave", "ian"]

Result

{
  "results": [
    {
      "email": "dave@gmail.com",
      "fname": "Dave",
      "lname": "Smith"
    },
    {
      "email": "ian@gmail.com",
      "fname": "Ian",
      "lname": "Taylor"
    }
  ]
}

Quick review

  • 문서 내의 배열은 slice가 가능

Query

SELECT
    fname || " " || lname AS full_name,
    email,
    children[0:2] AS offspring  -- array slicing
FROM tutorial
WHERE email LIKE '%@yahoo.com'
OR ANY child IN tutorial.children SATISFIES child.age > 10 END

Result

{
  "results": [
    {
      "email": "dave@gmail.com",
      "full_name": "Dave Smith",
      "offspring": [
        {
          "age": 17,
          "fname": "Aiden",
          "gender": "m"
        },
        {
          "age": 2,
          "fname": "Bill",
          "gender": "f"
        }
      ]
    },
    {
      "email": "earl@gmail.com",
      "full_name": "Earl Johnson",
      "offspring": [
        {
          "age": 17,
          "fname": "Xena",
          "gender": "f"
        },
        {
          "age": 2,
          "fname": "Yuri",
          "gender": "m"
        }
      ]
    },
    {
      "email": "harry@yahoo.com",
      "full_name": "Harry Jackson"
    },
    {
      "email": "ian@gmail.com",
      "full_name": "Ian Taylor",
      "offspring": [
        {
          "age": 17,
          "fname": "Abama",
          "gender": "m"
        },
        {
          "age": 21,
          "fname": "Bebama",
          "gender": "m"
        }
      ]
    }
  ]
}

Pagination with LIMIT and OFFSET

  • 좀 더 작은 단위로 처리하고 싶을 떄 사용
  • LIMIT → 결과 수 제한
  • OFFSET → 시작 점 지정

Result without LIMIT AND OFFSET

{
  "results": [
    {
      "age": 18,
      "fname": "Fred"
    },
    {
      "age": 20,
      "fname": "Harry"
    },
    {
      "age": 40,
      "fname": "Jane"
    },
    {
      "age": 46,
      "fname": "Dave"
    },
    {
      "age": 46,
      "fname": "Earl"
    },
    {
      "age": 56,
      "fname": "Ian"
    }
  ]
}

Query with LIMIT

SELECT
    fname,
    age
FROM tutorial
ORDER BY age
LIMIT 2

Result with LIMIT

{
  "results": [
    {
      "age": 18,
      "fname": "Fred"
    },
    {
      "age": 20,
      "fname": "Harry"
    }
  ]
}

Query with LIMIT AND OFFSET

SELECT
    fname,
    age
FROM tutorial
ORDER BY age
LIMIT 2
OFFSET 4

Result with LIMIT AND OFFSET

{
  "results": [
    {
      "age": 46,
      "fname": "Earl"
    },
    {
      "age": 56,
      "fname": "Ian"
    }
  ]
}

Filtering grouped data with HAVING

  • 반환되는 그룹을 필터하고 싶을 때 사용
  • GROUP BY

Query with GROUP BY

SELECT
    relation,
    COUNT(*) AS count
FROM tutorial
GROUP BY relation

Result with GROUP BY

{
  "results": [
    {
      "count": 2,
      "relation": "cousin"
    },
    {
      "count": 2,
      "relation": "friend"
    },
    {
      "count": 1,
      "relation": "coworker"
    },
    {
      "count": 1,
      "relation": "parent"
    }
  ]
}

Review

  • SELECT
  • FROM → tutorial bucket의 전체 6개 문서에서 시작
  • UNNEST → N1QL 사양에 따라, 내부 배열을 그 부모와 조인하여 내부의 컨텐츠로 접근.

Query with UNNEST

SELECT
    t.relation,
    t.fname,
    t.lname,
    t.email,
    t.children
FROM tutorial t
UNNEST t.children c

Result with UNNEST

  • 아래 결과를 보면 같은 데이터가 두 개씩 반환되는데, UNNEST 구문을 사용하여 children 필드의 배열이 밖으로 나오게 됐기 때문
{
  "results": [
    {
      "children": [
        {
          "fname": "Aiden",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bill",
          "age": 2,
          "gender": "f"
        }
      ],
      "email": "dave@gmail.com",
      "fname": "Dave",
      "lname": "Smith",
      "relation": "friend"
    },
    {
      "children": [
        {
          "fname": "Aiden",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bill",
          "age": 2,
          "gender": "f"
        }
      ],
      "email": "dave@gmail.com",
      "fname": "Dave",
      "lname": "Smith",
      "relation": "friend"
    },
    {
      "children": [
        {
          "fname": "Xena",
          "age": 17,
          "gender": "f"
        },
        {
          "fname": "Yuri",
          "age": 2,
          "gender": "m"
        }
      ],
      "email": "earl@gmail.com",
      "fname": "Earl",
      "lname": "Johnson",
      "relation": "friend"
    },
    {
      "children": [
        {
          "fname": "Xena",
          "age": 17,
          "gender": "f"
        },
        {
          "fname": "Yuri",
          "age": 2,
          "gender": "m"
        }
      ],
      "email": "earl@gmail.com",
      "fname": "Earl",
      "lname": "Johnson",
      "relation": "friend"
    },
    {
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "email": "ian@gmail.com",
      "fname": "Ian",
      "lname": "Taylor",
      "relation": "cousin"
    },
    {
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "email": "ian@gmail.com",
      "fname": "Ian",
      "lname": "Taylor",
      "relation": "cousin"
    }
  ]
}

Query with UNNEST ANd WHERE


SELECT
    t.relation,
    t.fname,
    t.lname,
    t.email,
    t.children
FROM tutorial t
UNNEST t.children c
WHERE c.age > 10

Result with UNNEST ANd WHERE

  • Ian Taylor의 데이터만 중복되는데, UNNEST된 children 데이터에서 10살이 넘는 아이가 두 명이 있기 때문
{
  "results": [
    {
      "children": [
        {
          "fname": "Aiden",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bill",
          "age": 2,
          "gender": "f"
        }
      ],
      "email": "dave@gmail.com",
      "fname": "Dave",
      "lname": "Smith",
      "relation": "friend"
    },
    {
      "children": [
        {
          "fname": "Xena",
          "age": 17,
          "gender": "f"
        },
        {
          "fname": "Yuri",
          "age": 2,
          "gender": "m"
        }
      ],
      "email": "earl@gmail.com",
      "fname": "Earl",
      "lname": "Johnson",
      "relation": "friend"
    },
    {
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "email": "ian@gmail.com",
      "fname": "Ian",
      "lname": "Taylor",
      "relation": "cousin"
    },
    {
      "children": [
        {
          "fname": "Abama",
          "age": 17,
          "gender": "m"
        },
        {
          "fname": "Bebama",
          "age": 21,
          "gender": "m"
        }
      ],
      "email": "ian@gmail.com",
      "fname": "Ian",
      "lname": "Taylor",
      "relation": "cousin"
    }
  ]
}

SELECT
    t.relation,
    t.fname,
    t.lname,
    t.email,
    t.children,
    COUNT(*) AS count,
    AVG(c.age) AS avg_age
FROM tutorial t
UNNEST t.children c
WHERE c.age > 10
GROUP BY t.relation HAVING COUNT(*) > 1
ORDER BY avg_age DESC

Query

SELECT
    t.relation,
    COUNT(*) AS count,
    AVG(c.age) AS avg_age
FROM tutorial t
UNNEST t.children c -- children 배열의 모든 항목들에 접근하기 위해 사용
WHERE c.age > 10
GROUP BY t.relation HAVING COUNT(*) > 1
ORDER BY avg_age DESC
LIMIT 1 OFFSET 1

Expected flow

1. 전체 6개 문서

[
  {
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Dave",
      "lname": "Smith",
      "age": 46,
      "email": "dave@gmail.com",
      "children": [
        { "fname": "Aiden", "age": 17, "gender": "m" },
        { "fname": "Bill", "age": 2, "gender": "f" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "friend"
    }
  },
  {
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Earl",
      "lname": "Johnson",
      "age": 46,
      "email": "earl@gmail.com",
      "children": [
        { "fname": "Xena", "age": 17, "gender": "f" },
        { "fname": "Yuri", "age": 2, "gender": "m" }
      ],
      "hobbies": ["surfing"],
      "relation": "friend"
    }
  },
  {
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Fred",
      "lname": "Jackson",
      "age": 18,
      "email": "fred@gmail.com",
      "hobbies": ["golf", "surfing"],
      "children": null,
      "relation": "coworker"
    }
  },
  {
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Harry",
      "lname": "Jackson",
      "age": 20,
      "email": "harry@yahoo.com",
      "relation": "parent"
    }
  },
  {
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Ian",
      "lname": "Taylor",
      "age": 56,
      "email": "ian@gmail.com",
      "children": [
        { "fname": "Abama", "age": 17, "gender": "m" },
        { "fname": "Bebama", "age": 21, "gender": "m" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "cousin"
    }
  },
  {
    "t": {
      "type": "contact",
      "title": "Mrs.",
      "fname": "Jane",
      "lname": "Edwards",
      "age": 40,
      "email": "jane@gmail.com",
      "contacts": [{ "fname": "Fred" }, { "fname": "Sheela" }],
      "relation": "cousin"
    }
  }
]

2.UNNEST로 children 배열과 그 부모를 조인

  • 이 경우 children이 null인 Fred Jackson과 children 자체가 없는 Harry Jackson은 제외된다
[
  {
    "c": { "age": 17, "fname": "Aiden", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Dave",
      "lname": "Smith",
      "age": 46,
      "email": "dave@gmail.com",
      "children": [
        { "fname": "Aiden", "age": 17, "gender": "m" },
        { "fname": "Bill", "age": 2, "gender": "f" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "friend"
    }
  },
  {
    "c": { "age": 2, "fname": "Bill", "gender": "f" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Dave",
      "lname": "Smith",
      "age": 46,
      "email": "dave@gmail.com",
      "children": [
        { "fname": "Aiden", "age": 17, "gender": "m" },
        { "fname": "Bill", "age": 2, "gender": "f" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "friend"
    }
  },
  {
    "c": { "age": 17, "fname": "Xena", "gender": "f" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Earl",
      "lname": "Johnson",
      "age": 46,
      "email": "earl@gmail.com",
      "children": [
        { "fname": "Xena", "age": 17, "gender": "f" },
        { "fname": "Yuri", "age": 2, "gender": "m" }
      ],
      "hobbies": ["surfing"],
      "relation": "friend"
    }
  },
  {
    "c": { "age": 2, "fname": "Yuri", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Earl",
      "lname": "Johnson",
      "age": 46,
      "email": "earl@gmail.com",
      "children": [
        { "fname": "Xena", "age": 17, "gender": "f" },
        { "fname": "Yuri", "age": 2, "gender": "m" }
      ],
      "hobbies": ["surfing"],
      "relation": "friend"
    }
  },
  {
    "c": { "age": 17, "fname": "Abama", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Ian",
      "lname": "Taylor",
      "age": 56,
      "email": "ian@gmail.com",
      "children": [
        { "fname": "Abama", "age": 17, "gender": "m" },
        { "fname": "Bebama", "age": 21, "gender": "m" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "cousin"
    }
  },
  {
    "c": { "age": 21, "fname": "Bebama", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Ian",
      "lname": "Taylor",
      "age": 56,
      "email": "ian@gmail.com",
      "children": [
        { "fname": "Abama", "age": 17, "gender": "m" },
        { "fname": "Bebama", "age": 21, "gender": "m" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "cousin"
    }
  }
]

3. c(자식)의 age가 10을 넘는 경우

  • Ian Taylor는 자식 둘 모두 10살을 넘어서 두 개의 문서가 반환된다
[
  {
    "c": { "age": 17, "fname": "Aiden", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Dave",
      "lname": "Smith",
      "age": 46,
      "email": "dave@gmail.com",
      "children": [
        { "fname": "Aiden", "age": 17, "gender": "m" },
        { "fname": "Bill", "age": 2, "gender": "f" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "friend"
    }
  },
  {
    "c": { "age": 17, "fname": "Xena", "gender": "f" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Earl",
      "lname": "Johnson",
      "age": 46,
      "email": "earl@gmail.com",
      "children": [
        { "fname": "Xena", "age": 17, "gender": "f" },
        { "fname": "Yuri", "age": 2, "gender": "m" }
      ],
      "hobbies": ["surfing"],
      "relation": "friend"
    }
  },
  {
    "c": { "age": 17, "fname": "Abama", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Ian",
      "lname": "Taylor",
      "age": 56,
      "email": "ian@gmail.com",
      "children": [
        { "fname": "Abama", "age": 17, "gender": "m" },
        { "fname": "Bebama", "age": 21, "gender": "m" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "cousin"
    }
  },
  {
    "c": { "age": 21, "fname": "Bebama", "gender": "m" },
    "t": {
      "type": "contact",
      "title": "Mr.",
      "fname": "Ian",
      "lname": "Taylor",
      "age": 56,
      "email": "ian@gmail.com",
      "children": [
        { "fname": "Abama", "age": 17, "gender": "m" },
        { "fname": "Bebama", "age": 21, "gender": "m" }
      ],
      "hobbies": ["golf", "surfing"],
      "relation": "cousin"
    }
  }
]

4. relation 필드로 그룹화하고, 그때 그룹된 결과의 수가 1개 초과하는 경우

  • 각 그룹별로 relation, count, avg_age 필드를 가지는 한 문서씩 남아야 하지만, 이해를 위해 기존 데이터를 남겨둔다
[
  {
    "freind_group": {
        "result" : {
            "avg_age": 17,
            "count": 2,
            "relation": "friend"
        },
        "original_data": [
            {
                "c": { "age": 17, "fname": "Aiden", "gender": "m" },
                "t": {
                    "type": "contact",
                    "title": "Mr.",
                    "fname": "Dave",
                    "lname": "Smith",
                    "age": 46,
                    "email": "dave@gmail.com",
                    "children": [
                            { "fname": "Aiden", "age": 17, "gender": "m" },
                            { "fname": "Bill", "age": 2, "gender": "f" }
                        ],
                    "hobbies": ["golf", "surfing"],
                    "relation": "friend"
                }
            },
            {
                "c": { "age": 17, "fname": "Xena", "gender": "f" },
                "t": {
                    "type": "contact",
                    "title": "Mr.",
                    "fname": "Earl",
                    "lname": "Johnson",
                    "age": 46,
                    "email": "earl@gmail.com",
                    "children": [
                        { "fname": "Xena", "age": 17, "gender": "f" },
                        { "fname": "Yuri", "age": 2, "gender": "m" }
                    ],
                    "hobbies": ["surfing"],
                    "relation": "friend"
                }
            }
        ]
    },
    "cousin_group": {
        "result":{"avg_age": 19,"count": 2,"relation": "cousin"},
        "original_data": [
            {
                "c": { "age": 17, "fname": "Abama", "gender": "m" },
                "t": {
                "type": "contact",
                "title": "Mr.",
                "fname": "Ian",
                "lname": "Taylor",
                "age": 56,
                "email": "ian@gmail.com",
                "children": [
                    { "fname": "Abama", "age": 17, "gender": "m" },
                    { "fname": "Bebama", "age": 21, "gender": "m" }
                ],
                "hobbies": ["golf", "surfing"],
                "relation": "cousin"
                }
            },
            {
                "c": { "age": 21, "fname": "Bebama", "gender": "m" },
                "t": {
                "type": "contact",
                "title": "Mr.",
                "fname": "Ian",
                "lname": "Taylor",
                "age": 56,
                "email": "ian@gmail.com",
                "children": [
                    { "fname": "Abama", "age": 17, "gender": "m" },
                    { "fname": "Bebama", "age": 21, "gender": "m" }
                ],
                "hobbies": ["golf", "surfing"],
                "relation": "cousin"
                }
            }
        ]
    }
}

5. 평균 나이로 내림차순 정렬

  • cousin 그룹 자식의 평균 나이는 19
  • friend 그룹 자식의 평균 나이는 17
[
  {
    "cousin_group": {
        "result":{
            "avg_age": 19,
            "count": 2,
            "relation": "cousin"
        },
        "original_data": [
            {
                "c": {
                    "age": 17,
                    "fname": "Abama",
                    "gender": "m" },
                "t": {
                "type": "contact",
                "title": "Mr.",
                "fname": "Ian",
                "lname": "Taylor",
                "age": 56,
                "email": "ian@gmail.com",
                "children": [
                    { "fname": "Abama", "age": 17, "gender": "m" },
                    { "fname": "Bebama", "age": 21, "gender": "m" }
                ],
                "hobbies": ["golf", "surfing"],
                "relation": "cousin"
                }
            },
            {
                "c": {
                    "age": 21,
                    "fname": "Bebama",
                    "gender": "m"
                },
                "t": {
                "type": "contact",
                "title": "Mr.",
                "fname": "Ian",
                "lname": "Taylor",
                "age": 56,
                "email": "ian@gmail.com",
                "children": [
                    { "fname": "Abama", "age": 17, "gender": "m" },
                    { "fname": "Bebama", "age": 21, "gender": "m" }
                ],
                "hobbies": ["golf", "surfing"],
                "relation": "cousin"
                }
            }
        ]
    },
    "freind_group": {
        "result" : {
            "avg_age": 17,
            "count": 2,
            "relation": "friend"
        },
        "original_data": [
            {
                "c": { "age": 17, "fname": "Aiden", "gender": "m" },
                "t": {
                    "type": "contact",
                    "title": "Mr.",
                    "fname": "Dave",
                    "lname": "Smith",
                    "age": 46,
                    "email": "dave@gmail.com",
                    "children": [
                            { "fname": "Aiden", "age": 17, "gender": "m" },
                            { "fname": "Bill", "age": 2, "gender": "f" }
                        ],
                    "hobbies": ["golf", "surfing"],
                    "relation": "friend"
                }
            },
            {
                "c": { "age": 17, "fname": "Xena", "gender": "f" },
                "t": {
                    "type": "contact",
                    "title": "Mr.",
                    "fname": "Earl",
                    "lname": "Johnson",
                    "age": 46,
                    "email": "earl@gmail.com",
                    "children": [
                        { "fname": "Xena", "age": 17, "gender": "f" },
                        { "fname": "Yuri", "age": 2, "gender": "m" }
                    ],
                    "hobbies": ["surfing"],
                    "relation": "friend"
                }
            }
        ]
    }
}

6. 0부터 시작하는 데이터에서, 1번째 인덱스 데이터 1개 반환

{
    "avg_age": 17,
    "count": 2,
    "relation": "friend"
}

JOIN

JOIN clause

  • 버킷이 아래와 같이 두 개 있을 경우
    1. users_with_orders
      • 유저 프로필 + 유저가 구매한 주문의 아이디
    2. orders_with_users
      • 어떤 사용자가 구매한 특정 주문에 대한 설명
      • JOIN 구문 사용하여 주문 정보로 유저 프로필 조회 가능
  • ARRAYFIRST: 컬렉션의 요소를 map 또는 filter

Query

SELECT
    usr.personal_details,
    usr.shipped_order_history,
    usr.user_id,
    orders
FROM users_with_orders usr
USE KEYS "Elinor_33313792"  -- 사용자 프로필의 key
JOIN orders_with_users orders
    ON KEYS ARRAY s.order_id
        FOR s IN usr.shipped_order_history END

Expected flow

  1. users_with_orders 버킷에서 유저 정보를 가져온다
  2. USE KEYS 절로 Elinor_33313792 아이디에 해당하는 정보는 가져온다
  3. JOIN으로 orders_with_users 버킷을 조인시킨다 4.

Result

{
  "results": [
    {
      "orders": {
        "doc_type": "order",
        "order_details": {
          "order_datetime": "Wed Jun  6 18:53:39 2012",
          "order_id": "T103929516925"
        },
        "payment_details": {
          "payment_mode": "Debit Card",
          "total_charges": 308
        },
        "product_details": {
          "currency": "EUR",
          "list_price": 318,
          "pct_discount": 5,
          "product_id": "P3109994453",
          "sale_price": 303
        },
        "shipping_details": {
          "shipping_charges": 5,
          "shipping_status": "Delivered",
          "shipping_type": "Express"
        },
        "user_id": "Elinor_33313792"
      },
      "personal_details": {
        "age": 60,
        "display_name": "Elinor Ritchie",
        "email": "Elinor.Ritchie@snailmail.com",
        "first_name": "Elinor",
        "last_name": "Ritchie",
        "state": "Arizona"
      },
      "shipped_order_history": [
        {
          "order_datetime": "Wed May 30 22:00:09 2012",
          "order_id": "T103929516925"
        },
        {
          "order_datetime": "Thu Aug  4 22:00:09 2011",
          "order_id": "T573145204032"
        }
      ]
    },
    {
      "orders": {
        "doc_type": "order",
        "order_details": {
          "order_datetime": "Thu Aug 11 18:53:39 2011",
          "order_id": "T573145204032"
        },
        "payment_details": {
          "payment_mode": "NetBanking",
          "total_charges": 569
        },
        "product_details": {
          "currency": "GBP",
          "list_price": 666,
          "pct_discount": 15,
          "product_id": "P9315874155",
          "sale_price": 567
        },
        "shipping_details": {
          "shipping_charges": 2,
          "shipping_status": "Delivered",
          "shipping_type": "Regular"
        },
        "user_id": "Elinor_33313792"
      },
      "personal_details": {
        "age": 60,
        "display_name": "Elinor Ritchie",
        "email": "Elinor.Ritchie@snailmail.com",
        "first_name": "Elinor",
        "last_name": "Ritchie",
        "state": "Arizona"
      },
      "shipped_order_history": [
        {
          "order_datetime": "Wed May 30 22:00:09 2012",
          "order_id": "T103929516925"
        },
        {
          "order_datetime": "Thu Aug  4 22:00:09 2011",
          "order_id": "T573145204032"
        }
      ]
    }
  ]
}

Updated: