0.4.0
Notion-query-builder is an opinionated filter query builder written in Typescript for use with the official Notion javascript client.
Note: This software is not affliated with Notion Labs, Inc. Issues and/or support should relating to this library be directed to the project's issue tracker.
Compatibility | Version Id |
---|---|
Notion API | 2022-06-28 |
Notion JS SDK | v2.2.3+ |
Javascript | ES2019+ |
npm i notion-query-builder
// or alternatively, [yarn|pnpm] add notion-query-builder
import nob from 'https://deno.land/x/notion_query_builder/mod.ts'
// note: for a smaller package size, try the npm version as it's stripped of development artifacts
import nob from 'npm:notion-query-builder'
As your filter queries become more complex, so does the size of the JSON you'll write for them. Large unwieldy blocks of JSON are always a hassle to reason about and maintain - often, solutions to manage this data utimately leads to code bloat.
node-query-builder
offers a simple and easy-to-use API to write filters and conditions programatically, reducing the effort and amount of code required by many factors.
To get started, here's a high level overview of the library:
toJSON()
method.import { Client } from '@notionhq/client';
import nob from 'notion-query-builder';
const notion = new Client({ auth: process.env.NOTION_API_KEY });
const myFilter = nob.filterQuery([
nob.checkboxFilter('Published', nob.equal(true)),
nob.multiSelectFilter('Tags', nob.contains(['A', 'B']))
]);
const response = await notion.databases.query({
database_id: databaseId,
filter: myFilter.toJson()
});
{
"and": [
{
"property": "Published",
"checkbox": {
"equals": true
}
},
{
"property": "Tags",
"multi_select": {
"contains": "A"
}
},
{
"property": "Tags",
"multi_select": {
"contains": "B"
}
}
]
}
notion-query-builder
is inspired by elastic-builder and the countless hours it has saved writing ElasticSearch queries.
MIT
A random charity appears!
Young Women’s Trust offers support to young women aged 18 to 30, who are living on low or no pay and want to build a better future, through Work It Out. Work It Out is a free service that offers coaching and personalised feedback on CV and job applications.
Org: Young Women's Trust, reg. charity no. 217868
Queries and special filters take other filters as arguments
A filter is a single condition used to specify and limit the entries returned from a database query. Database queries can be filtered by page property values. The API supports filtering by the following property types: rich_text, phone_number, number, checkbox, select, multi-select, date, people, files, relation, status, and formula. You may also filter a database by created_time or last_edited_time, even if these aren't present as properties on the database.
((FilterQueryFilter | Array<FilterQueryFilter>))
const query = nob.filterQuery(nob.textQuery('name', nob.equal('Jim')))
// when given array, filterQuery() autowraps child filters in a new CompoundFilter with an "and" list
const query = nob.filterQuery([
nob.textQuery('name', nob.equal('Jack')),
nob.textQuery('name', nob.equal('Jill'))
])
const query = nob.filterQuery(
nob.compoundFilter()
.or(nob.textQuery('name', nob.equal('Jack')))
.or(nob.textQuery('name', nob.equal('Jill')))
)
FilterQueryFilterObject
:
A compound filter object combines several filter objects together using a logical operator and or or. A compound filter can even be combined within a compound filter, but only up to two nesting levels deep.
Extends Filter
const filter = nob.compoundFilter()
.and(nob.checkboxFilter('Write todo list', nob.equal(true))
.or(nob.textFilter('name', nob.contain('Bridge')))
Append queries to the "and" list
((CompoundFilterFilterRecursive | Array<CompoundFilterFilterRecursive>))
CompoundFilter
:
allows CompoundFilter to be chainable
Append queries to the "or" list
((CompoundFilterFilterRecursive | Array<CompoundFilterFilterRecursive>))
CompoundFilter
:
allows CompoundFilter to be chainable
CompoundFilterObject
:
A rollup filter condition can be applied to database properties of type "rollup". Rollups which evaluate to arrays accept a filter with an any, every, or none condition; rollups which evaluate to numbers accept a filter with a number condition; and rollups which evaluate to dates accept a filter with a date condition.
Extends TermFilter
(RollUpFilterAggregationType)
the aggregation type to use
(RollUpFilterFilter)
the child filter for the rollup
const filter = nob.rollUpFilter('any', nob.numberQuery('age', nob.greaterThan(12)))
Array<Array<RollUpFilterObject>>
A formula filter condition can be applied to database properties of type "formula".
Extends TermFilter
(FormulaFilterAggregationType)
the aggregation type to use
(FormulaFilterFilter)
the child filter for the formula
const filter = nob.formulaFilter('number', nob.numberQuery('age', nob.greaterThan(12)))
Array<Array<FormulaFilterObject>>
Term Level Filters take Conditions as arguments
A text filter condition can be applied to database properties of types "title", "rich_text", "url", "email", and "phone_number".
Extends TermFilter
(string)
the database property
((TextFilterCondition | Array<TextFilterCondition>))
(TextPropertyFilterType
= rich_text
)
const filter = nob.textFilter('Name', nob.equal('Jim'))
const filter = nob.textFilter('Name', nob.equal('My blog title'), 'title')
const filter = nob.textFilter('Name', nob.equal('http://notion.com'), 'url')
const filter = nob.textFilter('Name', nob.equal('hello@example.com'), 'email')
const filter = nob.textFilter('Name', nob.equal('000000000000'), 'phone_number')
Array<Array<TextFilterObject>>
A number filter condition can be applied to database properties of type "number".
Extends TermFilter
(string)
the database property
((NumberFilterCondition | Array<NumberFilterCondition>))
const filter = nob.numberFilter('age', nob.equal(12))
const filter = nob.numberFilter('age', nob.greaterThan(12))
Array<Array<NumberFilterObject>>
A checkbox filter condition can be applied to database properties of type "checkbox".
Extends TermFilter
(string)
the database property
((CheckboxFilterCondition | Array<CheckboxFilterCondition>))
const filter = nob.checkboxFilter('Write todo list', nob.equal(true))
Array<Array<CheckboxFilterObject>>
A select filter condition can be applied to database properties of type "select".
Extends TermFilter
(string)
the database property
((SelectFilterCondition | Array<SelectFilterCondition>))
const filter = nob.selectFilter('assignee', nob.eq('Jim'))
Array<Array<SelectFilterObject>>
A multi-select filter condition can be applied to database properties of type "multi_select".
Extends TermFilter
(string)
the database property
((MultiSelectFilterCondition | Array<MultiSelectFilterCondition>))
const filter = nob.multiSelectFilter('fruits', nob.equal('apple'))
const filter = nob.multiSelectFilter('fruits', nob.equal(['apple', 'pear']))
Array<Array<MultiSelectFilterObject>>
Array<Array<MultiSelectFilterObject>>
A multi-select filter condition can be applied to database properties of type "multi_select".
Extends TermFilter
(string)
the database property
((MultiSelectFilterCondition | Array<MultiSelectFilterCondition>))
const filter = nob.multiSelectFilter('fruits', nob.equal('apple'))
const filter = nob.multiSelectFilter('fruits', nob.equal(['apple', 'pear']))
Array<Array<MultiSelectFilterObject>>
Array<Array<MultiSelectFilterObject>>
A status filter condition can be applied to database properties of type "status".
Extends TermFilter
(string)
the database property
((StatusFilterCondition | Array<StatusFilterCondition>))
const filter = nob.statusFilter('status', nob.eq('In Progress'))
Array<Array<StatusFilterObject>>
A date filter condition can be applied to database properties of types "date", "created_time", and "last_edited_time".
Extends TermFilter
(string)
the database property
((DateFilterCondition | Array<DateFilterCondition>))
(DateTimestampFilterType
= date
)
const filter = nob.dateFilter('published_date', nob.onOrAfter('2023-01-01'))
const filter = nob.dateFilter('blog', nob.after('2023-01-01'), 'created_time')
const filter = nob.dateFilter('blog', nob.after('2023-01-01'), 'last_edited_time')
Array<Array<DateFilterObject>>
A people filter condition can be applied to database properties of types "people", "created_by", and "last_edited_by".
Extends TermFilter
(string)
the database property
((PeopleFilterCondition | Array<PeopleFilterCondition>))
(PeoplePropertyFilterType
= people
)
const filter = nob.peopleFilter('firstName', nob.equal('Jim'))
const filter = nob.peopleFilter('firstName', nob.equal('Jim'), 'created_by')
const filter = nob.peopleFilter('firstName', nob.equal('Jim'), 'last_edited_by')
Array<Array<PeopleFilterObject>>
A files filter condition can be applied to database properties of type "files".
Extends TermFilter
(string)
the database property
((FilesFilterCondition | Array<FilesFilterCondition>))
const filter = nob.filesFilter('fileType', nob.equal('pdf'))
Array<Array<FilesFilterObject>>
A relation filter condition can be applied to database properties of type "relation".
Extends TermFilter
(string)
the database property
((RelationFilterCondition | Array<RelationFilterCondition>))
const filter = nob.relationFilter('user', nob.contains('6c574cee-ca68-41c8-86e0-1b9e992689fb'))
Array<Array<RelationFilterObject>>
Conditions take native data types as arguments
Only return pages where the page property value matches the provided value exactly.
Extends Condition
const condition = nob.equal('Bridge')
const condition = nob.equal(['Bridge', 'Moat'])
const condition = nob.equal(12)
const condition = nob.equal(false)
// aliases
export condition = nob.equals('Bridge')
export condition = nob.eq('Bridge')
export condition = nob.is('Bridge')
export condition = nob.be('Bridge')
Only return pages where the page property value does not match the provided value exactly.
Extends Condition
const condition = nob.notEqual('Bridge')
const condition = nob.notEqual(['Bridge', 'Moat'])
const condition = nob.notEqual(12)
const condition = nob.notEqual(false)
// aliases
const condition = nob.notEquals('Bridge')
const condition = nob.neq('Bridge')
const condition = nob.isnt('Bridge')
const condition = nob.isNot('Bridge')
Only return pages where the page property value is empty.
Extends Condition
const condition = nob.empty()
// aliases
const condition = nob.isEmpty()
const condition = nob.notExist()
Only return pages where the page property value is present.
Extends Condition
const condition = nob.notEmpty()
// aliases
const condition = nob.isNotEmpty()
const condition = nob.exists()
Only return pages where the page property value contains the provided value.
Extends Condition
const condition = nob.contain('Bridge')
const condition = nob.contain(['Bridge', 'Moat'])
// aliases
const condition = nob.contains('Bridge')
const condition = nob.has('Bridge')
const condition = nob.include('Bridge')
const condition = nob.includes('Bridge')
Only return pages where the page property value does not contain the provided value.
Extends Condition
const condition = nob.notContain('Bridge')
const condition = nob.notContain(['Bridge', 'Moat'])
// aliases
const condition = nob.notContains('Bridge')
const condition = nob.doesNotContain('Bridge')
const condition = nob.hasNot('Bridge')
const condition = nob.exclude('Bridge')
const condition = nob.excludes('Bridge')
Only return pages where the page property value starts with the provided value.
Extends Condition
const condition = nob.startsWith('Bridge')
const condition = nob.startsWith(['Bridge', 'Moat'])
Only return pages where the page property value ends with the provided value.
Extends Condition
const condition = nob.endsWith('Bridge')
const condition = nob.endsWith(['Bridge', 'Moat'])
Only return pages where the page property value is greater than the provided value.
Extends Condition
const condition = nob.greaterThan(12)
// aliases
const condition = nob.gt(12)
const condition = nob.moreThan(12)
Only return pages where the page property value is greater than or equal to the provided value.
Extends Condition
const condition = nob.greaterThanOrEqualTo(12)
// aliases
const condition = nob.gte(12)
const condition = nob.moreThanOrEqualTo(12)
Only return pages where the page property value is less than the provided value.
Extends Condition
const condition = nob.lessThan(12)
// aliases
const condition = nob.lt(12)
Only return pages where the page property value is less than or equal to the provided value.
Extends Condition
const condition = nob.lessThanOrEqualTo(12)
// aliases
const condition = nob.lte(12)
Only return pages where the page property value is before the provided date. If a date with a time is provided, the comparison is done with millisecond precision. Note that if no timezone is provided, the default is UTC.
Extends Condition
const condition = nob.before('2023-01-01')
const condition = nob.before(new Date(2023, 0, 1))
Only return pages where the page property value is on or before the provided date. If a date with a time is provided, the comparison is done with millisecond precision. Note that if no timezone is provided, the default is UTC.
Extends Condition
const condition = nob.onOrBefore('2023-01-01')
const condition = nob.onOrBefore(new Date(2023, 0, 1))
Only return pages where the page property value is on or before the provided date. If a date with a time is provided, the comparison is done with millisecond precision. Note that if no timezone is provided, the default is UTC.
Extends Condition
const condition = nob.onOrBefore('2023-01-01')
const condition = nob.onOrBefore(new Date(2023, 0, 1))
Only return pages where the page property value is after the provided date. If a date with a time is provided, the comparison is done with millisecond precision. Note that if no timezone is provided, the default is UTC.
Extends Condition
const condition = nob.after('2023-01-01')
const condition = nob.after(new Date(2023, 0, 1))
Only return pages where the page property value is on or after the provided date. If a date with a time is provided, the comparison is done with millisecond precision. Note that if no timezone is provided, the default is UTC.
Extends Condition
const condition = nob.onOrAfter('2023-01-01')
const condition = nob.onOrAfter(new Date(2023, 0, 1))
Only return pages where the page property value is on or after the provided date. If a date with a time is provided, the comparison is done with millisecond precision. Note that if no timezone is provided, the default is UTC.
Extends Condition
const condition = nob.onOrAfter('2023-01-01')
const condition = nob.onOrAfter(new Date(2023, 0, 1))
Only return pages where the page property value is within the past week.
Extends Condition
const condition = nob.pastWeek()
Only return pages where the page property value is within the past month.
Extends Condition
const condition = nob.pastMonth()
Only return pages where the page property value is within the past year.
Extends Condition
const condition = nob.pastYear()
Only return pages where the page property value is within the current week. The current week starts on the most recent Sunday and ends on the upcoming Saturday.
Extends Condition
const condition = nob.thisWeek()
Only return pages where the page property value is within the next week.
Extends Condition
const condition = nob.nextWeek()
Only return pages where the page property value is within the next month.
Extends Condition
const condition = nob.nextMonth()
Only return pages where the page property value is within the next year.
Extends Condition
const condition = nob.nextYear()
Utility functions for Sort
A sort is a condition used to order the entries returned from a database query. A database query can be sorted by a property and/or timestamp and in a given direction. For example, a library database can be sorted by the "Name of a book" (i.e. property) and in ascending (i.e. direction).
((string | SortTimeType))
the database field
(SortDirection
= descending
)
the sort direction
const sort = nob.sort('published_at')
const sort = nob.sort('created_time', 'ascending')
const sort = nob.sort('last_edited_time', 'ascending')
(SortProperty | SortTime)
:
TermFilter is a base class which represents all filters that take conditions as arguments
Extends Filter
(string)
the database field which this filter will be applied
(string)
certain filters can have variations eg TextFilter can be either title, rich_text etc
(TermFilterType)
determines whether this is a propertyFilter or a timestampFilter
A hook to optionally apply any tranforms to the condition value(s) when returning the toJson() object
(ConditionValueObject)
any
:
ConditionValueObject
// For DateFilter, we convert any Date objects to ISO Strings
transform(conditionObject: { [k: string]: string | Date | boolean }) {
return Object.keys(conditionObject).reduce((acc, key) => ({
...acc,
[key]: conditionObject[key] instanceof Date ? (conditionObject[key] as Date).toISOString() : conditionObject[key]
}), {});
}
the filter's "termFilterType" value
TermFilterType
:
TermFilter types
Type:
("property"
| "timestamp"
)
// when "property"
{
property: 'field',
...
}
// when "timestamp"
{
timestamp: 'field',
...
}
Possible conditions to be used with TextFilter
Type: (EqualCondition<string> | NotEqualCondition<string> | ContainCondition<string> | NotContainCondition<string> | StartsWithCondition<string> | EndsWithCondition<string> | EmptyCondition | NotEmptyCondition)
Possible filter types to be used with TextFilter
Type:
("title"
| "rich_text"
| "url"
| "email"
| "phone_number"
)
JSON representation of the TextFilter
Type: (TextPropertyFilterObject<(string | Array<string>)> | TextPropertyFilterObject<boolean>)
Possible conditions to be used with NumberFilter
Type: (EqualCondition<number> | NotEqualCondition<number> | GreaterThanCondition<number> | GreaterThanOrEqualToCondition<number> | LessThanCondition<number> | LessThanOrEqualToCondition<number> | EmptyCondition | NotEmptyCondition)
JSON representation of the NumberFilter
Type: (NumberPropertyFilterObject<(number | Array<number>)> | NumberPropertyFilterObject<boolean>)
Allowed conditions for checkboxFilter
Type: (EqualCondition<boolean> | NotEqualCondition<boolean>)
JSON representation of the checkboxFilter
Type: CheckboxPropertyFilterObject<boolean>
Possible conditions to be used with SelectFilter
Type: (EqualCondition<string> | NotEqualCondition<string> | EmptyCondition | NotEmptyCondition)
JSON representation of the SelectFilter
Type: (SelectPropertyFilterObject<(string | Array<string>)> | SelectPropertyFilterObject<boolean>)
Possible conditions to be used with MultiSelectFilter
Type: (ContainCondition<string> | NotContainCondition<string> | EmptyCondition | NotEmptyCondition)
Possible conditions to be used with MultiSelectFilter
Type: (ContainCondition<string> | NotContainCondition<string> | EmptyCondition | NotEmptyCondition)
JSON representation of the MultiSelectFilter
Type: (MultiSelectPropertyFilterObject<(string | Array<string>)> | MultiSelectPropertyFilterObject<boolean>)
JSON representation of the MultiSelectFilter
Type: (MultiSelectPropertyFilterObject<(string | Array<string>)> | MultiSelectPropertyFilterObject<boolean>)
Possible conditions to be used with StatusFilter
Type: (EqualCondition<string> | NotEqualCondition<string> | EmptyCondition | NotEmptyCondition)
JSON representation of the StatusFilter
Type: (StatusPropertyFilterObject<(string | Array<string>)> | StatusPropertyFilterObject<boolean>)
Possible conditions to be used with DateFilter
Type: (EqualCondition<(string | Date)> | BeforeCondition<(string | Date)> | OnOrBeforeCondition<(string | Date)> | AfterCondition<(string | Date)> | OnOrAfterCondition<(string | Date)> | PastWeekCondition | PastMonthCondition | PastYearCondition | ThisWeekCondition | NextWeekCondition | NextMonthCondition | NextYearCondition | EmptyCondition | NotEmptyCondition)
filter type variants for DateFilter
Type:
("date"
| "created_time"
| "last_edited_time"
)
const filter = nob.DateFilter('blog', nob.after('2023-01-01'), 'created_time')
JSON representation of the DateFilter
Type: (DateTimestampFilterObject<(string | Array<string> | Date | Array<Date>)> | DateTimestampFilterObject<boolean> | DateTimestampFilterObject<Record<string, any>>)
filter type variations for PeopleFilter
Type:
("people"
| "created_by"
| "last_edited_by"
)
Possible conditions to be used with PeopleFilter
Type: (ContainCondition<string> | NotContainCondition<string> | EmptyCondition | NotEmptyCondition)
JSON representation of the PeopleFilter
Type: (PeoplePropertyFilterObject<(string | Array<string>)> | PeoplePropertyFilterObject<boolean>)
Possible conditions to be used with FilesFilter
Type: (EmptyCondition | NotEmptyCondition)
JSON representation of the FilesFilter
Type: FilesPropertyFilterObject<boolean>
Possible conditions to be used with RelationFilter
Type: (ContainCondition<string> | NotContainCondition<string> | EmptyCondition | NotEmptyCondition)
JSON representation of the RelationFilter
Type: (RelationPropertyFilterObject<(string | Array<string>)> | RelationPropertyFilterObject<boolean>)
Possible aggregation types for RollUpFilter
Type:
("any"
| "every"
| "none"
| "number"
| "date"
)
Possible conditions to be used with RollUpFilter
Type: (TextFilter | NumberFilter | DateFilter)
JSON representation of the RollUpFilter
Type: any
Possible aggregation types for FormulaFilter
Type:
("string"
| "checkbox"
| "number"
| "date"
)
Possible conditions to be used with FormulaFilter
Type: (TextFilter | CheckboxFilter | NumberFilter | DateFilter)
JSON representation of the FormulaFilter
Type: any
Possible filters to use with Compoundfilter
Type: (TextFilter | NumberFilter | CheckboxFilter | SelectFilter | MultiSelectFilter | StatusFilter | DateFilter | PeopleFilter | FilesFilter | RelationFilter | RollUpFilter | FormulaFilter)
Recursive to allow nesting a CompoundFilter within a CompoundFilter
Type: (CompoundFilter | CompoundFilterFilter)
Possible filters objects to return with Compoundfilter
Type: (TextFilterObject | NumberFilterObject | CheckboxFilterObject | SelectFilterObject | MultiSelectFilterObject | StatusFilterObject | DateFilterObject | PeopleFilterObject | FilesFilterObject | RelationFilterObject | RollUpFilterObject | FormulaFilterObject)
Recursive to allow nesting a CompoundFilter within a CompoundFilter
JSON representation of CompoundFilter
Type: {and: Array<CompoundFilterObjectRecursive>?, or: Array<CompoundFilterObjectRecursive>?}
(Array<CompoundFilterObjectRecursive>?)
Possible filters to use with FilterQuery
Type: (TextFilter | NumberFilter | CheckboxFilter | SelectFilter | MultiSelectFilter | StatusFilter | DateFilter | PeopleFilter | FilesFilter | RelationFilter | RollUpFilter | FormulaFilter | CompoundFilter)
JSON representation of FilterQuery
Type: (TextFilterObject | NumberFilterObject | CheckboxFilterObject | SelectFilterObject | MultiSelectFilterObject | StatusFilterObject | DateFilterObject | PeopleFilterObject | FilesFilterObject | RelationFilterObject | RollUpFilterObject | FormulaFilterObject | CompoundFilterObject)
The base class for all conditions.
Type: {direction: SortDirection}
(SortDirection)
Type: any
Type:
("created_time"
| "last_edited_time"
)
Type: any