Query Cheat Sheet

While we work on the full reference documentation for our query-language GROQ, this has to do the job. You should probably read the how-to first. If you need help setting up a client to perform these queries in your front end, you should check out the documentation for the client for javascript or PHP.


*[_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
*[published == true] // match boolean
*[published] // true if published == true
*[!published] // true if published == 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
*[defined(published)] // has the attribute `published`
*["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"

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: These examples don't make much sense without also specifying an order. The "first 6 movies" query above is only "first" in the sense that these are the first six movies the backend happens to pull out.


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]


// Fetch movies with title, and join with poster asset with 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
*[_type=='movie']{title,'cast': castMembers[].person->{_id, name}}

Object Projections

*{title} // return only title
*{_id, _type, title} // return values for multiple attributes
{'threeMovieTitles': *[_type=='movie'][0..2].title // explicity name the outer return field
*{'renamedId': _id, _type, title} // explicitly name the return field for _id
*[_type == 'movie']{title} // only movie titles
*[_type=='movie' && title == 'Arrival']{title,'posterUrl': poster.asset->url} // movie titled Arrival and its posterUrl
*[_type == 'movie']{...} // Explicitly return all attributes
*[_type == 'movie']{..., 'posterUrl': poster.asset->url} // all attributes and materialize the posterUrl
*[_type == 'movie']{"actorCount": count(actors)} // number of elements in array 'actors' on each moveie

Default values

Apply values to returned data, effectively defining default values

*[_type == "movie"]{title, "rating": "18", rating} // Get movie title and rating. Set movie rating to "18" unless movie rating has a value
*[_type == "movie"]{..., "rating": "12"} // All movie attributes, override returned rating with "18", no matter what


// any document that references the document 
// with id person_sigourney-weaver, 
// return only 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.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 to query your documentsNext: Presenting Images