Skip to content

Commit

Permalink
Merge pull request #179 from weaviate/grpc/fix-filters-parsing-to-grp…
Browse files Browse the repository at this point in the history
…c-message

Fix parsing of `date` and `float` filters to gRPC message
  • Loading branch information
tsmith023 authored Jul 30, 2024
2 parents 0a51d72 + 795a9a2 commit 15a1206
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 13 deletions.
20 changes: 10 additions & 10 deletions src/collections/filters/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,18 @@ describe('Testing of the filter class with a simple collection', () => {
});
expect(res.objects.length).toEqual(2);

const obj1 = res.objects[0];
const obj2 = res.objects[1];
// Return of fetch not necessarily in order due to filter
expect(res.objects.map((o) => o.properties.text)).toContain('two');
expect(res.objects.map((o) => o.properties.text)).toContain('three');

expect(obj1.properties.text).toEqual('two');
expect(obj1.properties.int).toEqual(2);
expect(obj1.properties.float).toEqual(2.2);
expect(obj1.uuid).toEqual(ids[1]);
expect(res.objects.map((o) => o.properties.int)).toContain(2);
expect(res.objects.map((o) => o.properties.int)).toContain(3);

expect(obj2.properties.text).toEqual('three');
expect(obj2.properties.int).toEqual(3);
expect(obj2.properties.float).toEqual(3.3);
expect(obj2.uuid).toEqual(ids[2]);
expect(res.objects.map((o) => o.properties.float)).toContain(2.2);
expect(res.objects.map((o) => o.properties.float)).toContain(3.3);

expect(res.objects.map((o) => o.uuid)).toContain(ids[1]);
expect(res.objects.map((o) => o.uuid)).toContain(ids[2]);
});

it('should filter a fetch objects query with a reference filter', async () => {
Expand Down
26 changes: 23 additions & 3 deletions src/collections/serialize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class FilterGuards {
};

static isFloat = (argument?: FilterValueType): argument is number => {
return typeof argument === 'number';
return typeof argument === 'number' && !Number.isInteger(argument);
};

static isFloatArray = (argument?: FilterValueType): argument is number[] => {
Expand Down Expand Up @@ -793,8 +793,8 @@ export class Serialize {
return FiltersGRPC.fromPartial({
operator: Serialize.operator(filters.operator),
target: filters.target,
valueText: FilterGuards.isText(value) ? value : undefined,
valueTextArray: FilterGuards.isTextArray(value) ? { values: value } : undefined,
valueText: this.filtersGRPCValueText(value),
valueTextArray: this.filtersGRPCValueTextArray(value),
valueInt: FilterGuards.isInt(value) ? value : undefined,
valueIntArray: FilterGuards.isIntArray(value) ? { values: value } : undefined,
valueNumber: FilterGuards.isFloat(value) ? value : undefined,
Expand All @@ -806,6 +806,26 @@ export class Serialize {
}
};

private static filtersGRPCValueText = (value: any) => {
if (FilterGuards.isText(value)) {
return value;
} else if (FilterGuards.isDate(value)) {
return value.toISOString();
} else {
return undefined;
}
};

private static filtersGRPCValueTextArray = (value: any) => {
if (FilterGuards.isTextArray(value)) {
return { values: value };
} else if (FilterGuards.isDateArray(value)) {
return { values: value.map((v) => v.toISOString()) };
} else {
return undefined;
}
};

private static filterTargetToREST = (target: FilterTarget): string[] => {
if (target.property) {
return [target.property];
Expand Down
220 changes: 220 additions & 0 deletions src/collections/serialize/unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
NearVideoSearch,
PropertiesRequest,
} from '../../proto/v1/search_get.js';
import { Filters as FiltersFactory } from '../filters/classes.js';
import filter from '../filters/index.js';
import { Reference } from '../references/index.js';
import sort from '../sort/index.js';
Expand Down Expand Up @@ -489,6 +490,225 @@ describe('Unit testing of Serialize', () => {
],
});
});

describe('.filtersGRPC', () => {
it('should parse a text property', () => {
const f = filter<any>().byProperty('name').equal('test');
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'name',
},
valueText: 'test',
});
});
it('should parse a text array property', () => {
const f = filter<any>().byProperty('name').equal(['test1', 'test2']);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'name',
},
valueTextArray: { values: ['test1', 'test2'] },
});
});
it('should parse an int property', () => {
const f = filter<any>().byProperty('age').equal(10);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'age',
},
valueInt: 10,
});
});
it('should parse an int array property', () => {
const f = filter<any>().byProperty('age').equal([10, 20]);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'age',
},
valueIntArray: { values: [10, 20] },
});
});
it('should parse a float property', () => {
const f = filter<any>().byProperty('height').equal(1.8);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'height',
},
valueNumber: 1.8,
});
});
it('should parse a float array property', () => {
const f = filter<any>().byProperty('height').equal([1.8, 2.8]);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'height',
},
valueNumberArray: { values: [1.8, 2.8] },
});
});
it('should parse a boolean property', () => {
const f = filter<any>().byProperty('isHappy').equal(true);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'isHappy',
},
valueBoolean: true,
});
});
it('should parse a boolean array property', () => {
const f = filter<any>().byProperty('isHappy').equal([true, false]);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'isHappy',
},
valueBooleanArray: { values: [true, false] },
});
});
it('should parse a date property', () => {
const date = new Date();
const f = filter<any>().byProperty('birthday').equal(date);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'birthday',
},
valueText: date.toISOString(),
});
});
it('should parse a date array property', () => {
const date1 = new Date();
const date2 = new Date();
const f = filter<any>().byProperty('birthday').equal([date1, date2]);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'birthday',
},
valueTextArray: { values: [date1.toISOString(), date2.toISOString()] },
});
});
it('should parse a geo property', () => {
const f = filter<any>()
.byProperty('location')
.withinGeoRange({ latitude: 1, longitude: 1, distance: 1 });
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_WITHIN_GEO_RANGE,
on: [],
filters: [],
target: {
property: 'location',
},
valueGeo: {
distance: 1,
latitude: 1,
longitude: 1,
},
});
});
it('should parse several filters in a Filters.and', () => {
const f = FiltersFactory.and(
filter<any>().byProperty('name').equal('test'),
filter<any>().byProperty('age').equal(10)
);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_AND,
on: [],
target: undefined,
filters: [
{
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'name',
},
valueText: 'test',
},
{
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'age',
},
valueInt: 10,
},
],
});
});
it('should parse several filters in a Filters.or', () => {
const f = FiltersFactory.or(
filter<any>().byProperty('name').equal('test'),
filter<any>().byProperty('age').equal(10)
);
const args = Serialize.filtersGRPC(f);
expect(args).toEqual<Filters>({
operator: Filters_Operator.OPERATOR_OR,
on: [],
target: undefined,
filters: [
{
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'name',
},
valueText: 'test',
},
{
operator: Filters_Operator.OPERATOR_EQUAL,
on: [],
filters: [],
target: {
property: 'age',
},
valueInt: 10,
},
],
});
});
});
});

describe('Unit testing of DataGuards', () => {
Expand Down

0 comments on commit 15a1206

Please sign in to comment.