Results 1 to 3 of 3

Thread: Support of MongoDB update $pull operation with expressions

Hybrid View

  1. #1
    Join Date
    Aug 2012
    Posts
    5

    Default Support of MongoDB update $pull operation with expressions

    Hi all,
    I was wondering if the Update pull method supports expressions of the type
    Code:
    { $pull : { field : {field2: value} } } removes array elements with field2 matching value
    Code:
    { $pull : { field : {$gt: 3} } } removes array elements greater than 3
    Code:
    { $pull : { field : {<match-criteria>} } } removes array elements meeting match criteria
    In particular my case is as follows:

    Code:
    public void removeByOfficeAndLastUpdatedDate(Long officeOid, Collection<Long> departureOids, Date olderThan) {
    
            Update cabinFareUpd = new Update();
    
            WriteResult updateResult = this.mongoTemplate.updateMulti(
                query(where(BaseFareFields.OFFICE_OID.getValue()).is(officeOid).
                    and(BaseFareFields.DEPARTURE_OID.getValue()).in(departureOids).
                    and(BaseFareFields.CABIN_FARE.getValue()).elemMatch(where(BaseFareFields.LAST_UPDATED_DATE.getValue()).lte(olderThan))),
                cabinFareUpd.pull(BaseFareFields.LAST_UPDATED_DATE.getValue(),
                    query(where(BaseFareFields.LAST_UPDATED_DATE.getValue()).lte(olderThan))), BaseFare.class);
    
            logger.info(updateResult.toString());
    
        }
    Basically I want to remove an array element within a document whose last udpated date is less that the informed date.

    The execution of the pull method as written above currently throws an exception:
    Code:
    java.lang.StackOverflowError
    	at java.util.HashMap$EntryIterator.<init>(Unknown Source)
    	at java.util.HashMap$EntryIterator.<init>(Unknown Source)
    	at java.util.HashMap.newEntryIterator(Unknown Source)
    	at java.util.HashMap$EntrySet.iterator(Unknown Source)
    	at java.util.AbstractMap.hashCode(Unknown Source)
    	at org.springframework.util.ObjectUtils.nullSafeHashCode(ObjectUtils.java:336)
    	at org.springframework.data.util.TypeDiscoverer.hashCode(TypeDiscoverer.java:365)
    	at org.springframework.data.util.ClassTypeInformation.hashCode(ClassTypeInformation.java:39)
    	at java.util.concurrent.ConcurrentHashMap.hash(Unknown Source)
    	at java.util.concurrent.ConcurrentHashMap.get(Unknown Source)
    	at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:151)
    ...
    I have attached the complete stack trace here Mongo Pull Stack Overflow exception 09-26-2012.zip
    Thanks in advance for your help,

    Sebastian

  2. #2
    Join Date
    Aug 2012
    Posts
    5

    Default

    I have refined the example a bit based on some additional research:
    1) The elemMatch part has been removed per this note on MongoDB's explanation of the use of $pull with expressions: "Because of this feature, to use the embedded doc as a match criteria, you cannot do exact matches on array elements."
    2) The key has been replaced to BaseFareFields.CABIN_FARE.getValue() as this is the array element in the document.
    Thus here's the updated code:
    Code:
    public void removeByOfficeAndLastUpdatedDate(Long officeOid, Collection<Long> departureOids, Date olderThan) {
    
            Update cabinFareUpd = new Update();
    
            WriteResult updateResult = this.mongoTemplate.updateMulti(
                query(where(BaseFareFields.OFFICE_OID.getValue()).is(officeOid).and(BaseFareFields.DEPARTURE_OID.getValue())
                    .in(departureOids)), 
                cabinFareUpd.pull(BaseFareFields.CABIN_FARE.getValue(),
                    query(where(BaseFareFields.LAST_UPDATED_DATE.getValue()).lte(olderThan))), 
                BaseFare.class);
    
            logger.info(updateResult.toString());
    
        }
    Either if I pass the object as query or criteria (just where(...)) I still get the same StackOverflow error...

    What I am trying to reflect in the code is the following:

    Code:
    db.baseFare.update({ "officeOid" : 1 , "departureOid" : { "$in" : [ 70000]}}, { $pull : {cabinFare: { lastUpdatedDate: { $lte: new Date(2012, 8, 20) } } } }) => Using new Date just in javascript
    Which I have tested and accomplishes what is expected i.e. removing a cabinFare whose lastUpdatedDate is less than or equal to 09/20/2012.

  3. #3
    Join Date
    Aug 2012
    Posts
    5

    Default

    I've come up with a solution that includes DBObject objects exposed directly as a way to deal with the nested expressions in the update:

    Code:
        public void removeByOfficeAndLastUpdatedDate(Long officeOid, Collection<Long> departureOids, Date olderThan) {
    
            DBObject lastUpdatedDateUpd = new BasicDBObject(BaseFareFields.LAST_UPDATED_DATE.getValue(), new BasicDBObject(
                "$lte", olderThan));
    
            Update cabinFareUpd = new Update();
    
            cabinFareUpd.pull(BaseFareFields.CABIN_FARE.getValue(), lastUpdatedDateUpd);
    
            WriteResult updateResult = this.mongoTemplate.updateMulti(
                query(where(BaseFareFields.OFFICE_OID.getValue()).is(officeOid).and(BaseFareFields.DEPARTURE_OID.getValue())
                    .in(departureOids)), cabinFareUpd,
                BaseFare.class);
    
            logger.info(updateResult.toString());
    
        }
    Hope that it is useful to someone dealing with similar update requirements.

    Cheers,

    Sebastian

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •