Conversation
There was a problem hiding this comment.
Code Review
This pull request adds duck-typing support for native PyMongo and third-party BSON objects (such as ObjectId, Decimal128, Regex, Timestamp, MinKey, and MaxKey) within the encode_value helper function, along with corresponding unit tests. The review feedback suggests optimizing this performance-critical code path by using an O(1) set lookup for class names to avoid unnecessary attribute checks and recommends running benchmarks to verify that these changes do not introduce performance regressions.
| if hasattr(value, "__class__"): | ||
| cls_name = value.__class__.__name__ | ||
| if cls_name == "ObjectId" and hasattr(value, "binary"): | ||
| return encode_value({"__oid__": str(value).lower()}) | ||
| if cls_name == "Decimal128" and hasattr(value, "to_decimal"): | ||
| return encode_value({"__decimal128__": str(value)}) | ||
| if cls_name == "Regex" and hasattr(value, "pattern"): | ||
| opts = getattr(value, "flags", "") or getattr(value, "options", "") | ||
| return encode_value( | ||
| {"__regex__": {"pattern": value.pattern, "options": str(opts)}} | ||
| ) | ||
| if cls_name == "Timestamp" and hasattr(value, "time") and hasattr(value, "inc"): | ||
| return encode_value( | ||
| { | ||
| "__request_timestamp__": { | ||
| "seconds": value.time, | ||
| "increment": value.inc, | ||
| } | ||
| } | ||
| ) | ||
| if cls_name == "MinKey": | ||
| return encode_value({"__min__": None}) | ||
| if cls_name == "MaxKey": | ||
| return encode_value({"__max__": None}) |
There was a problem hiding this comment.
The encode_value function is a critical hot path called recursively for every field of every document during serialization. While the proposed change aims to optimize standard types using an O(1) set lookup, any changes to this performance-critical code path must be validated and benchmarked to ensure they do not degrade performance or eliminate fast-path optimizations (such as the overhead of double getattr calls). Please run benchmarks to verify the performance impact of this change.
cls_name = getattr(getattr(value, "__class__", None), "__name__", None)
if cls_name in {"ObjectId", "Decimal128", "Regex", "Timestamp", "MinKey", "MaxKey"}:
if cls_name == "ObjectId" and hasattr(value, "binary"):
return encode_value({"__oid__": str(value).lower()})
elif cls_name == "Decimal128" and hasattr(value, "to_decimal"):
return encode_value({"__decimal128__": str(value)})
elif cls_name == "Regex" and hasattr(value, "pattern"):
opts = getattr(value, "flags", "") or getattr(value, "options", "")
return encode_value(
{"__regex__": {"pattern": value.pattern, "options": str(opts)}}
)
elif cls_name == "Timestamp" and hasattr(value, "time") and hasattr(value, "inc"):
return encode_value(
{
"__request_timestamp__": {
"seconds": value.time,
"increment": value.inc,
}
}
)
elif cls_name == "MinKey":
return encode_value({"__min__": None})
elif cls_name == "MaxKey":
return encode_value({"__max__": None})References
- For performance-critical code paths executed on every request, validate and benchmark any proposed readability simplifications to ensure they do not degrade performance or eliminate fast-path optimizations.
e40a2d2 to
06445ee
Compare
06445ee to
80c0c3f
Compare
80c0c3f to
740326c
Compare
| Args: | ||
| value (Union[NoneType, bool, int, float, datetime.datetime, \ | ||
| str, bytes, dict, ~google.cloud.Firestore.GeoPoint, \ | ||
| ~google.cloud.firestore_v1.vector.Vector]): A native |
There was a problem hiding this comment.
it looks like we should add to this type here
| if cls_name == "MinKey": | ||
| return encode_value({"__min__": None}) | ||
| if cls_name == "MaxKey": | ||
| return encode_value({"__max__": None}) |
There was a problem hiding this comment.
Instead of encoding all of these special strings here, we should be able to rely on the BSONType class, which has this knowledge built in already. We should have a simple way to find the matching BSONType for this PyMongo class, and a simple way to convert any BSONType to a Value. Then we can just string it together as something like BSONType._from_cls(value)._encode_value()
740326c to
7038386
Compare
7038386 to
337ec30
Compare
337ec30 to
bb5e132
Compare
Adds duck-typing detection in
encode_value()for native PyMongo / third-party BSON objects (bson.ObjectId,bson.Decimal128,bson.Regex,bson.Timestamp,bson.MinKey,bson.MaxKey).Allows applications migrating from MongoDB that use native PyMongo BSON objects to write directly to Firestore without triggering
TypeErrorserialization failures or requiring manual type conversions.Note that this is optional work and can be skipped. We can discuss this offline.
Fixes b/562164315 🦕