zoukankan      html  css  js  c++  java
  • [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}
        }
    `

     

     

     

     

     

  • 相关阅读:
    谷歌SEO和百度SEO的区别
    如何在本地搭建网站(图文教程)
    企业级Web服务器安全主动防御措施
    如何在Ubuntu下搭建tftp服务器
    十条服务器端优化Web性能的技巧
    APP开发者如何从应用程序中赚钱?
    5个让你的404页面变的更加实用的技巧
    修改linux的MAC地址
    剪切文件或目录命令
    shell内置命令和外部命令的区别
  • 原文地址:https://www.cnblogs.com/Answer1215/p/15582722.html
Copyright © 2011-2022 走看看