Spring数据mongodb查询自动将String转换为ObjectId

标题可能不是很清楚,这里是问题所在

我正在以这种forms执行更新:

db.poi.update({ _id: ObjectId("50f40cd052187a491707053b"), "votes.userid": { "$ne": "50f5460d5218fe9d1e2c7b4f" } }, { $push: { votes: { "userid": "50f5460d5218fe9d1e2c7b4f", "value": 1 } }, $inc: { "score":1 } }) 

仅在没有具有相同用户标识的文档时才在文档中插入文档(解决方法,因为唯一索引不适用于数组)。 代码在mongo控制台上工作正常。 从我的应用程序我使用这个:

 @Override public void vote(String id, Vote vote) { 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); } 

如果作为“userid”使用不能成为mongo ObjectId的String,这可以正常工作,但如果我在示例中使用该字符串,则执行的查询会像这样翻译(来自mongosniff):

 update flags:0 q:{ _id: ObjectId('50f40cd052187a491707053b'), votes.userid: { $ne: ObjectId('50f5460d5218fe9d1e2c7b4f') } } o:{ $inc: { score: 1 }, $push: { votes: { userid: "50f5460d5218fe9d1e2c7b4f", value: 1 } } } 

该字符串现在是一个Objectid。 这是一个错误吗? BasicQuery做同样的事情。 我看到的唯一其他解决方案是对所有类ID使用ObjectId而不是String。

有什么想法吗?

更新:

这是投票类

 public class Vote { private String userid; private int value; } 

这是User类

 @Document public class User { @Id private String id; private String username; } 

这是我正在进行此更新的类和mongo文档

 @Document public class MyClass { @Id private String id; @Indexed private String name; int score private Setvotes = new HashSet(); } 

作为杰森

 { "_id" : ObjectId("50f40cd052187a491707053b"), "name" : "Test", "score" : 12, "votes" : [ { "userid" : "50f5460d5218fe9d1e2c7b4f", "value" : 1 } ] } 

将votes.userid中的Userid推送为String,但将相同的String作为$ ne中的ObjectId进行比较

在我看来,问题可以这样描述:如果你在类中使用String代替ObjectId,如果你想在其他文档(和嵌入文档)中使用这些id作为引用(没有dbrefs),它们会被推送as String(没关系,因为它们是字符串)。 这很好,因为spring数据可以将它们再次映射到objectid,但是如果你像我提到的那样进行查询则不行; 该字段在比较中转换为objectid(在本例中为$ ne运算符),但在嵌入文档中被视为字符串。 因此,总结一下,在我看来,$ ne运算符在这种情况下应该将字段视为字符串。

我的解决方案是编写一个自定义转换器,将String作为objectid存储在id为引用的文档中

 public class VoteWriteConverter implements Converter { @Override public DBObject convert(Vote vote) { DBObject dbo = new BasicDBObject(); dbo.put("userid", new ObjectId(vote.getUserid())); dbo.put("value", vote.getValue()); return dbo; } }