Skip to content
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

Simplify usage of user provided aggregation operations. #4059

Closed
wants to merge 2 commits into from

Conversation

christophstrobl
Copy link
Member

Introduce Aggregation.stage which allows to use a plain JSON String or any valid Bson representation to be used within an aggregation pipeline stage, without having to implement AggregationOperation directly.
The change allows to make use of driver native builder API for aggregates.

Introduce Aggregation.stage which allows to use a plain JSON String or any valid Bson representation to be used within an aggregation pipeline stage, without having to implement AggregationOperation directly.
The change allows to make use of driver native builder API for aggregates.
@christophstrobl christophstrobl linked an issue May 20, 2022 that may be closed by this pull request

@Override
default CodecRegistry getCodecRegistry() {
return MongoClientSettings.getDefaultCodecRegistry();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, when (if ever) will this default implementation be used? The underlying driver never uses this method, because it doesn't take into account important user configuration (most notably, the UUID representation).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it’s public API that users may have implemented, defaulting here eases the pain when upgrading to the new version. Internal implementations pick up the driver registry.
Are custom codecs heavily used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main thing is that even the default registry is changed in the MongoClient constructor in order to apply the uuidRepresentation to the registry. The default registry will throw when trying to encode a UUID value, because the default UuidRepresentation is UNSPECIFIED

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note: MongoClientSettings.getDefaultCodecRegistry() is also used explicitly in the default implementation of the MongoConverter.getCodecRegistry method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, same reason for those upgrading. As long as the user does not provide a custom implementation of the converter the codec registry (with all the user settings regarding UUID codec,...) will be used.

Comment on lines +98 to +114
public static Map<String, Object> asMap(@Nullable Bson bson, CodecRegistry codecRegistry) {

if (bson == null) {
return Collections.emptyMap();
}
if (bson instanceof BasicDBObject) {
return ((BasicDBObject) bson);

if (bson instanceof Document document) {
return document;
}
if (bson instanceof DBObject) {
return ((DBObject) bson).toMap();
if (bson instanceof BasicDBObject dbo) {
return dbo;
}
if (bson instanceof DBObject dbo) {
return dbo.toMap();
}

return (Map) bson.toBsonDocument(Document.class, MongoClientSettings.getDefaultCodecRegistry());
return new Document((Map) bson.toBsonDocument(Document.class, codecRegistry));
Copy link

@stIncMale stIncMale May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Should org.bson.BsonDocument be also included as a special case? It is a Map with String keys, just like Document and BasicDBObject.
  • Should BasicDBObject be replaced with its supertype org.bson.BasicBSONObject? BasicBSONObject is a Map with String keys.
  • bson.toBsonDocument(Document.class, codecRegistry) is a Map<String, BsonValue>. Couldn't it be returned without shallowly copying its content in a new Document? The method BsonUtils.asDocument will still do this copying, but at least it will be done exactly where it is needed, instead of being done when there may be no need, which may be the case when asMap is called not from asDocument.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the additional Document wrapping can be removed, yes.
The BasicDBObject is still in there from 2.x generation and likely to be completely removed for 4.x.

Comment on lines +42 to +52
if (value instanceof Document document) {
return document;
}

if (value instanceof Bson bson) {
return BsonUtils.asDocument(bson, context.getCodecRegistry());
}

if (value instanceof Map map) {
return new Document(map);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BsonUtil.asMap does not allow itself a liberty of just checking instanceof Map. I think that's because this check does not guarantee that the map keys are of the String type. For this reason, I don't think that

if (value instanceof Map map) {
    return new Document(map);
}

is a type-safe code. Am I missing something?

Given the above, and that BsonUtil.asMap and BsonUtil.asDocument already check for special cases when some work may be skipped, can't the three if blocks be replaced with

if (value instanceof Bson bson) {
    return BsonUtils.asDocument(bson, context.getCodecRegistry());
}

?

Comment on lines +141 to +145
if (bson instanceof Document document) {
return document;
}

Map<String, Object> map = asMap(bson);
Map<String, Object> map = asMap(bson, codecRegistry);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that asMap already does the instanceof Document check, this check may be safely removed here.


@Override
default CodecRegistry getCodecRegistry() {
return MongoClientSettings.getDefaultCodecRegistry();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note: MongoClientSettings.getDefaultCodecRegistry() is also used explicitly in the default implementation of the MongoConverter.getCodecRegistry method.

mp911de pushed a commit that referenced this pull request Jun 27, 2022
Introduce Aggregation.stage which allows to use a plain JSON String or any valid Bson representation to be used within an aggregation pipeline stage, without having to implement AggregationOperation directly.
The change allows to make use of driver native builder API for aggregates.

Original pull request: #4059.
Closes #4038
mp911de added a commit that referenced this pull request Jun 27, 2022
Simplify code.

Original pull request: #4059.
See #4038
@mp911de mp911de added this to the 4.0 M5 (2022.0.0) milestone Jun 27, 2022
@mp911de mp911de added the type: enhancement A general enhancement label Jun 27, 2022
@mp911de
Copy link
Member

mp911de commented Jun 27, 2022

That's merged and polished now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Simplify usage of user provided aggregation operations.
4 participants