Skip to content

Commit 4acb075

Browse files
feat(firestore): Added search stage support for languageCode, offset, limit, and retrievalDepth (#8161)
1 parent b0e5c07 commit 4acb075

4 files changed

Lines changed: 153 additions & 119 deletions

File tree

handwritten/firestore/dev/src/pipelines/expression.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3241,7 +3241,7 @@ export abstract class Expression
32413241
// * Evaluates to an HTML-formatted text snippet that renders terms matching
32423242
// * the search query in `<b>bold</b>`.
32433243
// *
3244-
// * @remarks This Expression can only be used within a `Search` stage.
3244+
// * @remarks This Expression can only be used within a `search` stage.
32453245
// *
32463246
// * @param rquery Define the search query using the search domain-specific language (DSL).
32473247
// * @returns An `Expression` representing the snippet function.
@@ -3252,7 +3252,7 @@ export abstract class Expression
32523252
// * Evaluates to an HTML-formatted text snippet that renders terms matching
32533253
// * the search query in `<b>bold</b>`.
32543254
// *
3255-
// * @remarks This Expression can only be used within a `Search` stage.
3255+
// * @remarks This Expression can only be used within a `search` stage.
32563256
// *
32573257
// * @param options Define how snippeting behaves.
32583258
// * @returns An `Expression` representing the snippet function.
@@ -3510,7 +3510,7 @@ export class Field
35103510
// /**
35113511
// * Perform a full-text search on this field.
35123512
// *
3513-
// * @remarks This Expression can only be used within a `Search` stage.
3513+
// * @remarks This Expression can only be used within a `search` stage.
35143514
// *
35153515
// * @param rquery Define the search query using the search domain-specific language (DSL).
35163516
// * @returns A `BooleanExpression` representing the matches function.
@@ -3528,7 +3528,7 @@ export class Field
35283528
* Evaluates to the distance in meters between the location specified
35293529
* by this field and the query location.
35303530
*
3531-
* @remarks This Expression can only be used within a `Search` stage.
3531+
* @remarks This Expression can only be used within a `search` stage.
35323532
*
35333533
* @example
35343534
* ```typescript
@@ -10905,7 +10905,7 @@ export function pipelineValue(
1090510905
// * @beta
1090610906
// * Perform a full-text search on the specified field.
1090710907
// *
10908-
// * @remarks This Expression can only be used within a `Search` stage.
10908+
// * @remarks This Expression can only be used within a `search` stage.
1090910909
// *
1091010910
// * @param searchField Search the specified field.
1091110911
// * @param rquery Define the search query using the search domain-specific language (DSL).
@@ -10923,7 +10923,7 @@ export function pipelineValue(
1092310923
*
1092410924
* Perform a full-text search on the document.
1092510925
*
10926-
* @remarks This Expression can only be used within a `Search` stage.
10926+
* @remarks This Expression can only be used within a `search` stage.
1092710927
*
1092810928
* @param rquery Define the search query using the search domain-specific language (DSL).
1092910929
* @returns A `BooleanExpression` representing the documentMatches function.
@@ -10944,7 +10944,7 @@ export function documentMatches(
1094410944
* in the search `query` provided to the `search` stage. If the `query` provided to the search stage
1094510945
* is not set or does not contain any text predicates, then this score will always be `0`.
1094610946
*
10947-
* @remarks This Expression can only be used within a `Search` stage.
10947+
* @remarks This Expression can only be used within a `search` stage.
1094810948
*
1094910949
* @returns An `Expression` representing the score function.
1095010950
*/
@@ -10956,7 +10956,7 @@ export function score(): Expression {
1095610956
// * Evaluates to an HTML-formatted text snippet that highlights terms matching
1095710957
// * the search query in `<b>bold</b>`.
1095810958
// *
10959-
// * @remarks This Expression can only be used within a `Search` stage.
10959+
// * @remarks This Expression can only be used within a `search` stage.
1096010960
// *
1096110961
// * @param searchField Search the specified field for matching terms.
1096210962
// * @param rquery Define the search query using the search domain-specific language (DSL).
@@ -10971,7 +10971,7 @@ export function score(): Expression {
1097110971
// * Evaluates to an HTML-formatted text snippet that highlights terms matching
1097210972
// * the search query in `<b>bold</b>`.
1097310973
// *
10974-
// * @remarks This Expression can only be used within a `Search` stage.
10974+
// * @remarks This Expression can only be used within a `search` stage.
1097510975
// *
1097610976
// * @param searchField Search the specified field for matching terms.
1097710977
// * @param options Define the search query using the search domain-specific language (DSL).
@@ -10996,7 +10996,7 @@ export function score(): Expression {
1099610996
* Evaluates to the distance in meters between the location in the specified
1099710997
* field and the query location.
1099810998
*
10999-
* @remarks This Expression can only be used within a `Search` stage.
10999+
* @remarks This Expression can only be used within a `search` stage.
1100011000
*
1100111001
* @param fieldName - Specifies the field in the document which contains
1100211002
* the first GeoPoint for distance computation.

handwritten/firestore/dev/system-test/pipeline.ts

Lines changed: 97 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7365,68 +7365,104 @@ describe.skipClassic('Pipeline search', () => {
73657365
// });
73667366
});
73677367

7368-
// TODO(search) enable with backend support
7369-
// describe('limit', () => {
7370-
// it('limits the number of documents returned', async () => {
7371-
// const ppl = firestore
7372-
// .pipeline()
7373-
// .collection(COLLECTION_NAME)
7374-
// .search({
7375-
// query: constant(true),
7376-
// sort: field('location')
7377-
// .geoDistance(new GeoPoint(39.6985, -105.024))
7378-
// .ascending(),
7379-
// limit: 5,
7380-
// queryEnhancement: 'disabled',
7381-
// });
7382-
//
7383-
// const snapshot = await ppl.execute();
7384-
// expectResults(
7385-
// snapshot,
7386-
// 'solTacos',
7387-
// 'lotusBlossomThai',
7388-
// 'goldenWaffle',
7389-
// );
7390-
// });
7391-
// it('limits the number of documents scored', async () => {
7392-
// const ppl = firestore
7393-
// .pipeline()
7394-
// .collection(COLLECTION_NAME)
7395-
// .search({
7396-
// query: field('menu').matches(
7397-
// 'chicken OR tacos OR fish OR waffles',
7398-
// ),
7399-
// retrievalDepth: 6,
7400-
// queryEnhancement: 'disabled',
7401-
// });
7402-
//
7403-
// const snapshot = await ppl.execute();
7404-
// expectResults(
7405-
// snapshot,
7406-
// 'eastsideChicken',
7407-
// 'eastsideTacos',
7408-
// 'solTacos',
7409-
// 'mileHighCatch',
7410-
// );
7411-
// });
7412-
// });
7368+
describe('languageCode', () => {
7369+
const rquery = 'al pastor';
7370+
it('en', async () => {
7371+
const ppl = firestore
7372+
.pipeline()
7373+
.collection(COLLECTION_NAME)
7374+
.search({
7375+
query: documentMatches(rquery),
7376+
sort: score().descending(),
7377+
languageCode: 'en',
7378+
// queryEnhancement: 'disabled'
7379+
});
74137380

7414-
// TODO(search) enable with backend support
7415-
// describe('offset', () => {
7416-
// it('skips N documents', async () => {
7417-
// const ppl = firestore
7418-
// .pipeline()
7419-
// .collection(COLLECTION_NAME)
7420-
// .search({
7421-
// query: constant(true),
7422-
// limit: 2,
7423-
// offset: 2,
7424-
// queryEnhancement: 'disabled',
7425-
// });
7426-
//
7427-
// const snapshot = await ppl.execute();
7428-
// expectResults(snapshot, 'eastsideChicken', 'eastsideTacos');
7429-
// });
7381+
const snapshot = await ppl.execute();
7382+
expectResults(snapshot, 'solTacos');
7383+
});
7384+
7385+
it('unknown', async () => {
7386+
const ppl = firestore
7387+
.pipeline()
7388+
.collection(COLLECTION_NAME)
7389+
.search({
7390+
query: documentMatches(rquery),
7391+
sort: score().descending(),
7392+
languageCode: 'unknown',
7393+
// queryEnhancement: 'disabled'
7394+
});
7395+
7396+
await expect(ppl.execute()).to.be.rejectedWith(
7397+
/3 INVALID_ARGUMENT.*/,
7398+
);
7399+
});
7400+
});
7401+
7402+
describe('limit', () => {
7403+
it('limits the number of documents returned', async () => {
7404+
const ppl = firestore
7405+
.pipeline()
7406+
.collection(COLLECTION_NAME)
7407+
.search({
7408+
query: field('location')
7409+
.geoDistance(new GeoPoint(39.6985, -105.024))
7410+
.lessThanOrEqual(100000000),
7411+
sort: field('location')
7412+
.geoDistance(new GeoPoint(39.6985, -105.024))
7413+
.ascending(),
7414+
limit: 3,
7415+
// queryEnhancement: 'disabled'
7416+
});
7417+
7418+
const snapshot = await ppl.execute();
7419+
expectResults(
7420+
snapshot,
7421+
'solTacos',
7422+
'lotusBlossomThai',
7423+
'mileHighCatch',
7424+
);
7425+
});
7426+
7427+
it('limits the number of documents scored via retrievalDepth', async () => {
7428+
const commonSearchParams = {
7429+
query: documentMatches('taco'),
7430+
addFields: [score().as('score')],
7431+
sort: score().descending(),
7432+
// queryEnhancement: 'disabled' as QueryEnhancement
7433+
};
7434+
7435+
let ppl = firestore
7436+
.pipeline()
7437+
.collection(COLLECTION_NAME)
7438+
.search({...commonSearchParams, retrievalDepth: 2});
7439+
7440+
let snapshot = await ppl.execute();
7441+
expectResults(snapshot, 'solTacos', 'eastsideTacos');
7442+
7443+
ppl = firestore
7444+
.pipeline()
7445+
.collection(COLLECTION_NAME)
7446+
.search({...commonSearchParams, retrievalDepth: 1});
7447+
7448+
snapshot = await ppl.execute();
7449+
expectResults(snapshot, 'eastsideTacos');
7450+
});
7451+
});
7452+
7453+
describe('offset', () => {
7454+
it('skips N documents', async () => {
7455+
const ppl = firestore.pipeline().collection(COLLECTION_NAME).search({
7456+
query: 'chicken',
7457+
limit: 2,
7458+
offset: 2,
7459+
// queryEnhancement: 'disabled'
7460+
});
7461+
7462+
const snapshot = await ppl.execute();
7463+
expectResults(snapshot, 'goldenWaffle');
7464+
});
7465+
});
74307466
// });
74317467
});
74327468

handwritten/firestore/dev/test/pipelines/stage.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,11 @@ describe('stage option serialization', () => {
257257
.database()
258258
.search({
259259
query: 'foo',
260-
// limit: 1,
261-
// retrievalDepth: 2,
262-
// offset: 3,
260+
limit: 1,
261+
retrievalDepth: 2,
262+
offset: 3,
263263
// queryEnhancement: 'required',
264-
// languageCode: 'en-US',
264+
languageCode: 'en-US',
265265
sort: [field('foo').ascending()],
266266
addFields: [constant(true).as('bar')],
267267
// select: [field('id')],
@@ -281,15 +281,15 @@ describe('stage option serialization', () => {
281281
foo: {
282282
stringValue: 'bar1',
283283
},
284-
// language_code: {
285-
// stringValue: 'en-US',
286-
// },
287-
// limit: {
288-
// integerValue: '1',
289-
// },
290-
// offset: {
291-
// integerValue: '3',
292-
// },
284+
language_code: {
285+
stringValue: 'en-US',
286+
},
287+
limit: {
288+
integerValue: '1',
289+
},
290+
offset: {
291+
integerValue: '3',
292+
},
293293
query: {
294294
functionValue: {
295295
args: [
@@ -303,9 +303,9 @@ describe('stage option serialization', () => {
303303
// query_enhancement: {
304304
// stringValue: 'required',
305305
// },
306-
// retrieval_depth: {
307-
// integerValue: '2',
308-
// },
306+
retrieval_depth: {
307+
integerValue: '2',
308+
},
309309
// select: {
310310
// mapValue: {
311311
// fields: {

0 commit comments

Comments
 (0)