-
Notifications
You must be signed in to change notification settings - Fork 938
Don't deserialize full Document proto for Query execution #2115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
8a276f2
f318dcd
91c228d
549aa06
69e402b
27cb4fe
1ded5b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,6 +75,12 @@ export class Document extends MaybeDocument { | |
private readonly converter?: (value: api.Value) => FieldValue | ||
) { | ||
super(key, version); | ||
assert( | ||
this.objectValue !== undefined || | ||
(this.proto !== undefined && this.converter !== undefined), | ||
'If objectValue is not defined, proto and converter need to be set.' | ||
); | ||
|
||
this.hasLocalMutations = !!options.hasLocalMutations; | ||
this.hasCommittedMutations = !!options.hasCommittedMutations; | ||
} | ||
|
@@ -83,11 +89,6 @@ export class Document extends MaybeDocument { | |
if (this.objectValue) { | ||
return this.objectValue.field(path); | ||
} else { | ||
assert( | ||
this.proto !== undefined && this.converter !== undefined, | ||
'Expected proto and converter to be defined.' | ||
); | ||
|
||
if (!this.fieldValueCache) { | ||
// TODO(b/136090445): Remove the cache when `getField` is no longer | ||
// called during Query ordering. | ||
|
@@ -103,42 +104,21 @@ export class Document extends MaybeDocument { | |
// deserialize the value at the requested field path. This speeds up | ||
// Query execution as query filters can discard documents based on a | ||
// single field. | ||
let protoValue: api.Value | undefined = this.proto!.fields[ | ||
path.firstSegment() | ||
]; | ||
for (let i = 1; protoValue !== undefined && i < path.length; ++i) { | ||
if (protoValue.mapValue) { | ||
protoValue = protoValue.mapValue.fields[path.get(i)]; | ||
} else { | ||
protoValue = undefined; | ||
} | ||
} | ||
|
||
const protoValue = this.getProtoField(path); | ||
if (protoValue === undefined) { | ||
fieldValue = null; | ||
} else { | ||
fieldValue = this.converter!(protoValue); | ||
} | ||
|
||
this.fieldValueCache.set(canonicalPath, fieldValue); | ||
} | ||
|
||
return fieldValue!; | ||
} | ||
} | ||
|
||
fieldValue(path: FieldPath): unknown { | ||
const field = this.field(path); | ||
return field ? field.value() : undefined; | ||
} | ||
|
||
data(): ObjectValue { | ||
if (!this.objectValue) { | ||
assert( | ||
this.proto !== undefined && this.converter !== undefined, | ||
'Expected proto and converter to be defined.' | ||
); | ||
|
||
let result = ObjectValue.EMPTY; | ||
obj.forEach(this.proto!.fields, (key: string, value: api.Value) => { | ||
result = result.set(new FieldPath([key]), this.converter!(value)); | ||
|
@@ -180,6 +160,27 @@ export class Document extends MaybeDocument { | |
return this.hasLocalMutations || this.hasCommittedMutations; | ||
} | ||
|
||
/** | ||
* Returns a the nested Protobuf value for 'path`. Can only be called if | ||
* `proto` was provided at construction time. | ||
*/ | ||
private getProtoField(path: FieldPath): api.Value | undefined { | ||
assert( | ||
this.proto !== undefined, | ||
"Can only call getProtoField() when proto is defined" | ||
); | ||
let protoValue: api.Value | undefined = this.proto!.fields[ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: add an empty line after There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
path.firstSegment() | ||
]; | ||
for (let i = 1; i < path.length; ++i) { | ||
if (!protoValue || !protoValue.mapValue) { | ||
return undefined; | ||
} | ||
protoValue = protoValue.mapValue.fields[path.get(i)]; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: add an empty line right after the loop? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
return protoValue; | ||
} | ||
|
||
static compareByField(field: FieldPath, d1: Document, d2: Document): number { | ||
const v1 = d1.field(field); | ||
const v2 = d2.field(field); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: s/a the/the/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done