如何在Java中直接从mongodb查询返回原始的JSON数据?

30

我有以下代码:

@RequestMapping(value = "/envinfo", method = RequestMethod.GET)
@ResponseBody
public Map getEnvInfo()
{
    BasicQuery basicQuery = new BasicQuery("{_id:'51a29f6413dc992c24e0283e'}", "{'envinfo':1, '_id': false }");
    Map envinfo= mongoTemplate.findOne(basicQuery, Map.class, "jvmInfo");
    return envinfo;
}

正如您所注意到的,该代码:

  1. 从MongoDB检索JSON数据
  2. 将其转换为Map对象
  3. 然后,Spring MongoData将Map对象转换为JSON并将其返回给浏览器。

是否可能直接从MongoDb返回原始JSON而不经过中间转换步骤?

3个回答

21

现在有两种方法可以实现这个:

1. 使用MongoTemplate上的CollectionCallback

您可以使用CollectionCallback来直接处理返回的DBObject并简单地将其toString():

template.execute("jvmInfo", new CollectionCallback<String>() {
  String doInCollection(DBCollection collection) {
    DBCursor cursor = collection.find(query)
    return cursor.next().toString()
  }
}

即使出现异常,也可以将其翻译成Spring的DataAccessExceptions。请注意,这可能有点脆弱,因为我们期望查询只返回一个结果,但这很可能是你在尝试生成String时需要处理的问题。

2. 注册一个从DBObjectStringConverter

您可以实现一个Spring Converter来执行toString()

class DBObjectToStringConverter implements Converter<DBObject, String> {
  public String convert(DBObject source) {
    return source == null ? null : source.toString();
  }
}

你可以使用XML配置或覆盖customConversions()方法,返回new CustomConversions(Arrays.asList(new DBObjectToStringConverter())),以便将其注册到MongoConverter中。然后你可以简单地执行以下操作:

String result = mongoTemplate.findOne(basicQuery, String.class, "jvmInfo");

我将把刚才展示的转换器添加到Spring Data MongoDB中,并默认注册它,以便在即将发布的1.3 GA版本中使用,并将修复内容移植回1.2.x,作为解决DATAMONGO-743问题的一部分。


2
我有一个问题!我可以使用MongoRepository做同样的事情吗? - Jaxox
这个不起作用。我会得到以下错误信息。 “只有在CurrentBSONType为STRING时,才可以调用readString,而不是在CurrentBSONType为DOCUMENT时。” - Bobin

9
正如Oliver所指出的那样,您可以使用Spring Data来实现,但您可能更喜欢使用MongoDB更低级别的Java驱动程序。请参阅MongoDB Java Driver 3.xMongoDB Java Driver 2.x文档以获取有关使用该驱动程序的说明。
基本上,您需要执行以下操作:

MongoDB Java Driver 3.x

MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection coll = db.getCollection("testCollection");    
BasicDBObject query = new BasicDBObject("_id", "51a29f6413dc992c24e0283e");

try (MongoCursor<Document> cursor = collection.find(query).iterator()) {
    while(cursor.hasNext()) {
        System.out.println(cursor.next());
    }
}

MongoDB Java Driver 2.x

MongoClient mongoClient = new MongoClient();
DB db = mongoClient.getDB("test");
DBCollection coll = db.getCollection("testCollection");    
BasicDBObject query = new BasicDBObject("_id", "51a29f6413dc992c24e0283e");

try (DBCursor cursor = coll.find(query)) {
    while(cursor.hasNext()) {
        System.out.println(cursor.next());
    }
}

这将打印出集合中所有具有字段_id且值为51a29f6413dc992c24e0283e的文档。


2
有人对此进行了负投票?很想知道它的问题在哪里。我没有测试它,但它几乎是从文档中复制粘贴的。 - CorayThan
1
有三个方面:首先,使用Spring Data是可以做到的。我正准备准备一个答案来看看它是如何工作的。其次,你的代码将东西倒出到标准输出,而不是返回一个String。第三,你的代码没有处理任何异常或类似的情况。我知道这只是示例代码,但如果您在使用Spring Data实现其他所有内容的情况下使用您的代码,那么会导致不一致的行为。 - Oliver Drotbohm
6
如果您能使用Spring Data实现,那就很有趣,我们想看看您是如何使用它的。至于返回字符串而不处理异常,这些都是相当琐碎的问题。任何一位合格的程序员都可以想出如何返回cursor.next()的结果而不是将其输出到系统控制台。 - CorayThan
1
没问题。总体来说,你展示的代码没有问题。只是人们在使用SD MongoDB时期望得到某些特定的行为(例如异常转换等),而你的示例中却没有实现这些行为。原帖的作者似乎正在使用SD MongoDB编写代码,并且明确要求使用它,所以我认为“你应该使用其他东西”不是一个很好的处理方式。这就像有人要求一个安卓应用,然后你告诉他“去买个iPhone”一样:)。别介意!我刚刚发布了我的答案:简而言之,它将在不久的将来自动完成,但现在已经可以轻松实现。 - Oliver Drotbohm

-3

对我来说,下面的方法完美地解决了问题:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.bson.Document;

List<Document> documents = mongoTemplate.find(query, Document.class, "collection_name");

问题不是要求 rawJson 吗?你在这里返回了一个对象列表。 - BabyishTank
1
如果他所说的rawJson指的是“原始”json字段,那么Document应该可以胜任。 - arxakoulini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接