Concordance
A concordance answers "where does this word appear, everywhere, in order?" That is a different
question from search, and concordance is built to answer it exactly:
- Exhaustive — every occurrence, reachable through pagination. Nothing is dropped.
- Canonically ordered — Genesis → Revelation, then chapter, then verse. Never ranked by relevance.
- Aggregated — totals per book and per testament come back alongside the page.
- In context — each occurrence includes a keyword-in-context snippet.
Concordance queries need the translation to have been indexed. Check
concordanceIndexedAt on the translation — if it is null, the query returns an error telling
you which rake task to run. See Translations.
A full query
- GraphQL
- cURL
- Ruby
- Node.js
- Response
query ConcordanceBasic {
concordance(translation: "spa-rv1909", word: "misericordia", first: 10) {
totalCount
entry {
lemma
surfaceForms
totalOccurrences
verseCount
occurrencesByTestament {
old
new
}
}
edges {
cursor
node {
verse {
bookName
chapter
verse
text
}
context
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
curl https://bibleql.org/graphql \
-H "Authorization: Bearer $BIBLEQL_API_KEY" \
-H "Content-Type: application/json" \
--data '{"query":"query ConcordanceBasic { concordance(translation: \"spa-rv1909\", word: \"misericordia\", first: 10) { totalCount entry { lemma surfaceForms totalOccurrences verseCount occurrencesByTestament { old new } } edges { cursor node { verse { bookName chapter verse text } context } } pageInfo { hasNextPage endCursor } } }"}'
This query has no dedicated method in bibleql-ruby as of its current release. Use the GraphQL or cURL tab, or send the document with any HTTP client.
This query has no dedicated method in bibleql-js as of its current release. Use the GraphQL or cURL tab, or send the document with any HTTP client.
{
"data": {
"concordance": {
"totalCount": 398,
"entry": {
"lemma": "misericordi",
"surfaceForms": [
"misericordia",
"misericordias",
"misericordioso",
"misericordiosos"
],
"totalOccurrences": 424,
"verseCount": 398,
"occurrencesByTestament": {
"old": 327,
"new": 71
}
},
"edges": [
{
"cursor": "MToxOToxNg==",
"node": {
"verse": {
"bookName": "Génesis",
"chapter": 19,
"verse": 16,
"text": "Y deteniéndose él, los varones asieron de su mano, y de la mano de su mujer, y de las manos de sus dos hijas, según la misericordia de Jehová para con él; y le sacaron, y le pusieron fuera de la ciudad."
},
"context": "mujer, y de las manos de sus dos hijas, según la <mark>misericordia</mark> de Jehová para con él; y le sacaron, y le pusieron fuera"
}
},
{
"cursor": "MToxOToxOQ==",
"node": {
"verse": {
"bookName": "Génesis",
"chapter": 19,
"verse": 19,
"text": "He aquí ahora ha hallado tu siervo gracia en tus ojos, y has engrandecido tu misericordia que has hecho conmigo dándome la vida; mas yo no podré escapar al monte, no sea caso que me alcance el mal, y muera."
},
"context": "hallado tu siervo gracia en tus ojos, y has engrandecido tu <mark>misericordia</mark> que has hecho conmigo dándome la vida; mas yo no podré escapar"
}
},
{
"cursor": "MToyNDoxMg==",
"node": {
"verse": {
"bookName": "Génesis",
"chapter": 24,
"verse": 12,
"text": "Y dijo: Jehová, Dios de mi señor Abraham, dame, te ruego, el tener hoy buen encuentro, y haz misericordia con mi señor Abraham."
},
"context": "señor Abraham, dame, te ruego, el tener hoy buen encuentro, y haz <mark>misericordia</mark> con mi señor Abraham"
}
},
// ... 7 more
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "MTo0MzoxNA=="
}
}
}
}
Reading the response
Three parts, each answering something different.
entry — translation-wide aggregates
entry {
lemma
surfaceForms
totalOccurrences
verseCount
occurrencesByBook { bookId bookName count }
occurrencesByTestament { old new }
}
These cover the whole translation and are unaffected by paging. They are also unaffected
by your book and testament filters — entry always describes the word globally, which is
what makes it useful as a header above filtered results.
lemmais the normalized stem, and it can look mangled (misericordi). It is an index key, not something to show a user.surfaceFormsis what to display — up to 10 real word forms found in the text, most frequent first. It is a sample, not an exhaustive list.totalOccurrencescounts tokens;verseCountcounts verses. The first can exceed the second when a word repeats inside one verse.
edges — this page of occurrences
edges {
cursor
node {
context
verse { bookName chapter verse text }
}
}
context contains HTMLcontext wraps the matched term in <mark> tags. It is generated server-side from the verse
text, but you must still sanitize it before rendering as HTML — never interpolate it into the
DOM unescaped as a habit.
pageInfo — where you are
pageInfo { hasNextPage endCursor }
Pagination
Pass endCursor back as after:
query {
concordance(translation: "spa-rv1909", word: "amor", first: 25, after: "UFNBOjIzOjE=") {
edges { cursor node { verse { bookName chapter verse } } }
pageInfo { hasNextPage endCursor }
}
}
Cursors are opaque — do not decode or construct them. first defaults to 25 and is clamped to
1–100.
Keep paging while hasNextPage is true. Because ordering is canonical and stable, a cursor
stays valid across requests as long as the translation has not been re-indexed.
Filtering
| Argument | Effect |
|---|---|
book | Canonical id (PSA) or localized name (Salmos) |
testament | OLD or NEW |
The two combine with AND — book: "PSA", testament: OLD is a valid, non-contradictory
filter. This differs from randomVerse, where books overrides testament; see
API Behavior.
- GraphQL
- cURL
- Ruby
- Node.js
- Response
query ConcordanceByBook {
concordance(
translation: "spa-rv1909"
word: "misericordia"
book: "Salmos"
first: 10
) {
totalCount
edges {
node {
verse {
bookName
chapter
verse
text
}
}
}
}
}
curl https://bibleql.org/graphql \
-H "Authorization: Bearer $BIBLEQL_API_KEY" \
-H "Content-Type: application/json" \
--data '{"query":"query ConcordanceByBook { concordance( translation: \"spa-rv1909\" word: \"misericordia\" book: \"Salmos\" first: 10 ) { totalCount edges { node { verse { bookName chapter verse text } } } } }"}'
This query has no dedicated method in bibleql-ruby as of its current release. Use the GraphQL or cURL tab, or send the document with any HTTP client.
This query has no dedicated method in bibleql-js as of its current release. Use the GraphQL or cURL tab, or send the document with any HTTP client.
{
"data": {
"concordance": {
"totalCount": 164,
"edges": [
{
"node": {
"verse": {
"bookName": "Salmos",
"chapter": 4,
"verse": 1,
"text": "Al Músico principal: sobre Neginoth: Salmo de David. RESPÓNDEME cuando clamo, oh Dios de mi justicia: estando en angustia, tú me hiciste ensanchar: ten misericordia de mí, y oye mi oración."
}
}
},
{
"node": {
"verse": {
"bookName": "Salmos",
"chapter": 5,
"verse": 7,
"text": "Y yo en la multitud de tu misericordia entraré en tu casa: adoraré hacia el templo de tu santidad en tu temor."
}
}
},
{
"node": {
"verse": {
"bookName": "Salmos",
"chapter": 6,
"verse": 2,
"text": "Ten misericordia de mí, oh Jehová, porque yo estoy debilitado: sáname, oh Jehová, porque mis huesos están conmovidos."
}
}
},
// ... 7 more
]
}
}
}
Note two things in that response. totalCount drops from 398 to 164 — the count for Psalms
alone. And book accepted "Salmos", the localized name, rather than the canonical PSA;
either works.
Filters narrow edges and totalCount, but not entry, which stays translation-wide.
That is deliberate: it lets you show "164 of 398 occurrences are in Psalms" from a single
request.
Stemming
Matching runs through the translation's PostgreSQL text-search dictionary, so amor finds
amores and amoroso. Whether that happens depends on the translation:
hasStemming: true— linguistic stemming for that language is availablehasStemming: false— only exact word forms match
Check it before promising users fuzzy word matching.
Complexity budget
concordance carries a custom complexity cost proportional to first, against the schema's
overall budget of 300. Requesting first: 100 alongside deeply nested verse selections can
exceed it. If you hit a complexity error, lower first or select fewer fields per occurrence.
The word index
To browse what words exist rather than look one up, use concordanceIndex:
- GraphQL
- cURL
- Ruby
- Node.js
- Response
query {
concordanceIndex(translation: "spa-rv1909", prefix: "mis", first: 5) {
lemma
verseCount
totalOccurrences
}
}
curl https://bibleql.org/graphql \
-H "Authorization: Bearer $BIBLEQL_API_KEY" \
-H "Content-Type: application/json" \
--data '{"query":"query { concordanceIndex(translation: \"spa-rv1909\", prefix: \"mis\", first: 5) { lemma verseCount totalOccurrences } }"}'
This query has no dedicated method in bibleql-ruby as of its current release. Use the GraphQL or cURL tab, or send the document with any HTTP client.
This query has no dedicated method in bibleql-js as of its current release. Use the GraphQL or cURL tab, or send the document with any HTTP client.
{
"data": {
"concordanceIndex": [
{
"lemma": "misael",
"verseCount": 8,
"totalOccurrences": 8
},
{
"lemma": "misam",
"verseCount": 2,
"totalOccurrences": 2
},
{
"lemma": "miseal",
"verseCount": 2,
"totalOccurrences": 2
},
// ... 2 more
]
}
}
It returns an alphabetical frequency list — useful for building a word-study index page or an
autocomplete. minOccurrences filters out rare words; first is clamped to 1–200.
Note these entries are lemma values, with the same caveat as above: they are stems, not
display forms.