Adding ability to specify filters when calling the repository

This commit is contained in:
kobelb 2018-06-06 07:35:28 -04:00
parent 1231c7073d
commit 9da30a15db
6 changed files with 321 additions and 28 deletions

View file

@ -212,6 +212,7 @@ export class SavedObjectsRepository {
* @property {string} [options.sortField]
* @property {string} [options.sortOrder]
* @property {Array<string>} [options.fields]
* @property {Array<Object>} [options.filters]
* @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page }
*/
async find(options = {}) {
@ -224,6 +225,7 @@ export class SavedObjectsRepository {
sortField,
sortOrder,
fields,
filters,
} = options;
if (searchFields && !Array.isArray(searchFields)) {
@ -247,7 +249,8 @@ export class SavedObjectsRepository {
searchFields,
type,
sortField,
sortOrder
sortOrder,
filters,
})
}
};

View file

@ -388,13 +388,18 @@ describe('SavedObjectsRepository', () => {
}
});
it('passes mappings, search, searchFields, type, sortField, and sortOrder to getSearchDsl', async () => {
it('passes mappings, search, searchFields, type, sortField, sortOrder, and filters to getSearchDsl', async () => {
const relevantOpts = {
search: 'foo*',
searchFields: ['foo'],
type: 'bar',
sortField: 'name',
sortOrder: 'desc',
filters: [{
terms: {
type: ['foo', 'bar']
}
}],
};
await savedObjectsRepository.find(relevantOpts);

View file

@ -67,33 +67,43 @@ function getFieldsForTypes(searchFields, types) {
* @param {Array<string>} searchFields
* @return {Object}
*/
export function getQueryParams(mappings, type, search, searchFields) {
if (!type && !search) {
return {};
}
const bool = {};
export function getQueryParams(mappings, type, search, searchFields, filters = []) {
const filter = [...filters];
const must = [];
if (type) {
bool.filter = [
{ [Array.isArray(type) ? 'terms' : 'term']: { type } }
];
filter.push({ [Array.isArray(type) ? 'terms' : 'term']: { type } });
}
if (search) {
bool.must = [
...bool.must || [],
{
simple_query_string: {
query: search,
...getFieldsForTypes(
searchFields,
getTypes(mappings, type)
)
}
must.push({
simple_query_string: {
query: search,
...getFieldsForTypes(
searchFields,
getTypes(mappings, type)
)
}
];
});
}
return { query: { bool } };
if (filter.length === 0 && must.length === 0) {
return {};
}
const result = {
query: {
bool: {}
}
};
if (filter.length > 0) {
result.query.bool.filter = filter;
}
if (must.length > 0) {
result.query.bool.must = must;
}
return result;
}

View file

@ -95,6 +95,36 @@ describe('searchDsl/queryParams', () => {
});
});
describe('{type,filters}', () => {
it('includes filters and a term filter for type when type is a string', () => {
expect(getQueryParams(MAPPINGS, 'saved', null, null, [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ term: { type: 'saved' } }
]
}
}
});
});
it('includes filters and a terms filter for type when type is an array', () => {
expect(getQueryParams(MAPPINGS, ['saved', 'vis'], null, null, [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ terms: { type: ['saved', 'vis'] } }
]
}
}
});
});
});
describe('{search}', () => {
it('includes just a sqs query', () => {
expect(getQueryParams(MAPPINGS, null, 'us*'))
@ -115,8 +145,31 @@ describe('searchDsl/queryParams', () => {
});
});
describe('{search,filters}', () => {
it('includes filters and a sqs query', () => {
expect(getQueryParams(MAPPINGS, null, 'us*', null, [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } }
],
must: [
{
simple_query_string: {
query: 'us*',
all_fields: true
}
}
]
}
}
});
});
});
describe('{type,search}', () => {
it('includes bool with sqs query and term filter for type', () => {
it('includes bool with sqs query and term filter for type when type is a string', () => {
expect(getQueryParams(MAPPINGS, 'saved', 'y*'))
.toEqual({
query: {
@ -136,7 +189,7 @@ describe('searchDsl/queryParams', () => {
}
});
});
it('includes bool with sqs query and terms filter for type', () => {
it('includes bool with sqs query and terms filter for type when type is an array', () => {
expect(getQueryParams(MAPPINGS, ['saved', 'vis'], 'y*'))
.toEqual({
query: {
@ -158,6 +211,52 @@ describe('searchDsl/queryParams', () => {
});
});
describe('{type,search,filters}', () => {
it('includes bool with sqs query, filters and term filter for type when type is a string', () => {
expect(getQueryParams(MAPPINGS, 'saved', 'y*', null, [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ term: { type: 'saved' } }
],
must: [
{
simple_query_string: {
query: 'y*',
all_fields: true
}
}
]
}
}
});
});
it('includes bool with sqs query, filters and terms filter for type when type is an array', () => {
expect(getQueryParams(MAPPINGS, ['saved', 'vis'], 'y*', null, [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ terms: { type: ['saved', 'vis'] } }
],
must: [
{
simple_query_string: {
query: 'y*',
all_fields: true
}
}
]
}
}
});
});
});
describe('{search,searchFields}', () => {
it('includes all types for field', () => {
expect(getQueryParams(MAPPINGS, null, 'y*', ['title']))
@ -223,6 +322,80 @@ describe('searchDsl/queryParams', () => {
});
});
describe('{search,searchFields,filters}', () => {
it('includes all types for field and includes filter', () => {
expect(getQueryParams(MAPPINGS, null, 'y*', ['title'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'pending.title',
'saved.title'
]
}
}
]
}
}
});
});
it('supports field boosting and includes filter', () => {
expect(getQueryParams(MAPPINGS, null, 'y*', ['title^3'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'pending.title^3',
'saved.title^3'
]
}
}
]
}
}
});
});
it('supports field and multi-field and includes filter', () => {
expect(getQueryParams(MAPPINGS, null, 'y*', ['title', 'title.raw'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'pending.title',
'saved.title',
'pending.title.raw',
'saved.title.raw',
]
}
}
]
}
}
});
});
});
describe('{type,search,searchFields}', () => {
it('includes bool, with term filter and sqs with field list', () => {
expect(getQueryParams(MAPPINGS, 'saved', 'y*', ['title']))
@ -315,4 +488,101 @@ describe('searchDsl/queryParams', () => {
});
});
});
describe('{type,search,searchFields,filters}', () => {
it('includes bool, with term filter and filter and sqs with field list', () => {
expect(getQueryParams(MAPPINGS, 'saved', 'y*', ['title'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ term: { type: 'saved' } }
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'saved.title'
]
}
}
]
}
}
});
});
it('includes bool, with terms filter and filter and sqs with field list', () => {
expect(getQueryParams(MAPPINGS, ['saved', 'vis'], 'y*', ['title'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ terms: { type: ['saved', 'vis'] } }
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'saved.title',
'vis.title'
]
}
}
]
}
}
});
});
it('supports fields pointing to multi-fields and filter', () => {
expect(getQueryParams(MAPPINGS, 'saved', 'y*', ['title.raw'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ term: { type: 'saved' } }
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'saved.title.raw'
]
}
}
]
}
}
});
});
it('supports multiple search fields and filter', () => {
expect(getQueryParams(MAPPINGS, 'saved', 'y*', ['title', 'title.raw'], [{ terms: { foo: ['bar', 'baz' ] } }]))
.toEqual({
query: {
bool: {
filter: [
{ terms: { foo: ['bar', 'baz' ] } },
{ term: { type: 'saved' } }
],
must: [
{
simple_query_string: {
query: 'y*',
fields: [
'saved.title',
'saved.title.raw'
]
}
}
]
}
}
});
});
});
});

View file

@ -28,7 +28,8 @@ export function getSearchDsl(mappings, options = {}) {
search,
searchFields,
sortField,
sortOrder
sortOrder,
filters,
} = options;
if (!type && sortField) {
@ -40,7 +41,7 @@ export function getSearchDsl(mappings, options = {}) {
}
return {
...getQueryParams(mappings, type, search, searchFields),
...getQueryParams(mappings, type, search, searchFields, filters),
...getSortingParams(mappings, type, sortField, sortOrder),
};
}

View file

@ -46,13 +46,16 @@ describe('getSearchDsl', () => {
});
describe('passes control', () => {
it('passes (mappings, type, search, searchFields) to getQueryParams', () => {
it('passes (mappings, type, search, searchFields, filters) to getQueryParams', () => {
const spy = sandbox.spy(queryParamsNS, 'getQueryParams');
const mappings = { type: { properties: {} } };
const opts = {
type: 'foo',
search: 'bar',
searchFields: ['baz'],
filters: [
{ terms: { foo: ['bar', 'baz'] } }
]
};
getSearchDsl(mappings, opts);
@ -63,6 +66,7 @@ describe('getSearchDsl', () => {
opts.type,
opts.search,
opts.searchFields,
opts.filters,
);
});