Spring Data MongoDB查询自动将String转换为ObjectId [英] Spring data mongodb query converts String to ObjectId automatically

查看:836
本文介绍了Spring Data MongoDB查询自动将String转换为ObjectId的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The title might not be super clear, here the problem

我正在以这种形式执行更新:

I'm executing an update in this form:

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

仅在没有相同用户名的文档中将其插入数组中(解决方法,因为唯一索引不适用于数组).该代码可以从mongo控制台正常工作.从我的应用程序中,我正在使用这个:

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:

@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);
}

如果作为用户ID",我使用不能为mongo ObjectId的字符串,则此方法很好,但如果在示例中使用该字符串,则执行的查询将这样翻译(来自mongosniff):

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):

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.

The string is now an Objectid. Is this a bug? BasicQuery do the same thing. The only other solution I see is to use ObjectId instead of String for all classes ids.

有什么想法吗?

更新:

这是投票类

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

这是User类

@Document
public class User {

  @Id
  private String id;
  private String username;
}

这是我正在执行此更新的班级和mongo文档

This is the class and mongo document where I'm doing this update

@Document
public class MyClass {

  @Id
  private String id;
  @Indexed
  private String name;
  int score
  private Set<Vote>votes = new HashSet<Vote>();
}

作为杰森

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

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

Userid in votes.userid is pushed as String, but the same String is compared as an ObjectId in the $ne

推荐答案

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

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.

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

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

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;
  }
}

这篇关于Spring Data MongoDB查询自动将String转换为ObjectId的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆