Files

895 lines
26 KiB
TypeScript

/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { expect, use } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { addEqualityMatcher } from '../../util/equality_matcher';
import {
doc,
DocumentData,
setDoc,
query,
where,
FieldPath,
orderBy,
limit,
limitToLast,
startAt,
startAfter,
endAt,
endBefore,
collectionGroup,
collection,
and,
documentId,
addDoc,
getDoc,
or,
getDocs
} from '../util/firebase_export';
import {
apiDescribe,
PERSISTENCE_MODE_UNSPECIFIED,
withTestCollection
} from '../util/helpers';
import { execute, PipelineSnapshot } from '../util/pipeline_export';
use(chaiAsPromised);
// This is the Query integration tests from the lite API (no cache support)
// with some additional test cases added for more complete coverage.
apiDescribe.skipClassic('Query to Pipeline', persistence => {
addEqualityMatcher();
function verifyResults(
actual: PipelineSnapshot,
...expected: DocumentData[]
): void {
const results = actual.results;
expect(results.length).to.equal(expected.length);
for (let i = 0; i < expected.length; ++i) {
expect(results[i].data()).to.deep.equal(expected[i]);
}
}
it('supports default query', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{ 1: { foo: 1 } },
async (collRef, db) => {
const snapshot = await execute(db.pipeline().createFrom(collRef));
verifyResults(snapshot, { foo: 1 });
}
);
});
it('supports filtered query', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, where('foo', '==', 1));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 });
}
);
});
it('supports filtered query (with FieldPath)', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, where(new FieldPath('foo'), '==', 1));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 });
}
);
});
it('supports ordered query (with default order)', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 }, { foo: 2 });
}
);
});
it('supports ordered query (with asc)', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo', 'asc'));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 }, { foo: 2 });
}
);
});
it('supports ordered query (with desc)', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo', 'desc'));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 }, { foo: 1 });
}
);
});
it('supports limit query', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), limit(1));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 });
}
);
});
it('supports limitToLast query', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 },
3: { foo: 3 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), limitToLast(2));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 }, { foo: 3 });
}
);
});
it('supports startAt', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), startAt(2));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 });
}
);
});
it('supports startAt with limitToLast', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 },
3: { foo: 3 },
4: { foo: 4 },
5: { foo: 5 }
},
async (collRef, db) => {
const query1 = query(
collRef,
orderBy('foo'),
startAt(3),
limitToLast(4)
);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 3 }, { foo: 4 }, { foo: 5 });
}
);
});
it('supports endAt with limitToLast', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 },
3: { foo: 3 },
4: { foo: 4 },
5: { foo: 5 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), endAt(3), limitToLast(2));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 }, { foo: 3 });
}
);
});
it('supports startAfter (with DocumentSnapshot)', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { id: 1, foo: 1, bar: 1, baz: 1 },
2: { id: 2, foo: 1, bar: 1, baz: 2 },
3: { id: 3, foo: 1, bar: 1, baz: 2 },
4: { id: 4, foo: 1, bar: 2, baz: 1 },
5: { id: 5, foo: 1, bar: 2, baz: 2 },
6: { id: 6, foo: 1, bar: 2, baz: 2 },
7: { id: 7, foo: 2, bar: 1, baz: 1 },
8: { id: 8, foo: 2, bar: 1, baz: 2 },
9: { id: 9, foo: 2, bar: 1, baz: 2 },
10: { id: 10, foo: 2, bar: 2, baz: 1 },
11: { id: 11, foo: 2, bar: 2, baz: 2 },
12: { id: 12, foo: 2, bar: 2, baz: 2 }
},
async (collRef, db) => {
let docRef = await getDoc(doc(collRef, '2'));
let query1 = query(
collRef,
orderBy('foo'),
orderBy('bar'),
orderBy('baz'),
startAfter(docRef)
);
let snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ id: 3, foo: 1, bar: 1, baz: 2 },
{ id: 4, foo: 1, bar: 2, baz: 1 },
{ id: 5, foo: 1, bar: 2, baz: 2 },
{ id: 6, foo: 1, bar: 2, baz: 2 },
{ id: 7, foo: 2, bar: 1, baz: 1 },
{ id: 8, foo: 2, bar: 1, baz: 2 },
{ id: 9, foo: 2, bar: 1, baz: 2 },
{ id: 10, foo: 2, bar: 2, baz: 1 },
{ id: 11, foo: 2, bar: 2, baz: 2 },
{ id: 12, foo: 2, bar: 2, baz: 2 }
);
docRef = await getDoc(doc(collRef, '3'));
query1 = query(
collRef,
orderBy('foo'),
orderBy('bar'),
orderBy('baz'),
startAfter(docRef)
);
snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ id: 4, foo: 1, bar: 2, baz: 1 },
{ id: 5, foo: 1, bar: 2, baz: 2 },
{ id: 6, foo: 1, bar: 2, baz: 2 },
{ id: 7, foo: 2, bar: 1, baz: 1 },
{ id: 8, foo: 2, bar: 1, baz: 2 },
{ id: 9, foo: 2, bar: 1, baz: 2 },
{ id: 10, foo: 2, bar: 2, baz: 1 },
{ id: 11, foo: 2, bar: 2, baz: 2 },
{ id: 12, foo: 2, bar: 2, baz: 2 }
);
}
);
});
it('supports startAt (with DocumentSnapshot)', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { id: 1, foo: 1, bar: 1, baz: 1 },
2: { id: 2, foo: 1, bar: 1, baz: 2 },
3: { id: 3, foo: 1, bar: 1, baz: 2 },
4: { id: 4, foo: 1, bar: 2, baz: 1 },
5: { id: 5, foo: 1, bar: 2, baz: 2 },
6: { id: 6, foo: 1, bar: 2, baz: 2 },
7: { id: 7, foo: 2, bar: 1, baz: 1 },
8: { id: 8, foo: 2, bar: 1, baz: 2 },
9: { id: 9, foo: 2, bar: 1, baz: 2 },
10: { id: 10, foo: 2, bar: 2, baz: 1 },
11: { id: 11, foo: 2, bar: 2, baz: 2 },
12: { id: 12, foo: 2, bar: 2, baz: 2 }
},
async (collRef, db) => {
let docRef = await getDoc(doc(collRef, '2'));
let query1 = query(
collRef,
orderBy('foo'),
orderBy('bar'),
orderBy('baz'),
startAt(docRef)
);
let snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ id: 2, foo: 1, bar: 1, baz: 2 },
{ id: 3, foo: 1, bar: 1, baz: 2 },
{ id: 4, foo: 1, bar: 2, baz: 1 },
{ id: 5, foo: 1, bar: 2, baz: 2 },
{ id: 6, foo: 1, bar: 2, baz: 2 },
{ id: 7, foo: 2, bar: 1, baz: 1 },
{ id: 8, foo: 2, bar: 1, baz: 2 },
{ id: 9, foo: 2, bar: 1, baz: 2 },
{ id: 10, foo: 2, bar: 2, baz: 1 },
{ id: 11, foo: 2, bar: 2, baz: 2 },
{ id: 12, foo: 2, bar: 2, baz: 2 }
);
docRef = await getDoc(doc(collRef, '3'));
query1 = query(
collRef,
orderBy('foo'),
orderBy('bar'),
orderBy('baz'),
startAt(docRef)
);
snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ id: 3, foo: 1, bar: 1, baz: 2 },
{ id: 4, foo: 1, bar: 2, baz: 1 },
{ id: 5, foo: 1, bar: 2, baz: 2 },
{ id: 6, foo: 1, bar: 2, baz: 2 },
{ id: 7, foo: 2, bar: 1, baz: 1 },
{ id: 8, foo: 2, bar: 1, baz: 2 },
{ id: 9, foo: 2, bar: 1, baz: 2 },
{ id: 10, foo: 2, bar: 2, baz: 1 },
{ id: 11, foo: 2, bar: 2, baz: 2 },
{ id: 12, foo: 2, bar: 2, baz: 2 }
);
}
);
});
it('supports startAfter', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), startAfter(1));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 });
}
);
});
it('supports endAt', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), endAt(1));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 });
}
);
});
it('supports endBefore', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('foo'), endBefore(2));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1 });
}
);
});
it('supports pagination', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
let query1 = query(collRef, orderBy('foo'), limit(1));
const pipeline1 = db.pipeline().createFrom(query1);
let snapshot = await execute(pipeline1);
verifyResults(snapshot, { foo: 1 });
// Pass the document snapshot from the previous snapshot
query1 = query(query1, startAfter(snapshot.results[0].get('foo')));
snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 });
}
);
});
it('supports pagination on DocumentIds', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1 },
2: { foo: 2 }
},
async (collRef, db) => {
let query1 = query(
collRef,
orderBy('foo'),
orderBy(documentId(), 'asc'),
limit(1)
);
const pipeline1 = db.pipeline().createFrom(query1);
let snapshot = await execute(pipeline1);
verifyResults(snapshot, { foo: 1 });
// Pass the document snapshot from the previous snapshot
query1 = query(
query1,
startAfter(
snapshot.results[0].get('foo'),
snapshot.results[0].ref?.id
)
);
snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2 });
}
);
});
it('supports collection groups', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{},
async (collRef, db) => {
const collectionGroupId = `${collRef.id}group`;
const fooDoc = doc(
collRef.firestore,
`${collRef.id}/foo/${collectionGroupId}/doc1`
);
const barDoc = doc(
collRef.firestore,
`${collRef.id}/bar/baz/boo/${collectionGroupId}/doc2`
);
await setDoc(fooDoc, { foo: 1 });
await setDoc(barDoc, { bar: 1 });
const query1 = collectionGroup(collRef.firestore, collectionGroupId);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { bar: 1 }, { foo: 1 });
}
);
});
it('supports query over collection path with special characters', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{},
async (collRef, db) => {
const docWithSpecials = doc(collRef, 'so!@#$%^&*()_+special');
const collectionWithSpecials = collection(
docWithSpecials,
'so!@#$%^&*()_+special'
);
await addDoc(collectionWithSpecials, { foo: 1 });
await addDoc(collectionWithSpecials, { foo: 2 });
const snapshot = await execute(
db
.pipeline()
.createFrom(query(collectionWithSpecials, orderBy('foo', 'asc')))
);
verifyResults(snapshot, { foo: 1 }, { foo: 2 });
}
);
});
it('supports multiple inequality on same field', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
'01': { id: 1, foo: 1, bar: 1, baz: 1 },
'02': { id: 2, foo: 1, bar: 1, baz: 2 },
'03': { id: 3, foo: 1, bar: 1, baz: 2 },
'04': { id: 4, foo: 1, bar: 2, baz: 1 },
'05': { id: 5, foo: 1, bar: 2, baz: 2 },
'06': { id: 6, foo: 1, bar: 2, baz: 2 },
'07': { id: 7, foo: 2, bar: 1, baz: 1 },
'08': { id: 8, foo: 2, bar: 1, baz: 2 },
'09': { id: 9, foo: 2, bar: 1, baz: 2 },
'10': { id: 10, foo: 2, bar: 2, baz: 1 },
'11': { id: 11, foo: 2, bar: 2, baz: 2 },
'12': { id: 12, foo: 2, bar: 2, baz: 2 }
},
async (collRef, db) => {
const query1 = query(
collRef,
and(where('id', '>', 2), where('id', '<=', 10))
);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ id: 3, foo: 1, bar: 1, baz: 2 },
{ id: 4, foo: 1, bar: 2, baz: 1 },
{ id: 5, foo: 1, bar: 2, baz: 2 },
{ id: 6, foo: 1, bar: 2, baz: 2 },
{ id: 7, foo: 2, bar: 1, baz: 1 },
{ id: 8, foo: 2, bar: 1, baz: 2 },
{ id: 9, foo: 2, bar: 1, baz: 2 },
{ id: 10, foo: 2, bar: 2, baz: 1 }
);
}
);
});
it('supports multiple inequality on different fields', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
'01': { id: 1, foo: 1, bar: 1, baz: 1 },
'02': { id: 2, foo: 1, bar: 1, baz: 2 },
'03': { id: 3, foo: 1, bar: 1, baz: 2 },
'04': { id: 4, foo: 1, bar: 2, baz: 1 },
'05': { id: 5, foo: 1, bar: 2, baz: 2 },
'06': { id: 6, foo: 1, bar: 2, baz: 2 },
'07': { id: 7, foo: 2, bar: 1, baz: 1 },
'08': { id: 8, foo: 2, bar: 1, baz: 2 },
'09': { id: 9, foo: 2, bar: 1, baz: 2 },
'10': { id: 10, foo: 2, bar: 2, baz: 1 },
'11': { id: 11, foo: 2, bar: 2, baz: 2 },
'12': { id: 12, foo: 2, bar: 2, baz: 2 }
},
async (collRef, db) => {
const query1 = query(
collRef,
and(where('id', '>=', 2), where('baz', '<', 2))
);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ id: 4, foo: 1, bar: 2, baz: 1 },
{ id: 7, foo: 2, bar: 1, baz: 1 },
{ id: 10, foo: 2, bar: 2, baz: 1 }
);
}
);
});
it('supports collectionGroup query', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{ 1: { foo: 1 } },
async (collRef, db) => {
const snapshot = await execute(
db.pipeline().createFrom(collectionGroup(db, collRef.id))
);
verifyResults(snapshot, { foo: 1 });
}
);
});
// TODO(pipeline) fix test or SDK
// eslint-disable-next-line -- no-restricted-properties
it.skip('supports eq nan', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: NaN },
2: { foo: 2, bar: 1 },
3: { foo: 3, bar: 'bar' }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', '==', NaN));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1, bar: NaN });
}
);
});
// TODO(pipeline) fix test or SDK
// eslint-disable-next-line -- no-restricted-properties
it.skip('supports neq nan', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: NaN },
2: { foo: 2, bar: 1 },
3: { foo: 3, bar: 'bar' }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', '!=', NaN));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2, bar: 1 }, { foo: 3, bar: 'bar' });
}
);
});
it('supports eq null', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: null },
2: { foo: 2, bar: 1 }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', '==', null));
const classicSnapshot = await getDocs(query1);
const classicData = classicSnapshot.docs.map(d => d.data());
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, ...classicData);
}
);
});
it('supports neq null', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: null },
2: { foo: 2, bar: 1 }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', '!=', null));
const classicSnapshot = await getDocs(query1);
const classicData = classicSnapshot.docs.map(d => d.data());
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, ...classicData);
}
);
});
it('supports neq', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: 0 },
2: { foo: 2, bar: 1 }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', '!=', 0));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 2, bar: 1 });
}
);
});
it('supports array contains', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: [0, 2, 4, 6] },
2: { foo: 2, bar: [1, 3, 5, 7] }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', 'array-contains', 4));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1, bar: [0, 2, 4, 6] });
}
);
});
it('supports array contains any', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: [0, 2, 4, 6] },
2: { foo: 2, bar: [1, 3, 5, 7] },
3: { foo: 3, bar: [10, 20, 30, 40] }
},
async (collRef, db) => {
const query1 = query(
collRef,
where('bar', 'array-contains-any', [4, 5])
);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(
snapshot,
{ foo: 1, bar: [0, 2, 4, 6] },
{ foo: 2, bar: [1, 3, 5, 7] }
);
}
);
});
it('supports in', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: 2 },
2: { foo: 2 },
3: { foo: 3, bar: 10 }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', 'in', [0, 10, 20]));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 3, bar: 10 });
}
);
});
it('supports in with 1', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: 2 },
2: { foo: 2 },
3: { foo: 3, bar: 10 }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', 'in', [2]));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1, bar: 2 });
}
);
});
it('supports not in', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: 2 },
2: { foo: 2, bar: 1 },
3: { foo: 3, bar: 10 }
},
async (collRef, db) => {
const query1 = query(
collRef,
where('bar', 'not-in', [0, 10, 20]),
orderBy('foo')
);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1, bar: 2 }, { foo: 2, bar: 1 });
}
);
});
// TODO(pipeline) fix test or SDK
// eslint-disable-next-line -- no-restricted-properties
it.skip('supports not in with 1', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: 2 },
2: { foo: 2 },
3: { foo: 3, bar: 10 }
},
async (collRef, db) => {
const query1 = query(collRef, where('bar', 'not-in', [2]));
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 3, bar: 10 });
}
);
});
it('supports or operator', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
1: { foo: 1, bar: 2 },
2: { foo: 2, bar: 0 },
3: { foo: 3, bar: 10 }
},
async (collRef, db) => {
const query1 = query(
collRef,
or(where('bar', '==', 2), where('foo', '==', 3)),
orderBy('foo')
);
const snapshot = await execute(db.pipeline().createFrom(query1));
verifyResults(snapshot, { foo: 1, bar: 2 }, { foo: 3, bar: 10 });
}
);
});
// TODO(pipeline) fix test or SDK
// eslint-disable-next-line -- no-restricted-properties
it.skip('not-in removes existence filter', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
doc1: { field: 2 },
doc2: { field: 1 },
doc3: {}
},
async (collRef, db) => {
const query1 = query(collRef, where('field', 'not-in', [1]));
const snapshot = await execute(db.pipeline().createFrom(query1));
// doc3 (missing 'field') should be included because 'not-in' (and implicit order by)
// should NOT generate an existence filter.
verifyResults(snapshot, { field: 2 }, {});
}
);
});
// TODO(pipeline) fix test or SDK
// eslint-disable-next-line -- no-restricted-properties
it.skip('not-equal removes existence filter', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
doc1: { field: 2 },
doc2: { field: 1 },
doc3: {}
},
async (collRef, db) => {
const query1 = query(collRef, where('field', '!=', 1));
const snapshot = await execute(db.pipeline().createFrom(query1));
// doc3 (missing 'field') should be included.
verifyResults(snapshot, { field: 2 }, {});
}
);
});
it('inequality maintains existence filter', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
doc1: { field: 0 },
doc2: {}
},
async (collRef, db) => {
const query1 = query(collRef, where('field', '<', 1));
const snapshot = await execute(db.pipeline().createFrom(query1));
// doc2 (missing 'field') should be EXCLUDED by the inequality filter itself.
verifyResults(snapshot, { field: 0 });
}
);
});
it('explicit order maintains existence filter', () => {
return withTestCollection(
PERSISTENCE_MODE_UNSPECIFIED,
{
doc1: { field: 1 },
doc2: {}
},
async (collRef, db) => {
const query1 = query(collRef, orderBy('field'));
const snapshot = await execute(db.pipeline().createFrom(query1));
// doc2 (missing 'field') should be EXCLUDED by the explicit orderBy existence filter.
verifyResults(snapshot, { field: 1 });
}
);
});
});