[QROQ] Query Language

lib.js

复制代码
import { parse, evaluate } from "groq-js"

export let groq = async ([query]) => {
  let tree = parse(query)
  return async dataset => {
    let result = await evaluate(tree, { dataset })
    return await result.get()
  }
}
复制代码

 

Projections in GROQ enable you to restructure your filtered results into any form you want. You can create custom new fields based on the current values in scope and prepare your data exactly the way you want to be displayed to users.

Create a basic query which return all the data:

index.js

复制代码
import fs from "fs-extra"
import { groq } from "./lib.js"

let people = [
    {
        name: 'wan',
        age: 23
    },
    {
        name: 'tian',
        age: 27
    }
]

let query = await groq`
*
`

let result = await query(people)

console.log(result) // [ { name: 'wan', age: 23 }, { name: 'tian', age: 27 } ]
复制代码

 

Add a filter for the query:

let query = await groq`
*[name=='tian']
`

let result = await query(people)

console.log(result) // [ { name: 'tian', age: 27 } ]

 

If we just want the name prop:

let query = await groq`
*[name=='tian'].name
`

let result = await query(people)

console.log(result) // [ 'tian' ]

 

You can restructure the return data:

let query = await groq`
    *[name=='tian']
        {"newName": name + "new", "newAge": age + 5}
`
// [ { newName: 'tiannew', newAge: 32 } ]

 

GROQ's select function works kind of like a JavaScript switch statement. You give it some conditions and a default and it will assign the first condition that passes to the new field you've created.

Using select function for condition, select function works as `switch` function

复制代码
let people = [
    {
        name: 'wan',
        age: 23
    },
    {
        name: 'tian',
        age: 27
    },{
        name: 'yue',
        age: 31
    }
]
let query = await groq`
    *[]
        {
            "fristName": name,
            "group": select(
                age < 30 => "young",
                "old"
            )
        }
`
/**
 * [
  { fristName: 'wan', group: 'young' },
  { fristName: 'tian', group: 'young' },
  { fristName: 'yue', group: 'old' }
]
 */
复制代码

So what code does is 

if age < 30, assign group value as young

Default value as old

 

You can combine mutli groups:

复制代码
let query = await groq`
    *[]
        {
            "firstName": name,
            "group": select(
                age < 20 => "too young",
                age < 30 => "young",
                "Super"
            )
        }
        {
            "description": firstName + " is " + group
        }
`
/**
 * [
  { description: 'wan is too young' },
  { description: 'tian is young' },
  { description: 'yue is Super' }
]
 */
复制代码

As you can see, this will reconstructure the data.

 

The in keyboard in GROQ allows you to compare properties from your current JSON object scope against an Array of values to control which values should be returned. This becomes very important when matching against ids, types, and other fields that might exist on two separate JSON objects.

If the result we want to query is an array type inside object:
let query = await groq`
    *["Poison" in type]
`

It finds all the pokemon which is Poison type.

 

let query = await groq`
    *[egg in ["5 km"]]
`

It finds all the pokeon in 5 km egg.

 

let query = await groq`
    *[egg in ["5 km", "2 km"]]
`

Find both 2 km and 5km.

 

When working with large datasets, or when you simply want the first couple of results, it's essential to understand how to slice an Array using GROQ. The syntax is simple and can be used on any Array from your JSON, it's mainly a matter of knowing where you want your start index and end index of the Array of results you want to return.

Let's say we want to only get first 5 results:

let query = await groq`
    *[egg in ["5 km", "2 km"]]
    [0..5]
        {"hatch": name + " hatches in " + egg}
            .hatch
`

It is index based, so from index 0 to index 5, you will get 6 results.

 

If you just want 5 result, instead of 6:

let query = await groq`
    *[egg in ["5 km", "2 km"]]
    [0...5]
        {"hatch": name + " hatches in " + egg}
            .hatch
`

 

GROQ provides a useful order function for sorting the results of any Array in your JSON. Pass in the name of the property that you want to sort on and then the desc or asc to determine the order and you'll get your data back just how you want it.

Using order(prop) for asc sorting:

let query = await groq`
    *[egg in ["5 km", "2 km"]]
    [0..10] {id, name} | order(name)
`

 

For desc:

let query = await groq`
    *[egg in ["5 km", "2 km"]]
    [0..10] {id, name} | order(name desc)
`

 

Let's say, you only return names, you need to use '@' sign to return the current scope:

let query = await groq`
    *[egg in ["5 km", "2 km"]]
    [0..10].name | order(@ desc)
`

 

Notice that following two has the same effect:

let query = await groq`
    *[] | order(@.name)
`

let query = await groq`
    *[] | order(name)
`

 

GROQ enables you to join together arrays of JSON objects by looping through arrays inside of projections and using the in keyword to match items based on values. This lesson uses Pokemon to demonstrate matching a base Pokemon with the Pokemon's evolutions from a Pokedex dataset.

复制代码
let query = await groq`
    *[]
    [0..5]
    {
        name,
        num,
        "evolutions": *[num in ^.next_evolution[].num]{name, num}
    }
`
复制代码

In the parent query: we create a new prop "evolutions" which contains current pokemon's 'next_evolution'.

^: is referingn to parnet query:

    {
        name,
        num,
       ..
    }

 

We can also use GROQ's in keyword in our filters and negate it using the !() syntax. This allows us to exclude items that might be included later on in joins before we even get to the projection stage of our query. This example demonstrates filtering out all of the evolutions of Pokemon since they will be included by joining them into the base Pokemon objects.

Based on the previous example, in the finial result, we only want to list the base evolution, and filter continues evolutions:
复制代码
let query = await groq`
    *[!(num in *[].next_evolution[].num)]
    [0..5]
    {
        name,
        num,
        "evolutions": *[num in ^.next_evolution[].num]{name, num}
    }
`
复制代码

 

GROQ enables you to join together data in whatever format you want. Based on the dataset, sometimes the query needs to include a subquery where you must track which scope the query is running to be able to compare values against values in the parent scope. The parent scope can be accessed through the ^ so you know which scope the value belongs to.

复制代码
let query = await groq`
    *[]
    [0..3]
    {
        name,
        type,
        "matchup": *[
            count(
                weaknesses[@ in ^.^.type]
            ) > 0
        ]
            [0...3]
                {name, type, weaknesses, "message": ^.name + " vs. " + name}
    }
`
复制代码

 

 

 

 

 

 

 

 

 

posted @   Zhentiw  阅读(163)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2019-11-21 [HTML5] Using HTMLPortalElement to improve MPA preformance
2019-11-21 [CSS] prefers-reduced-motion
2018-11-21 [Testing] Config jest to test Javascript Application -- Part 2
2017-11-21 [ES6] The Iterator Protocol
2017-11-21 [Python] for.. not in.. Remove Deduplication
2017-11-21 [Python] String Join
2017-11-21 [Python] Slicing Lists
点击右上角即可分享
微信分享提示