Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(query) add $sqs simple_query_string query #24

Merged
merged 1 commit into from
Jun 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,26 @@ query: {
}
```

### $sqs
[simple_query_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html). A query that uses the SimpleQueryParser to parse its context. Optional `$default_operator` which is set to `or` by default but can be set to `and` if required.

```js
query: {
$sqs: {
$fields: [
'title^5',
'description'
],
$query: '+like +javascript',
$default_operator: 'and'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if we could change $default_operator to simply $operator. I try to keep the parameters as short as possible, as the queries tend to grow quite long quite quickly.

}
}
```
This can also be expressed in an URL as the following:
```http
http://localhost:3030/users?$sqs[$fields][]=title^5&$sqs[$fields][]=description&$sqs[$query]=+like +javascript&$sqs[$default_operator]=and
```

## Parent-child relationship
Elasticsearch supports [parent-child relationship](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-parent-field.html), however it is not exactly the same as in relational databases. feathers-elasticsearch supports all CRUD operations for Elasticsearch types with parent mapping, and does that with the Elasticsearch constrains. Therefore:

Expand Down
26 changes: 26 additions & 0 deletions src/utils/parse-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const specialQueryHandlers = {
$or: $or,
$and: $and,
$all: $all,
$sqs: $sqs,
$child: (...args) => $childOr$parent('$child', ...args),
$parent: (...args) => $childOr$parent('$parent', ...args)
};
Expand Down Expand Up @@ -66,6 +67,31 @@ function $and (value, esQuery, idProp) {
return esQuery;
}

function $sqs (value, esQuery, idProp) {
if (value === null || value === undefined) {
return esQuery;
}

validateType(value, '$sqs', 'object');
validateType(value.$fields, `value.$fields`, 'array');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second parameter should be simply $sqs.$fields

validateType(value.$query, `value.$query`, 'string');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second parameter should be '$sqs.$query'.


if (value.$default_operator) {
validateType(value.$default_operator, `value.$default_operator`, 'string');
}

esQuery.must = esQuery.must || [];
esQuery.must.push({
simple_query_string: {
fields: value.$fields,
query: value.$query,
default_operator: value.$default_operator || 'or'
}
});

return esQuery;
}

function $childOr$parent (key, value, esQuery) {
let subQuery;
let queryName = key === '$child' ? 'has_child' : 'has_parent';
Expand Down
21 changes: 21 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,27 @@ describe('Elasticsearch Service', () => {
});
});

it('can $sqs (simple_query_string)', () => {
return app.service(serviceName)
.find({
query: {
$sort: { name: 1 },
$sqs: {
$fields: [
'bio',
'name^5'
],
$query: '+like -javascript',
$default_operator: 'and'
}
}
})
.then(results => {
expect(results.length).to.equal(1);
expect(results[0].name).to.equal('Moody');
});
});

it('can $child', () => {
return app.service(serviceName)
.find({
Expand Down
36 changes: 36 additions & 0 deletions test/utils/parse-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ export default function parseQueryTests () {
expect(() => parseQuery({ $and: {} }, '_id')).to.throw(errors.BadRequest);
});

it('should throw BadRequest if $sqs is not an object', () => {
expect(() => parseQuery({ $sqs: 12 }, '_id')).to.throw(errors.BadRequest);
expect(() => parseQuery({ $sqs: true }, '_id')).to.throw(errors.BadRequest);
expect(() => parseQuery({ $sqs: 'abc' }, '_id')).to.throw(errors.BadRequest);
expect(() => parseQuery({ $sqs: {} }, '_id')).to.throw(errors.BadRequest);
});

it('should throw BadRequest if $child is not an object, null or undefined', () => {
expect(() => parseQuery({ $child: 12 })).to.throw(errors.BadRequest);
expect(() => parseQuery({ $child: true })).to.throw(errors.BadRequest);
Expand Down Expand Up @@ -257,6 +264,35 @@ export default function parseQueryTests () {
.deep.equal(expectedResult);
});

it('should return "must" $sqs', () => {
let query = {
$sqs: {
$fields: [
'description',
'title^5'
],
$query: '-(track another)'
}
};
let expectedResult = {
must: [
{
simple_query_string: {
fields: [
'description',
'title^5'
],
query: '-(track another)',
default_operator: 'or'
}
}
]
};

expect(parseQuery(query, '_id')).to
.deep.equal(expectedResult);
});

it('should return "prefix" query for $prefix', () => {
let query = {
user: { $prefix: 'ada' }
Expand Down