OData v4 query builder that uses a simple object-based syntax similar to MongoDB and js-data
yarn add odata-query
or
npm install --save odata-query
and then use the library
import buildQuery from 'odata-query'
const query = buildQuery({...})
fetch(`https://localhost${query}`)
where the query object syntax for {...}
is defined below. There is also react-odata which utilizies this library for a declarative React component.
See tests for examples as well
buildQuery({ filter: {...} })
=> '?$filter=...'
const filter = { PropName: 1 };
buildQuery({ filter })
=> '?$filter=PropName eq 1'
const filter = { PropName: { gt: 5 } };
buildQuery({ filter })
=> '?$filter=PropName gt 5'
Supported operators: eq
, ne
, gt
, ge
, lt
, le
, in
// `and` implied by using an array
const filter = [{ SomeProp: 1 }, { AnotherProp: 2 }, 'startswith(Name, "foo")'];
// or you can be explicit
const filter = {
and: [
{ SomeProp: 1 },
{ AnotherProp: 2 },
'startswith(Name, "foo")'
]
};
buildQuery({ filter })
=> '?$filter=SomeProp eq 1 and AnotherProp eq 2 and startswith(Name, "foo")'
Supported operators: and
, or
Using an object
const filter = {
ItemsProp: {
any: {
SomeProp: 1,
AnotherProp: 2
}
}
};
buildQuery({ filter })
=> '?$filter=ItemsProp/any(i:i/SomeProp eq 1 and i/AnotherProp eq 2)'
or also as an array of object
const filter = {
ItemsProp: {
any: [
{ SomeProp: 1 },
{ AnotherProp: 2},
]
}
};
buildQuery({ filter })
=> '?$filter=ItemsProp/any(i:i/SomeProp eq 1 and i/AnotherProp eq 2)'
const filter = {
ItemsProp: {
any: {
or: [
{ SomeProp: 1 },
{ AnotherProp: 2},
]
}
}
};
buildQuery({ filter })
=> '?$filter=ItemsProp/any(i:(i/SomeProp eq 1 or i/AnotherProp eq 2)'
Supported operators: any
, all
const filter = { PropName: { contains: 'foo' } };
buildQuery({ filter })
=> "$filter=contains(PropName, 'foo')"
Supported operators: startswith
, endswith
, contains
const filter = { 'length(PropName)': { gt: 10 } };
buildQuery({ filter })
=> "$filter=length(PropName) gt 10"
Supported operators: length
, tolower
, toupper
, trim
,
day
, month
, year
, hour
, minute
, second
,
round
, floor
, ceiling
const filter = { "indexof(PropName, 'foo')": { eq: 3 } };
buildQuery({ filter })
=> "$filter=indexof(PropName, 'foo') eq 3"
Supported operators: indexof
, substring
Coming soon
A string can also be passed as the value of the filter and it will be taken as is. This can be useful when using something like odata-filter-builder or if you want to just write the OData filter sytnax yourself but use the other benefits of the library, such as groupBy, expand, etc.
import f from 'odata-filter-builder';
const filter = f().eq('TypeId', '1')
.contains(x => x.toLower('Name'), 'a')
.toString();
buildQuery({ filter })
const select = ['Foo', 'Bar'];
buildQuery({ select })
=> '?$select=Foo,Bar'
const orderBy = ['Foo desc', 'Bar'];
buildQuery({ orderBy })
=> '?$orderby=Foo desc,Bar'
Coming soon
const page = 3;
const perPage = 25;
const top = perPage;
const skip = perPage * (page - 1);
buildQuery({ top, skip })
=> '?$top=25&$skip=50'
Include count inline with result
const count = true;
buildQuery({ count })
=> '?$count=true'
Or you can return only the count by passing the a filter object to count
const count = { PropName: 1 }
const query = buildQuery({ count })
=> '/$count?PropName eq 1'
fetch(`https://localhost${query}`)
Coming soon