Skip to content

Commit 7963861

Browse files
vinz51SebC99
authored andcommitted
Add the new fullTextSearch method with the associated tests.
1 parent f713a2c commit 7963861

File tree

2 files changed

+158
-53
lines changed

2 files changed

+158
-53
lines changed

src/ParseQuery.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,37 @@ export default class ParseQuery {
10321032
return this._addCondition(key, '$geoIntersects', { '$point': point });
10331033
}
10341034

1035+
/**
1036+
* Method to find by full text.
1037+
* The key and the search fields are required the others are optionals.
1038+
* @method fullTextSearch
1039+
* @param {String} key The key to structure the where query
1040+
* @param {String} search The string to search
1041+
* @param {String} language Determine the list of stop words
1042+
* @param {Boolean} caseSensitive Dis/en-able the case sensitive search
1043+
* @param {Boolean} diacriticSensitive Dis/en-able diacritic sensitive search
1044+
* @return {Parse.Query} Returns the query, so you can chain this call.
1045+
*/
1046+
fullTextSearch(key: string, search: string, language: string, caseSensitive: boolean, diacriticSensitive: boolean): ParseQuery {
1047+
if (typeof key === 'undefined' || !key) {
1048+
throw new Error('A key is required.');
1049+
}
1050+
if (typeof search === 'undefined' || !search) {
1051+
throw new Error('You have to add one string to search.');
1052+
}
1053+
var options = { '$term': search };
1054+
if (typeof language !== "undefined" || language !== null) {
1055+
options['$language'] = language;
1056+
}
1057+
if (typeof caseSensitive !== "undefined" || caseSensitive !== null) {
1058+
options['$caseSensitive'] = caseSensitive;
1059+
}
1060+
if (typeof diacriticSensitive !== "undefined" || diacriticSensitive !== null) {
1061+
options['$diacriticSensitive'] = diacriticSensitive;
1062+
}
1063+
return this._addCondition(key, '$text', { '$search': options });
1064+
}
1065+
10351066
/** Query Orderings **/
10361067

10371068
/**
@@ -1110,6 +1141,17 @@ export default class ParseQuery {
11101141
return this;
11111142
}
11121143

1144+
/**
1145+
* Method to sort the full text search by text score
1146+
* @method sortByTextScore
1147+
* @return {Parse.Query} Returns the query, so you can chain this call.
1148+
*/
1149+
sortByTextScore() {
1150+
this.ascending('$score');
1151+
this.select(['$score']);
1152+
return this;
1153+
}
1154+
11131155
/** Query Options **/
11141156

11151157
/**

src/__tests__/ParseQuery-test.js

Lines changed: 116 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ describe('ParseQuery', () => {
13381338
});
13391339

13401340

1341-
1341+
13421342
it('overrides cached object with query results', (done) => {
13431343
jest.dontMock("../ParseObject");
13441344
jest.resetModules();
@@ -1347,12 +1347,12 @@ describe('ParseQuery', () => {
13471347
ParseQuery = require('../ParseQuery').default;
13481348

13491349
ParseObject.enableSingleInstance();
1350-
1351-
var objectToReturn = {
1352-
objectId: 'T01',
1353-
name: 'Name',
1354-
other: 'other',
1355-
className:"Thing",
1350+
1351+
var objectToReturn = {
1352+
objectId: 'T01',
1353+
name: 'Name',
1354+
other: 'other',
1355+
className:"Thing",
13561356
createdAt: '2017-01-10T10:00:00Z'
13571357
};
13581358

@@ -1368,10 +1368,10 @@ describe('ParseQuery', () => {
13681368
var testObject;
13691369
q.find().then((results) => {
13701370
testObject = results[0];
1371-
1371+
13721372
expect(testObject.get("name")).toBe("Name");
13731373
expect(testObject.get("other")).toBe("other");
1374-
1374+
13751375
objectToReturn = { objectId: 'T01', name: 'Name2'};
13761376
var q2 = new ParseQuery("Thing");
13771377
return q2.find();
@@ -1393,13 +1393,13 @@ describe('ParseQuery', () => {
13931393
ParseQuery = require('../ParseQuery').default;
13941394

13951395
ParseObject.enableSingleInstance();
1396-
1397-
var objectToReturn = {
1398-
objectId: 'T01',
1399-
name: 'Name',
1400-
other: 'other',
1401-
tbd: 'exists',
1402-
className:"Thing",
1396+
1397+
var objectToReturn = {
1398+
objectId: 'T01',
1399+
name: 'Name',
1400+
other: 'other',
1401+
tbd: 'exists',
1402+
className:"Thing",
14031403
createdAt: '2017-01-10T10:00:00Z',
14041404
subObject: {key1:"value", key2:"value2", key3:"thisWillGoAway"}
14051405
};
@@ -1416,14 +1416,14 @@ describe('ParseQuery', () => {
14161416
var testObject;
14171417
return q.find().then((results) => {
14181418
testObject = results[0];
1419-
1419+
14201420
expect(testObject.get("name")).toBe("Name");
14211421
expect(testObject.get("other")).toBe("other");
14221422
expect(testObject.has("tbd")).toBe(true);
14231423
expect(testObject.get("subObject").key1).toBe("value");
14241424
expect(testObject.get("subObject").key2).toBe("value2");
14251425
expect(testObject.get("subObject").key3).toBe("thisWillGoAway");
1426-
1426+
14271427
var q2 = new ParseQuery("Thing");
14281428
q2.select("other", "tbd", "subObject.key1", "subObject.key3");
14291429
objectToReturn = { objectId: 'T01', other: 'other2', subObject:{key1:"updatedValue"}};
@@ -1442,7 +1442,7 @@ describe('ParseQuery', () => {
14421442
expect(testObject.has("tbd")).toBe(false);
14431443
expect(testObject.get("subObject").key1).toBe("updatedValue");
14441444
expect(testObject.get("subObject").key2).toBe("value2");
1445-
expect(testObject.get("subObject").key3).toBeUndefined();
1445+
expect(testObject.get("subObject").key3).toBeUndefined();
14461446
done();
14471447
}, (error) => {
14481448
done.fail(error);
@@ -1457,12 +1457,12 @@ describe('ParseQuery', () => {
14571457
ParseQuery = require('../ParseQuery').default;
14581458

14591459
ParseObject.enableSingleInstance();
1460-
1461-
var objectToReturn = {
1462-
objectId: 'T01',
1463-
name: 'Name',
1464-
other: 'other',
1465-
className:"Thing",
1460+
1461+
var objectToReturn = {
1462+
objectId: 'T01',
1463+
name: 'Name',
1464+
other: 'other',
1465+
className:"Thing",
14661466
createdAt: '2017-01-10T10:00:00Z'
14671467
};
14681468

@@ -1478,10 +1478,10 @@ describe('ParseQuery', () => {
14781478
var testObject;
14791479
q.first().then((result) => {
14801480
testObject = result;
1481-
1481+
14821482
expect(testObject.get("name")).toBe("Name");
14831483
expect(testObject.get("other")).toBe("other");
1484-
1484+
14851485
objectToReturn = { objectId: 'T01', name: 'Name2'};
14861486
var q2 = new ParseQuery("Thing");
14871487
return q2.first();
@@ -1503,13 +1503,13 @@ describe('ParseQuery', () => {
15031503
ParseQuery = require('../ParseQuery').default;
15041504

15051505
ParseObject.enableSingleInstance();
1506-
1507-
var objectToReturn = {
1508-
objectId: 'T01',
1509-
name: 'Name',
1510-
other: 'other',
1511-
tbd: 'exists',
1512-
className:"Thing",
1506+
1507+
var objectToReturn = {
1508+
objectId: 'T01',
1509+
name: 'Name',
1510+
other: 'other',
1511+
tbd: 'exists',
1512+
className:"Thing",
15131513
subObject: {key1:"value", key2:"value2", key3:"thisWillGoAway"},
15141514
createdAt: '2017-01-10T10:00:00Z',
15151515
};
@@ -1526,11 +1526,11 @@ describe('ParseQuery', () => {
15261526
var testObject;
15271527
return q.first().then((result) => {
15281528
testObject = result;
1529-
1529+
15301530
expect(testObject.get("name")).toBe("Name");
15311531
expect(testObject.get("other")).toBe("other");
15321532
expect(testObject.has("tbd")).toBe(true);
1533-
1533+
15341534
var q2 = new ParseQuery("Thing");
15351535
q2.select("other", "tbd", "subObject.key1", "subObject.key3");
15361536
objectToReturn = { objectId: 'T01', other: 'other2', subObject:{key1:"updatedValue"}};
@@ -1546,10 +1546,10 @@ describe('ParseQuery', () => {
15461546
}).then(() => {
15471547
expect(testObject.get("name")).toBe("Name");
15481548
expect(testObject.get("other")).toBe("other2");
1549-
expect(testObject.has("tbd")).toBe(false);
1549+
expect(testObject.has("tbd")).toBe(false);
15501550
expect(testObject.get("subObject").key1).toBe("updatedValue");
15511551
expect(testObject.get("subObject").key2).toBe("value2");
1552-
expect(testObject.get("subObject").key3).toBeUndefined();
1552+
expect(testObject.get("subObject").key3).toBeUndefined();
15531553
done();
15541554
}, (error) => {
15551555
done.fail(error);
@@ -1593,12 +1593,12 @@ describe('ParseQuery', () => {
15931593
ParseQuery = require('../ParseQuery').default;
15941594

15951595
ParseObject.enableSingleInstance();
1596-
1597-
var objectToReturn = {
1598-
objectId: 'T01',
1599-
name: 'Name',
1600-
tbd: 'exists',
1601-
className:"Thing",
1596+
1597+
var objectToReturn = {
1598+
objectId: 'T01',
1599+
name: 'Name',
1600+
tbd: 'exists',
1601+
className:"Thing",
16021602
createdAt: '2017-01-10T10:00:00Z'
16031603
};
16041604

@@ -1615,7 +1615,7 @@ describe('ParseQuery', () => {
16151615
var testObject;
16161616
return q.find().then((results) => {
16171617
testObject = results[0];
1618-
1618+
16191619
expect(testObject.get("name")).toBe("Name");
16201620
expect(testObject.has("other")).toBe(false);
16211621
expect(testObject.has("subObject")).toBe(false);
@@ -1635,12 +1635,12 @@ describe('ParseQuery', () => {
16351635
ParseQuery = require('../ParseQuery').default;
16361636

16371637
ParseObject.enableSingleInstance();
1638-
1639-
var objectToReturn = {
1640-
objectId: 'T01',
1641-
name: 'Name',
1642-
tbd: 'exists',
1643-
className:"Thing",
1638+
1639+
var objectToReturn = {
1640+
objectId: 'T01',
1641+
name: 'Name',
1642+
tbd: 'exists',
1643+
className:"Thing",
16441644
subObject1: {foo:"bar"},
16451645
subObject2: {foo:"bar"},
16461646
subObject3: {foo:"bar"},
@@ -1660,7 +1660,7 @@ describe('ParseQuery', () => {
16601660
var testObject;
16611661
return q.find().then((results) => {
16621662
testObject = results[0];
1663-
1663+
16641664
expect(testObject.has("subObject1")).toBe(true);
16651665
expect(testObject.has("subObject2")).toBe(true);
16661666
expect(testObject.has("subObject3")).toBe(true);
@@ -1675,7 +1675,7 @@ describe('ParseQuery', () => {
16751675
expect(testObject.has("subObject2")).toBe(false); //selected and not returned
16761676
expect(testObject.has("subObject3")).toBe(true); //not selected, so should still be there
16771677
expect(testObject.has("subObject4")).toBe(true); //selected and just added
1678-
expect(testObject.has("subObject5")).toBe(true);
1678+
expect(testObject.has("subObject5")).toBe(true);
16791679
expect(testObject.get("subObject5").subSubObject).toBeDefined();
16801680
expect(testObject.get("subObject5").subSubObject.bar).toBeDefined(); //not selected but a sibiling was, so should still be there
16811681
}).then(() => {
@@ -1685,4 +1685,67 @@ describe('ParseQuery', () => {
16851685
});
16861686
});
16871687

1688+
it('full text search with one parameter', () => {
1689+
let query = new ParseQuery('Item');
1690+
1691+
query.fullTextSearch('size', 'small');
1692+
1693+
expect(query.toJSON()).toEqual({
1694+
where: {
1695+
size: {
1696+
$text: {
1697+
$search: {
1698+
$term: "small"
1699+
}
1700+
}
1701+
}
1702+
}
1703+
});
1704+
});
1705+
1706+
it('full text search with all parameters', () => {
1707+
let query = new ParseQuery('Item');
1708+
1709+
query.fullTextSearch('size', 'medium', 'en', false, true);
1710+
1711+
expect(query.toJSON()).toEqual({
1712+
where: {
1713+
size: {
1714+
$text: {
1715+
$search: {
1716+
$term: "medium",
1717+
$language: "en",
1718+
$caseSensitive: false,
1719+
$diacriticSensitive: true
1720+
}
1721+
}
1722+
}
1723+
}
1724+
});
1725+
1726+
});
1727+
1728+
it('add the score for the full text search', () => {
1729+
let query = new ParseQuery('Item');
1730+
1731+
query.fullTextSearch('size', 'medium', 'fr');
1732+
query.sortByTextScore();
1733+
1734+
expect(query.toJSON()).toEqual({
1735+
where: {
1736+
size: {
1737+
$text: {
1738+
$search: {
1739+
$term: "medium",
1740+
$language: "fr"
1741+
}
1742+
}
1743+
}
1744+
},
1745+
keys : "$score",
1746+
order : "$score"
1747+
});
1748+
1749+
});
1750+
16881751
});

0 commit comments

Comments
 (0)