Results 1 to 2 of 2

Thread: Spring data mongoDB Criteria.ne autoconversion to ObjectId

  1. #1
    Join Date
    Dec 2011
    Posts
    10

    Default Spring data mongoDB Criteria.ne autoconversion to ObjectId

    Hello,

    I'm executing an update in this form:

    Code:
    db.poi.update( {_id: ObjectId("50f40cd052187a491707053b"), "votes.userid":{"$ne": "50f5460d5218fe9d1e2c7b4f"}},  { $push:{votes:{"userid": "50f5460d5218fe9d1e2c7b4f", "value": 1}}, $inc:{"score":1}})
    To insert a document in an array only if there isn't one with the same userid (workaround because unique indexes don't work on arrays). The code works fine from mongo console. From my application I'm using this:

    Code:
    Query query = new Query(Criteria.where("_id").is(id).and("votes.userid").ne(vote.getUserid()));
    		Update update = new Update().inc("score", vote.getValue()).push("votes", vote);
    		mongoOperations.updateFirst(query, update, Poi.class);
    This works fine if as "userid" I use a String that can't be a mongo ObjectId, but if I use the string in the example, the query executed translates like this (from mongosniff):

    Code:
    update  flags:0 q:{ _id: ObjectId('50f40cd052187a491707053b'), votes.userid: { $ne: ObjectId('50f5460d5218fe9d1e2c7b4f') } } o:{ $inc: { score: 1 }, $push: { votes: { userid: "50f5460d5218fe9d1e2c7b4f", value: 1 } } }
    The string is now an Objectid. Is this a bug? Can I work around this using a BasicQuery or I'll get the same result? The only other solution I see is to use ObjectId instead of String for all classes ids.

    Edit: it's the same with BasicQuery
    Last edited by alexmaz; Jan 15th, 2013 at 09:07 AM.

  2. #2
    Join Date
    Dec 2011
    Posts
    10

    Default

    It seems to me the problem can be described like this: if you use String in your classes in place of an ObjectId, if you want to use those ids as references (no dbrefs) in other documents (and embedded documents), they are pushed as String (it's ok because they are Strings). It's fine because spring data can map them again to objectid, but it's not fine if you do a query like the one I mentioned; the field is converted to an objectid in the comparison (the $ne operator in this case) but is considered as a string in the embedded document. So, to wrap up, in my opinion the $ne operator in this case should consider the field a String.

    My solution was to write a custom converter to store the String as an objectid in the documents where the id is a reference

    Code:
    public class VoteWriteConverter implements Converter<Vote, DBObject> {
    
    	@Override
    	public DBObject convert(Vote vote) {
    		DBObject dbo = new BasicDBObject();
    		dbo.put("userid", new ObjectId(vote.getUserid()));
    		dbo.put("value", vote.getValue());
    		return dbo;
    	}
    
    }
    Last edited by alexmaz; Jan 16th, 2013 at 05:37 AM.

Posting Permissions

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