如何使用Java将HashMap插入MongoDB

2023/05/18

1. 简介

在这个快速教程中,我们将学习如何在MongoDB中使用Java HashMapMongoDB有一个Map友好的API,而Spring Data MongoDB使得使用Map或Map集合更加简单

2. 设置我们的场景

Spring Data MongoDB带有MongoTemplate,它有许多insert()的重载版本,允许我们将Map插入到我们的集合中。MongoDB表示JSON格式的文档。因此,我们可以用Java中的Map<String, Object>表示它

我们将使用MongoTemplate和一个简单的可重用Map来实现我们的用例。让我们从创建Map引用和注入MongoTemplate开始:

class MongoDbHashMapIntegrationTest {
    private static final Map<String, Object> MAP = new HashMap<>();

    @Autowired
    private MongoTemplate mongo;
}

然后,我们将使用一些不同类型的条目来初始化我们的Map:

@BeforeAll
static void init() {
    MAP.put("name", "Document A");
    MAP.put("number", 2);
    MAP.put("dynamic", true);
}

我们用@BeforeAll标记它,这样我们所有的测试都可以使用它。

3. 直接插入单个Map

首先,我们调用mongo.insert()并选择一个集合插入:

@Test
void whenUsingMap_thenInsertSucceeds() {
    Map<String, Object> saved = mongo.insert(MAP, "map-collection");

    assertNotNull(saved.get("_id"));
}

不需要特定的包装器。插入后,我们的Map成为我们MongoDB集合中的单个JSON文档。最重要的是,我们可以检查MongoDB生成的_id属性是否存在,确保它被正确处理

4. 直接批量插入Map

我们还可以插入一个Map集合。每次插入都会成为不同的文档。此外,为确保我们不插入重复项,我们将使用Set

让我们将之前创建的Map与新Map一起添加到我们的集合中

@Test
void whenMapSet_thenInsertSucceeds() {
    Set<Map<String, Object>> set = new HashSet<>();

    Map<String, Object> otherMap = new HashMap<>();
    otherMap.put("name", "Other Document");
    otherMap.put("number", 22);

    set.add(MAP);
    set.add(otherMap);

    Collection<Map<String, Object>> insert = mongo.insert(set, "map-set");

    assertEquals(2, insert.size());
}

结果,我们得到了两个插入。此方法有助于减少一次添加大量文档的开销

5. 从Map构建文档并插入

Document类是在Java中处理MongoDB文档的推荐方式。它实现了Map和Bson,使其易于工作。让我们使用接收Map的构造函数:

@Test
void givenMap_whenDocumentConstructed_thenInsertSucceeds() {
    Document document = new Document(MAP);

    Document saved = mongo.insert(document, "doc-collection");

    assertNotNull(saved.get("_id"));
}

在内部,Document使用LinkedHashMap来保证插入顺序。

6. 从Map构造BasicDBObject并插入

虽然 Document类是首选,但我们也可以从Map构造BasicDBObject:

@Test
void givenMap_whenBasicDbObjectConstructed_thenInsertSucceeds() {
    BasicDBObject dbObject = new BasicDBObject(MAP);

    BasicDBObject saved = mongo.insert(dbObject, "db-collection");

    assertNotNull(saved.get("_id"));
}

如果我们处理遗留代码,BasicDBObject仍然很有用,因为Document类仅从MongoDB驱动程序版本3开始可用

7. 从对象值流构建文档并插入

在最后一个示例中,我们将从Map构建一个Document对象,其中每个键的值都是一个Object值列表。由于我们知道值的格式,因此我们可以通过为每个值放置一个属性名称来构建我们的Document。

让我们从构建我们的input Map开始:

Map<String, List<Object>> input = new HashMap<>();
List<Object> listOne = new ArrayList<>();
listOne.add("Doc A");
listOne.add(1);

List<Object> listTwo = new ArrayList<>();
listTwo.add("Doc B");
listTwo.add(2);

input.put("a", listOne);
input.put("b", listTwo);

如我们所见,没有属性名称,只有值。因此,让我们流式传输我们的input的entrySet()并从中构建我们的result。为此,我们会将输入中的每个条目收集到HashSet中。然后,我们将在accumulator函数中构建一个Document,将entry键作为_id属性。之后,我们将遍历条目值,将它们放在适当的属性名称下。最后,我们将每个Document添加到我们的result中:

Set<Document> docs = input.entrySet()
    .stream()
    .collect(HashSet::new, (set, entry) -> {
        Document document = new Document();
        
        document.put("_id", entry.getKey());
        Iterator<Object> iterator = entry.getValue()
            .iterator();
        document.put("name", iterator.next());
        document.put("number", iterator.next());
        set.add(document);
    }, Set::addAll);

Collection<Document> saved = mongo.insert(docs, "custom-set");

saved.forEach(this::assertHasMongoId);

请注意,在此示例中我们不需要来自collect()的第三个参数。但这是因为只有并行流使用combiner函数。

最后,我们可以将result插入MongoDB

mongo.insert(result, "custom-set");

这种策略很有用,例如,如果我们想将CSV值转换为JSON。

8. 总结

在本文中,我们看到了使用HashMap和HashMap列表将文档插入MongoDB集合的不同方法。我们使用MongoTemplate来简化任务并使用最常见的文档抽象:BasicDBObject和Document。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章