Index
Edit

Query Cheat Sheet - GROQ

You could go off and read the entire how-to as well, but below we've collected some typical queries in GROQ. To actually run them you would either need the JavaScript or PHP clients or the Vision plugin that runs queries right inside the Content Studio.

Special variables

*   // Everything, i.e. all documents
*[ @["1"] ] // @ refers to the root value (document) of the scope
*{"arraySizes": arrays[]{"size": count(@)}} // @ also works for nested scopes

Constraints

*[_id == "abc.123"] // _id equals
*[_type in ["movie", "person"]] // _type is movie or person
*[_type == "movie" && popularity > 15 && releaseDate > "2016-04-25"] // multiple constraints AND
*[_type == "movie" && (popularity > 15 || releaseDate > "2016-04-25")] // multiple constraints OR
*[popularity < 15] // less than
*[popularity > 15] // greater than
*[popularity <= 15] // less than or equal
*[popularity >= 15] // greater than or equal
*[popularity == 15]
*[releaseDate != "2016-04-27"] // not equal
*[!(releaseDate == "2016-04-27")] // not equal
*[!(releaseDate != "2016-04-27")] // i couldn't fail to disagree with you less
*[_updatedAt > '2018-04-20T20:43:31Z'] // Use zulu-time when comparing datetimes to strings
*[name < "Baker"] // Records whose name precedes "Baker" alphabetically
*[awardWinner == true] // match boolean
*[awardWinner] // true if awardWinner == true
*[!awardWinner] // true if awardWinner == false
*[title == "Aliens"]
*[title in ["Aliens", "Interstellar", "Passengers"]]
*[_id in path("a.b.c.*")] // _id matches a.b.c.d but not a.b.c.d.e
*[_id in path("a.b.c.**")] // _id matches a.b.c.d, and also a.b.c.d.e.f.g, but not a.b.x.1
*[!(_id in path("drafts.**"))] // _id matches anything that is not under the drafts-path
*[defined(awardWinner)] // has the attribute `awardWinner`
*["yolo" in tags] // documents that have the string "yolo" in the array "tags"
*[status in ["completed", "archived"]] // the string field status is either == "completed" og "archived"
*[text match "word"] // text contains the word "word"
*[title match "wo*"] // title contains a word starting with "wo"
*[[title, body] match ["wo*", "zero"]] // title and body combined contains a word starting with "wo" and the full word "zero"
*[body[].children[].text match "aliens"] // are there any aliens someshere in my rich text?
*[tags[] match "frui*"] // any document tagged with a tag starting with the letters 'frui'
*[castMembers[].person._ref == 'person_sigourney-weaver'] // Any document having a castMember referencing sigourney as its person
*[slug.current == "some-slug"] // nested properties

Slice Operations

Note: Default limit is 100.

*[_type == "movie"][0] // a single movie (an object is returned, not an array)
*[_type == "movie"][0..5] // first 6 movies (inclusive)
*[_type == "movie"][0...5] // first 5 movies (non-inclusive)
*[_type == "movie"]{title}[0...10] // first 10 movie titles
*[_type == "movie"][0...10]{title} // first 10 movie titles

Also note: The above queries don't make much sense without also specifying an order. E.g. the "first 6 movies" query only returns "first" movies in the sense that these are the first six movies the backend happens to pull out.

Ordering

Note: There is no default ordering, so if you're querying for a subset of your documents it's usually a good idea to specify order.

// order results
*[_type == "movie"] | order(_createdAt asc)

// order results by multiple attributes
*[_type == "movie"] | order(releaseDate desc) | order(_createdAt asc)

// order todo items by descending priority,
// where priority is equal, list most recently updated
// item first
*[_type == "todo"] | order(priority desc, _updatedAt desc) 

// the single, oldest document
*[_type == "movie"] | order(_createdAt asc) [0]

// the single, newest document
*[_type == "movie"] | order(_createdAt desc) [0]

// oldest 10 documents
*[_type == "movie"] | order(_createdAt asc) [0..9]

// BEWARE! This returns 10 random documents, ordered ascendingly by _createdAt
*[_type == "movie"][0..9] | order(_createdAt asc)

// limit/offset using external params (see client documentation)
*[_type == "movie"] | order(_createdAt asc) [$start..$end]

Joins

// Fetch movies with title, and join with poster asset with path + url
*[_type=='movie']{title,poster{asset->{path,url}}}

// Say castMembers is an array containing objects with character name and a reference to the person:
// We want to fetch movie with title and an attribute named "cast" which is an array of actor names
*[_type=='movie']{title,'cast': castMembers[].person->name}

// Same query as above, except "cast" now contains objects with person._id and person.name
*[_type=='movie']{title,'cast': castMembers[].person->{_id, name}}

// Using the ^ operator to refer to the enclosing document. Here ^._id refers to the id
// of the enclosing person record.
*[_type=="person"]{
  name,
  "relatedMovies": *[_type=='movie' && references(^._id)]{ title }
}

// Books by author.name (book.author is a reference)
*[_type == "book" && author._ref in *[_type=="author" && name=="John Doe"]._id ]{...}

Object Projections

// return only title
*[_type == 'movie']{title} 

// return values for multiple attributes
*[_type == 'movie']{_id, _type, title} 

// explicitly name the return field for _id
*[_type == 'movie']{'renamedId': _id, _type, title} 

// Return an array of attribute values (no object wrapper)
*[_type == 'movie'].title
*[_type == 'movie']{'characterNames': castMembers[].characterName}

// movie titled Arrival and its posterUrl
*[_type=='movie' && title == 'Arrival']{title,'posterUrl': poster.asset->url} 

// Explicitly return all attributes
*[_type == 'movie']{...} 

// Some computed attributes, then also add all attributes of the result
*[_type == 'movie']{'posterUrl': poster.asset->url, ...} 

// Default values when missing or null in document
*[_type == 'movie']{..., 'rating': coalesce(rating, 'unknown')}

// Number of elements in array 'actors' on each moveie
*[_type == 'movie']{"actorCount": count(actors)} 

// Apply a projection to every member of an array
*[_type == 'movie']{castMembers[]{characterName, person}} 

// Filter embedded objects
*[_type == 'movie']{castMembers[characterName match 'Ripley']{characterName, person}} 

// Follow every reference in an array of references
*[_type == 'book']{authors[]->{name, bio}}

// Explicity name the outer return field
{'threeMovieTitles': *[_type=='movie'][0..2].title}

// Combining several unrelated queries in one request
{'featuredMovie': *[_type == 'movie' && title == 'Alien'][0], 'scifiMovies': *[_type == 'movie' && 'sci-fi' in genres]}

Conditionals

// select() returns the first => pair whose left-hand side evaluates to true
*[_type=='movie']{..., "popularity": select(
  popularity > 20 => "high",
  popularity > 10 => "medium",
  popularity <= 10 => "low",
)}

// The first select() parameter without => is returned if no previous matches are found
*[_type=='movie']{..., "popularity": select(
  popularity > 20 => "high",
  popularity > 10 => "medium",
  "low",
)}

// Projections also have syntactic sugar for inline conditionals
*[_type=='movie']{
  ...,
  releaseDate >= '2018-06-01' => {
    "screenings": *[_type == 'screening' && movie._ref == ^._id],
    "news": *[_type == 'news' && movie._ref == ^._id],
  },
  popularity > 20 && rating > 7.0 => {
    "featured": true,
    "awards": *[_type == 'award' && movie._ref == ^._id],
  },
}

// The above is exactly equivalent to:
*[_type=='movie']{
  ...,
  ...select(releaseDate >= '2018-06-01' => {
    "screenings": *[_type == 'screening' && movie._ref == ^._id],
    "news": *[_type == 'news' && movie._ref == ^._id],
  }),
  ...select(popularity > 20 && rating > 7.0 => {
    "featured": true,
    "awards": *[_type == 'award' && movie._ref == ^._id],
  }),
}

Functions

// any document that references the document 
// with id person_sigourney-weaver, 
// return only title
*[references("person_sigourney-weaver")]{title}
// Movies which reference ancient people
*[_type=="movie" && references(*[_type=="person" && age > 99]._id)]{title} *[defined(tags)] // any document that has the attribute 'tags' // coalesce takes a number of attribute references // and returns the value of the first attribute
// that is non-null. In this example used to
// default back to the english language where a // finnish translation does not exist. *{"title": coalesce(title.fi, title.en)}
// count counts the number of items in a collection count(*[_type == 'movie' && rating == 'R']) // returns number of R-rated movies
*[_type == 'movie']{ title, "actorCount": count(actors) // Counts the number of elements in the array actors }

Previous: How Queries Work - GROQNext: What About GraphQL?