Java Spring数据mongodb查询自动将字符串转换为ObjectId

Java Spring数据mongodb查询自动将字符串转换为ObjectId,java,mongodb,spring-data,Java,Mongodb,Spring Data,标题可能不太清楚,问题就在这里 我正在执行此表单中的更新: db.poi.update({ _id: ObjectId("50f40cd052187a491707053b"), "votes.userid": { "$ne": "50f5460d5218fe9d1e2c7b4f" } }, { $push: { votes: { "userid": "50f5460d5218fe9d1e2c7b4f", "value": 1 }

标题可能不太清楚,问题就在这里

我正在执行此表单中的更新:

db.poi.update({
  _id: ObjectId("50f40cd052187a491707053b"),
  "votes.userid": {
    "$ne": "50f5460d5218fe9d1e2c7b4f"
  }
},
{
  $push: {
    votes: {
      "userid": "50f5460d5218fe9d1e2c7b4f", 
      "value": 1
    }
  },
  $inc: { "score":1 }
})
仅当没有具有相同用户ID的文档时才在数组中插入文档(解决方法是,唯一索引在数组中不起作用)。代码在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,那么这很好,但是如果我在示例中使用该字符串,则执行的查询如下所示(来自mongosniff):

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

有什么想法吗

更新:

这是投票课

public class Vote {
  private String userid;
  private int value;
}
这是用户类

@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 Set<Vote>votes = new HashSet<Vote>();
}

投票中的Userid.Userid作为字符串推送,但相同的字符串作为$ne中的ObjectId进行比较。在我看来,问题可以这样描述:如果您在类中使用字符串代替ObjectId,如果您想在其他文档(和嵌入文档)中使用这些id作为引用(无dbref),它们被作为字符串推送(这没关系,因为它们是字符串)。这很好,因为spring数据可以再次将它们映射到objectid,但如果您执行我提到的查询,这就不好了;该字段在比较中转换为objectid(本例中为$ne运算符),但在嵌入文档中被视为字符串。因此,在我看来,在这种情况下,$NE运算符应该考虑字段为字符串。 我的解决方案是编写一个自定义转换器,将字符串作为objectid存储在id为引用的文档中

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;
  }
}
公共类VoteWriteConverter实现转换器{
@凌驾
公共数据库对象转换(投票){
DBObject dbo=新的BasicDBObject();
put(“userid”,新的ObjectId(vote.getUserid());
dbo.put(“value”,vote.getValue());
返回dbo;
}
}

您似乎在内部存储了
String
值,这些值可以是
ObjectId
s。这是什么原因?
String
-to-
ObjectId
转换存在,以便能够在Java对象中使用
String
,并且数据库中仍然有
ObjectId
。也许我遗漏了什么。我使用字符串作为用户对象的_id;我的投票对象有一个userid字符串字段,我将其用作对用户id的引用。db中的投票“字段”是一个文档数组。当我$push此数组中的vote.userid时,数据库中有一个字符串,而不是ObjectId。我会用一些代码更新我的帖子,让它更清晰。你不能说你使用的是SpringDataMongoDB的哪个版本。最近,当我从1.0.3升级到1.1.0时,我被这个相反的情况所困扰,因为它们似乎已经取消了这种自动转换。我被咬是因为我导出为JSON,然后重新导入,留下了“_id”:{“$id”:“4ee76418f3e1450f11000000”},这给了我org.springframework.data.mapping.model.MappingException:找不到java.lang.String的映射元数据。我不认为你可以两全其美。因为Spring Data Mongodb 1.2.0也面临类似的问题。如果我在高级文档中使用相同的字符串,则比较是有效的。但如果我把它放在嵌套对象中,它就会尝试进行ObjectId比较。非常古怪。否则,插入/查询时的行为也应该相同。一定是个虫子。
{
  "_id" : ObjectId("50f40cd052187a491707053b"),
  "name" : "Test",
  "score" : 12,
  "votes" : [
    {
      "userid" : "50f5460d5218fe9d1e2c7b4f",
      "value" : 1
    }
  ]
}
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;
  }
}