fix: add support for descending sorting of full text search (#7496)
This commit is contained in:
@@ -152,6 +152,7 @@ ___
|
|||||||
- Refactor: uniform issue templates across repos (Manuel Trezza) [#7528](https://github.com/parse-community/parse-server/pull/7528)
|
- Refactor: uniform issue templates across repos (Manuel Trezza) [#7528](https://github.com/parse-community/parse-server/pull/7528)
|
||||||
- ci: bump ci environment (Manuel Trezza) [#7539](https://github.com/parse-community/parse-server/pull/7539)
|
- ci: bump ci environment (Manuel Trezza) [#7539](https://github.com/parse-community/parse-server/pull/7539)
|
||||||
- CI now pushes docker images to Docker Hub (Corey Baker) [#7548](https://github.com/parse-community/parse-server/pull/7548)
|
- CI now pushes docker images to Docker Hub (Corey Baker) [#7548](https://github.com/parse-community/parse-server/pull/7548)
|
||||||
|
- Allow setting descending sort to full text queries (dblythy) [#7496](https://github.com/parse-community/parse-server/pull/7496)
|
||||||
- Allow cloud string for ES modules (Daniel Blyth) [#7560](https://github.com/parse-community/parse-server/pull/7560)
|
- Allow cloud string for ES modules (Daniel Blyth) [#7560](https://github.com/parse-community/parse-server/pull/7560)
|
||||||
- docs: Introduce deprecation ID for reference in comments and online search (Manuel Trezza) [#7562](https://github.com/parse-community/parse-server/pull/7562)
|
- docs: Introduce deprecation ID for reference in comments and online search (Manuel Trezza) [#7562](https://github.com/parse-community/parse-server/pull/7562)
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ const Parse = require('parse/node');
|
|||||||
const request = require('../lib/request');
|
const request = require('../lib/request');
|
||||||
let databaseAdapter;
|
let databaseAdapter;
|
||||||
|
|
||||||
const fullTextHelper = () => {
|
const fullTextHelper = async () => {
|
||||||
const config = Config.get('test');
|
const config = Config.get('test');
|
||||||
databaseAdapter = config.database.adapter;
|
databaseAdapter = config.database.adapter;
|
||||||
|
|
||||||
const subjects = [
|
const subjects = [
|
||||||
'coffee',
|
'coffee',
|
||||||
'Coffee Shopping',
|
'Coffee Shopping',
|
||||||
@@ -19,170 +18,75 @@ const fullTextHelper = () => {
|
|||||||
'coffee and cream',
|
'coffee and cream',
|
||||||
'Cafe con Leche',
|
'Cafe con Leche',
|
||||||
];
|
];
|
||||||
const requests = [];
|
await reconfigureServer({
|
||||||
for (const i in subjects) {
|
|
||||||
const request = {
|
|
||||||
method: 'POST',
|
|
||||||
body: {
|
|
||||||
subject: subjects[i],
|
|
||||||
comment: subjects[i],
|
|
||||||
},
|
|
||||||
path: '/1/classes/TestObject',
|
|
||||||
};
|
|
||||||
requests.push(request);
|
|
||||||
}
|
|
||||||
return reconfigureServer({
|
|
||||||
appId: 'test',
|
appId: 'test',
|
||||||
restAPIKey: 'test',
|
restAPIKey: 'test',
|
||||||
publicServerURL: 'http://localhost:8378/1',
|
publicServerURL: 'http://localhost:8378/1',
|
||||||
databaseAdapter,
|
databaseAdapter,
|
||||||
}).then(() => {
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/batch',
|
|
||||||
body: {
|
|
||||||
requests,
|
|
||||||
},
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
await Parse.Object.saveAll(
|
||||||
|
subjects.map(subject => new Parse.Object('TestObject').set({ subject, comment: subject }))
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Parse.Query Full Text Search testing', () => {
|
describe('Parse.Query Full Text Search testing', () => {
|
||||||
it('fullTextSearch: $search', done => {
|
it('fullTextSearch: $search', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'coffee');
|
||||||
subject: {
|
const results = await query.find();
|
||||||
$text: {
|
expect(results.length).toBe(3);
|
||||||
$search: {
|
|
||||||
$term: 'coffee',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
resp => {
|
|
||||||
expect(resp.data.results.length).toBe(3);
|
|
||||||
done();
|
|
||||||
},
|
|
||||||
e => done.fail(e)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $search, sort', done => {
|
it('fullTextSearch: $search, sort', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'coffee');
|
||||||
subject: {
|
query.select('$score');
|
||||||
$text: {
|
query.ascending('$score');
|
||||||
$search: {
|
const results = await query.find();
|
||||||
$term: 'coffee',
|
expect(results.length).toBe(3);
|
||||||
},
|
expect(results[0].get('score'));
|
||||||
},
|
expect(results[1].get('score'));
|
||||||
},
|
expect(results[2].get('score'));
|
||||||
};
|
|
||||||
const order = '$score';
|
|
||||||
const keys = '$score';
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, order, keys, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
const resp = response.data;
|
|
||||||
expect(resp.results.length).toBe(3);
|
|
||||||
expect(resp.results[0].score);
|
|
||||||
expect(resp.results[1].score);
|
|
||||||
expect(resp.results[2].score);
|
|
||||||
done();
|
|
||||||
}, done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $language', done => {
|
it('fulltext descending by $score', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'coffee');
|
||||||
subject: {
|
query.descending('$score');
|
||||||
$text: {
|
query.select('$score');
|
||||||
$search: {
|
const [first, second, third] = await query.find();
|
||||||
$term: 'leche',
|
expect(first).toBeDefined();
|
||||||
$language: 'spanish',
|
expect(second).toBeDefined();
|
||||||
},
|
expect(third).toBeDefined();
|
||||||
},
|
expect(first.get('score'));
|
||||||
},
|
expect(second.get('score'));
|
||||||
};
|
expect(third.get('score'));
|
||||||
return request({
|
expect(first.get('score') >= second.get('score')).toBeTrue();
|
||||||
method: 'POST',
|
expect(second.get('score') >= third.get('score')).toBeTrue();
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.data.results.length).toBe(2);
|
|
||||||
done();
|
|
||||||
}, done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $diacriticSensitive', done => {
|
it('fullTextSearch: $language', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'leche', { language: 'spanish' });
|
||||||
subject: {
|
const resp = await query.find();
|
||||||
$text: {
|
expect(resp.length).toBe(2);
|
||||||
$search: {
|
|
||||||
$term: 'CAFÉ',
|
|
||||||
$diacriticSensitive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.data.results.length).toBe(1);
|
|
||||||
done();
|
|
||||||
}, done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $search, invalid input', done => {
|
it('fullTextSearch: $diacriticSensitive', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
|
query.fullText('subject', 'CAFÉ', { diacriticSensitive: true });
|
||||||
|
const resp = await query.find();
|
||||||
|
expect(resp.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fullTextSearch: $search, invalid input', async () => {
|
||||||
|
await fullTextHelper();
|
||||||
|
const invalidQuery = async () => {
|
||||||
const where = {
|
const where = {
|
||||||
subject: {
|
subject: {
|
||||||
$text: {
|
$text: {
|
||||||
@@ -190,7 +94,8 @@ describe('Parse.Query Full Text Search testing', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return request({
|
try {
|
||||||
|
await request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
url: 'http://localhost:8378/1/classes/TestObject',
|
||||||
body: { where, _method: 'GET' },
|
body: { where, _method: 'GET' },
|
||||||
@@ -200,185 +105,73 @@ describe('Parse.Query Full Text Search testing', () => {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
} catch (e) {
|
||||||
.then(resp => {
|
throw new Parse.Error(e.data.code, e.data.error);
|
||||||
fail(`no request should succeed: ${JSON.stringify(resp)}`);
|
}
|
||||||
done();
|
};
|
||||||
})
|
await expectAsync(invalidQuery()).toBeRejectedWith(
|
||||||
.catch(err => {
|
new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $search, should be object')
|
||||||
expect(err.data.code).toEqual(Parse.Error.INVALID_JSON);
|
);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $language, invalid input', done => {
|
it('fullTextSearch: $language, invalid input', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'leche', { language: true });
|
||||||
subject: {
|
await expectAsync(query.find()).toBeRejectedWith(
|
||||||
$text: {
|
new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $language, should be string')
|
||||||
$search: {
|
);
|
||||||
$term: 'leche',
|
|
||||||
$language: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
fail(`no request should succeed: ${JSON.stringify(resp)}`);
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
expect(err.data.code).toEqual(Parse.Error.INVALID_JSON);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $caseSensitive, invalid input', done => {
|
it('fullTextSearch: $caseSensitive, invalid input', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'leche', { caseSensitive: 'string' });
|
||||||
subject: {
|
await expectAsync(query.find()).toBeRejectedWith(
|
||||||
$text: {
|
new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $caseSensitive, should be boolean')
|
||||||
$search: {
|
);
|
||||||
$term: 'Coffee',
|
|
||||||
$caseSensitive: 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
fail(`no request should succeed: ${JSON.stringify(resp)}`);
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
expect(err.data.code).toEqual(Parse.Error.INVALID_JSON);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $diacriticSensitive, invalid input', done => {
|
it('fullTextSearch: $diacriticSensitive, invalid input', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'leche', { diacriticSensitive: 'string' });
|
||||||
subject: {
|
await expectAsync(query.find()).toBeRejectedWith(
|
||||||
$text: {
|
new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $diacriticSensitive, should be boolean')
|
||||||
$search: {
|
);
|
||||||
$term: 'CAFÉ',
|
|
||||||
$diacriticSensitive: 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
fail(`no request should succeed: ${JSON.stringify(resp)}`);
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
expect(err.data.code).toEqual(Parse.Error.INVALID_JSON);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe_only_db('mongo')('[mongodb] Parse.Query Full Text Search testing', () => {
|
describe_only_db('mongo')('[mongodb] Parse.Query Full Text Search testing', () => {
|
||||||
it('fullTextSearch: does not create text index if compound index exist', done => {
|
it('fullTextSearch: does not create text index if compound index exist', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
await databaseAdapter.dropAllIndexes('TestObject');
|
||||||
return databaseAdapter.dropAllIndexes('TestObject');
|
let indexes = await databaseAdapter.getIndexes('TestObject');
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
return databaseAdapter.getIndexes('TestObject');
|
|
||||||
})
|
|
||||||
.then(indexes => {
|
|
||||||
expect(indexes.length).toEqual(1);
|
expect(indexes.length).toEqual(1);
|
||||||
return databaseAdapter.createIndex('TestObject', {
|
await databaseAdapter.createIndex('TestObject', {
|
||||||
subject: 'text',
|
subject: 'text',
|
||||||
comment: 'text',
|
comment: 'text',
|
||||||
});
|
});
|
||||||
})
|
indexes = await databaseAdapter.getIndexes('TestObject');
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
return databaseAdapter.getIndexes('TestObject');
|
query.fullText('subject', 'coffee');
|
||||||
})
|
query.select('$score');
|
||||||
.then(indexes => {
|
query.ascending('$score');
|
||||||
|
const results = await query.find();
|
||||||
|
expect(results.length).toBe(3);
|
||||||
|
expect(results[0].get('score'));
|
||||||
|
expect(results[1].get('score'));
|
||||||
|
expect(results[2].get('score'));
|
||||||
|
|
||||||
|
indexes = await databaseAdapter.getIndexes('TestObject');
|
||||||
expect(indexes.length).toEqual(2);
|
expect(indexes.length).toEqual(2);
|
||||||
const where = {
|
|
||||||
subject: {
|
const schemas = await new Parse.Schema('TestObject').get();
|
||||||
$text: {
|
expect(schemas.indexes._id_).toBeDefined();
|
||||||
$search: {
|
expect(schemas.indexes._id_._id).toEqual(1);
|
||||||
$term: 'coffee',
|
expect(schemas.indexes.subject_text_comment_text).toBeDefined();
|
||||||
},
|
expect(schemas.indexes.subject_text_comment_text.subject).toEqual('text');
|
||||||
},
|
expect(schemas.indexes.subject_text_comment_text.comment).toEqual('text');
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.data.results.length).toEqual(3);
|
|
||||||
return databaseAdapter.getIndexes('TestObject');
|
|
||||||
})
|
|
||||||
.then(indexes => {
|
|
||||||
expect(indexes.length).toEqual(2);
|
|
||||||
request({
|
|
||||||
url: 'http://localhost:8378/1/schemas/TestObject',
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-Master-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
}).then(response => {
|
|
||||||
const body = response.data;
|
|
||||||
expect(body.indexes._id_).toBeDefined();
|
|
||||||
expect(body.indexes._id_._id).toEqual(1);
|
|
||||||
expect(body.indexes.subject_text_comment_text).toBeDefined();
|
|
||||||
expect(body.indexes.subject_text_comment_text.subject).toEqual('text');
|
|
||||||
expect(body.indexes.subject_text_comment_text.comment).toEqual('text');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: does not create text index if schema compound index exist', done => {
|
it('fullTextSearch: does not create text index if schema compound index exist', done => {
|
||||||
@@ -458,64 +251,20 @@ describe_only_db('mongo')('[mongodb] Parse.Query Full Text Search testing', () =
|
|||||||
.catch(done.fail);
|
.catch(done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $diacriticSensitive - false', done => {
|
it('fullTextSearch: $diacriticSensitive - false', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'CAFÉ', { diacriticSensitive: false });
|
||||||
subject: {
|
const resp = await query.find();
|
||||||
$text: {
|
expect(resp.length).toBe(2);
|
||||||
$search: {
|
|
||||||
$term: 'CAFÉ',
|
|
||||||
$diacriticSensitive: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.data.results.length).toBe(2);
|
|
||||||
done();
|
|
||||||
}, done.fail);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fullTextSearch: $caseSensitive', done => {
|
it('fullTextSearch: $caseSensitive', async () => {
|
||||||
fullTextHelper()
|
await fullTextHelper();
|
||||||
.then(() => {
|
const query = new Parse.Query('TestObject');
|
||||||
const where = {
|
query.fullText('subject', 'Coffee', { caseSensitive: true });
|
||||||
subject: {
|
const results = await query.find();
|
||||||
$text: {
|
expect(results.length).toBe(1);
|
||||||
$search: {
|
|
||||||
$term: 'Coffee',
|
|
||||||
$caseSensitive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return request({
|
|
||||||
method: 'POST',
|
|
||||||
url: 'http://localhost:8378/1/classes/TestObject',
|
|
||||||
body: { where, _method: 'GET' },
|
|
||||||
headers: {
|
|
||||||
'X-Parse-Application-Id': 'test',
|
|
||||||
'X-Parse-REST-API-Key': 'test',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(resp => {
|
|
||||||
expect(resp.data.results.length).toBe(1);
|
|
||||||
done();
|
|
||||||
}, done.fail);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ function RestQuery(
|
|||||||
var fields = restOptions.order.split(',');
|
var fields = restOptions.order.split(',');
|
||||||
this.findOptions.sort = fields.reduce((sortMap, field) => {
|
this.findOptions.sort = fields.reduce((sortMap, field) => {
|
||||||
field = field.trim();
|
field = field.trim();
|
||||||
if (field === '$score') {
|
if (field === '$score' || field === '-$score') {
|
||||||
sortMap.score = { $meta: 'textScore' };
|
sortMap.score = { $meta: 'textScore' };
|
||||||
} else if (field[0] == '-') {
|
} else if (field[0] == '-') {
|
||||||
sortMap[field.slice(1)] = -1;
|
sortMap[field.slice(1)] = -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user