0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Dynamic Routing Beta: Filter collections with NQL (#9704)

refs #9601

- replace jsonpath with [NQL](https://github.com/NexesJS/NQL)
- jsonpath was just a temporary solution (a short-term fix)
- with NQL we are able to filter collections more powerful in the near future
- NQL is not feature complete
- we still support `featured:true` for collections
This commit is contained in:
Katharina Irrgang 2018-06-26 01:54:51 +02:00 committed by GitHub
parent fc9da07025
commit 7027980ad2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 30 deletions

View file

@ -1,21 +1,7 @@
const _ = require('lodash'),
jsonpath = require('jsonpath'),
nql = require('@nexes/nql'),
debug = require('ghost-ignition').debug('services:url:generator'),
localUtils = require('./utils'),
/**
* @TODO: This is a fake version of the upcoming GQL tool.
* GQL will offer a tool to match a JSON against a filter.
*/
transformFilter = (filter) => {
filter = '$[?(' + filter + ')]';
filter = filter.replace(/(\w+):(\w+)/g, '@.$1 == "$2"');
filter = filter.replace(/"true"/g, 'true');
filter = filter.replace(/"false"/g, 'false');
filter = filter.replace(/"0"/g, '0');
filter = filter.replace(/"1"/g, '1');
filter = filter.replace(/\+/g, ' && ');
return filter;
};
localUtils = require('./utils');
class UrlGenerator {
constructor(router, queue, resources, urls, position) {
@ -29,7 +15,8 @@ class UrlGenerator {
// CASE: routers can define custom filters, but not required.
if (this.router.getFilter()) {
this.filter = transformFilter(this.router.getFilter());
this.filter = this.router.getFilter();
this.nql = nql(this.filter);
debug('filter', this.filter);
}
@ -117,7 +104,7 @@ class UrlGenerator {
resource.reserve();
this._resourceListeners(resource);
return true;
} else if (jsonpath.query(resource, this.filter).length) {
} else if (this.nql.queryJSON(resource.data)) {
this.urls.add({
url: url,
generatorId: this.uid,

View file

@ -1,7 +1,7 @@
const _ = require('lodash');
const Promise = require('bluebird');
const should = require('should');
const jsonpath = require('jsonpath');
const nql = require('@nexes/nql');
const sinon = require('sinon');
const urlUtils = require('../../../../server/services/url/utils');
const UrlGenerator = require('../../../../server/services/url/UrlGenerator');
@ -67,7 +67,7 @@ describe('Unit: services/url/UrlGenerator', function () {
it('routing type has filter', function () {
router.getFilter.returns('featured:true');
const urlGenerator = new UrlGenerator(router, queue);
urlGenerator.filter.should.eql('$[?(@.featured == true)]');
urlGenerator.filter.should.eql('featured:true');
});
it('routing type has changed', function () {
@ -153,9 +153,10 @@ describe('Unit: services/url/UrlGenerator', function () {
router.getFilter.returns(false);
router.getResourceType.returns('posts');
resource.isReserved.returns(false);
sandbox.stub(jsonpath, 'query');
const urlGenerator = new UrlGenerator(router, queue, resources, urls);
should.not.exist(urlGenerator.nql);
sandbox.stub(urlGenerator, '_generateUrl').returns('something');
sandbox.stub(urlGenerator, '_resourceListeners');
@ -165,16 +166,16 @@ describe('Unit: services/url/UrlGenerator', function () {
urlGenerator._resourceListeners.calledOnce.should.be.true();
urls.add.calledOnce.should.be.true();
resource.reserve.calledOnce.should.be.true();
jsonpath.query.called.should.be.false();
});
it('resource is taken', function () {
router.getFilter.returns(false);
router.getResourceType.returns('posts');
resource.isReserved.returns(true);
sandbox.stub(jsonpath, 'query');
const urlGenerator = new UrlGenerator(router, queue, resources, urls);
should.not.exist(urlGenerator.nql);
sandbox.stub(urlGenerator, '_generateUrl').returns('something');
sandbox.stub(urlGenerator, '_resourceListeners');
@ -184,7 +185,6 @@ describe('Unit: services/url/UrlGenerator', function () {
urlGenerator._resourceListeners.called.should.be.false();
urls.add.called.should.be.false();
resource.reserve.called.should.be.false();
jsonpath.query.called.should.be.false();
});
});
@ -193,9 +193,10 @@ describe('Unit: services/url/UrlGenerator', function () {
router.getFilter.returns('featured:true');
router.getResourceType.returns('posts');
resource.isReserved.returns(false);
sandbox.stub(jsonpath, 'query').returns([true]);
const urlGenerator = new UrlGenerator(router, queue, resources, urls);
sandbox.stub(urlGenerator.nql, 'queryJSON').returns(true);
sandbox.stub(urlGenerator, '_generateUrl').returns('something');
sandbox.stub(urlGenerator, '_resourceListeners');
@ -205,16 +206,17 @@ describe('Unit: services/url/UrlGenerator', function () {
urlGenerator._resourceListeners.calledOnce.should.be.true();
urls.add.calledOnce.should.be.true();
resource.reserve.calledOnce.should.be.true();
jsonpath.query.calledOnce.should.be.true();
urlGenerator.nql.queryJSON.called.should.be.true();
});
it('no match', function () {
router.getFilter.returns('featured:true');
router.getResourceType.returns('posts');
resource.isReserved.returns(false);
sandbox.stub(jsonpath, 'query').returns([]);
const urlGenerator = new UrlGenerator(router, queue, resources, urls);
sandbox.stub(urlGenerator.nql, 'queryJSON').returns(false);
sandbox.stub(urlGenerator, '_generateUrl').returns('something');
sandbox.stub(urlGenerator, '_resourceListeners');
@ -224,16 +226,17 @@ describe('Unit: services/url/UrlGenerator', function () {
urlGenerator._resourceListeners.called.should.be.false();
urls.add.called.should.be.false();
resource.reserve.called.should.be.false();
jsonpath.query.calledOnce.should.be.true();
urlGenerator.nql.queryJSON.called.should.be.true();
});
it('resource is taken', function () {
router.getFilter.returns('featured:true');
router.getResourceType.returns('posts');
resource.isReserved.returns(true);
sandbox.stub(jsonpath, 'query').returns([]);
const urlGenerator = new UrlGenerator(router, queue, resources, urls);
sandbox.stub(urlGenerator.nql, 'queryJSON').returns(true);
sandbox.stub(urlGenerator, '_generateUrl').returns('something');
sandbox.stub(urlGenerator, '_resourceListeners');
@ -243,7 +246,7 @@ describe('Unit: services/url/UrlGenerator', function () {
urlGenerator._resourceListeners.called.should.be.false();
urls.add.called.should.be.false();
resource.reserve.called.should.be.false();
jsonpath.query.called.should.be.false();
urlGenerator.nql.queryJSON.called.should.be.false();
});
});
});

View file

@ -29,6 +29,7 @@
"cli": "^1.7.0"
},
"dependencies": {
"@nexes/nql": "0.0.1",
"amperize": "0.3.7",
"analytics-node": "2.4.1",
"archiver": "1.3.0",

View file

@ -2,6 +2,24 @@
# yarn lockfile v1
"@nexes/mongo-knex@0.0.0":
version "0.0.0"
resolved "https://registry.yarnpkg.com/@nexes/mongo-knex/-/mongo-knex-0.0.0.tgz#7a44a7263d8830c8416b90ba3c963c2c722e7b72"
dependencies:
lodash "^4.17.10"
"@nexes/nql-lang@0.0.0":
version "0.0.0"
resolved "https://registry.yarnpkg.com/@nexes/nql-lang/-/nql-lang-0.0.0.tgz#eb0fb807aea8aa64d3d0b454f3d1167af394f39a"
"@nexes/nql@0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@nexes/nql/-/nql-0.0.1.tgz#e8f5e5352badeffd67e371f22bccd41fa0c20c24"
dependencies:
"@nexes/mongo-knex" "0.0.0"
"@nexes/nql-lang" "0.0.0"
mingo "2.2.2"
"@segment/loosely-validate-event@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-1.1.2.tgz#d77840999e3f7e43e74b3b0d43391c1526f793b8"
@ -3762,6 +3780,10 @@ mimic-response@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e"
mingo@2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/mingo/-/mingo-2.2.2.tgz#be69d486ae6e0ac54b979dc5f4412db21851f693"
minimatch@0.3:
version "0.3.0"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd"