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

Update with $unset fails with mapping exception #4565

Open
csmager opened this issue Nov 20, 2023 · 7 comments
Open

Update with $unset fails with mapping exception #4565

csmager opened this issue Nov 20, 2023 · 7 comments
Assignees
Labels
status: pending-design-work Needs design work before any code can be developed type: bug A general bug

Comments

@csmager
Copy link

csmager commented Nov 20, 2023

I'm using spring-data-mongodb 4.0.8. On creating an update with an $unset, the following is added to the document:

{  $unset: { fieldName: 1 } }

The value here - 1 - is then attempted to be mapped to the correct type for that field. In my case, that's Decimal128. I get this stack trace:

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Integer] to type [org.bson.types.Decimal128] for value [1]
 at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
 at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
 at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
 at org.springframework.data.mongodb.core.convert.QueryMapper.applyFieldTargetTypeHintToValue(QueryMapper.java:848)
 at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedValue(QueryMapper.java:436)
 at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObjectForField(QueryMapper.java:339)
 at org.springframework.data.mongodb.core.convert.UpdateMapper.getMappedObjectForField(UpdateMapper.java:160)
 at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:166)
 at org.springframework.data.mongodb.core.convert.UpdateMapper.getMappedObject(UpdateMapper.java:66)
 at org.springframework.data.mongodb.core.convert.QueryMapper.convertSimpleOrDocument(QueryMapper.java:578)
 at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedKeyword(QueryMapper.java:399)
 at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:146)
 at org.springframework.data.mongodb.core.convert.UpdateMapper.getMappedObject(UpdateMapper.java:66)
 at org.springframework.data.mongodb.core.QueryOperations$UpdateContext.getMappedUpdate(QueryOperations.java:864)
 at org.springframework.data.mongodb.core.MongoTemplate.doUpdate(MongoTemplate.java:1617)
 at org.springframework.data.mongodb.core.MongoTemplate.updateFirst(MongoTemplate.java:1540)

The value here does not relate to the field value, it should not be mapped. My current workaround is to override unset as below:

var update = new Update() {
    @Override
    public Update unset(String key) {
        addMultiFieldOperation("$unset", key, "");
        return this;
    }
};

The mapping does not fail with an empty string, and an empty string is what's used in the examples in the docs.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 20, 2023
@christophstrobl christophstrobl added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 20, 2023
@christophstrobl christophstrobl self-assigned this Nov 20, 2023
@christophstrobl
Copy link
Member

@csmager thanks for reporting! We'll see what we can do about this.

@christophstrobl
Copy link
Member

@csmager I might be missing something as I was not able to reproduce the issue on 4.0.x nor current main.
Could you please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

@christophstrobl christophstrobl added the status: waiting-for-feedback We need additional information before we can continue label Nov 21, 2023
@csmager
Copy link
Author

csmager commented Nov 21, 2023

Of course - I'd been a little lazy and hoped it'd be easily reproducible. I'll try and reproduce.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 21, 2023
@csmager
Copy link
Author

csmager commented Nov 21, 2023

The repo is here: https://github.com/csmager/spring-data-mongodb-repro

But I suspect all you need is this. It appears the field mapping to Decimal128 is important - I tried the default (which I think is string), and I tried other types that I thought ought to fail (like ObjectId or Date), and none throw.

@SpringBootTest
class SpringDataMongoDbReproTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    void throws_on_unset() {
        this.mongoTemplate.updateMulti(
            new Query(),
            new Update()
                .unset("field"),
            Entity.class
        );
    }

    public static class Entity {
        private ObjectId id;
        @Field(targetType = FieldType.DECIMAL128)
        private BigDecimal field;
    }
}

@christophstrobl
Copy link
Member

ah thanks - I was using Decimal128 as field type directly.

@csmager
Copy link
Author

csmager commented Nov 23, 2023

Yeah, it does seem it's the type hint / mapping that's causing it, it's probably quite a niche issue.

@christophstrobl
Copy link
Member

Unfortunately there's no easy fix for the issue as we'd need to provide more context to the update mapping (which needs a bit more thought) to decide if conversion needs to be applied.

@christophstrobl christophstrobl added status: pending-design-work Needs design work before any code can be developed and removed status: feedback-provided Feedback has been provided labels Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: pending-design-work Needs design work before any code can be developed type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants