[MongoDB] Java异步操作Mongo示例

一、问题描述

笔记。

二、版本说明

以下为本次示例相关环境的说明:

1、数据库

MongoDB server version: 4.2.10

2、JDK版本

java version "1.8.0_152"
Java(TM) SE Runtime Environment (build 1.8.0_152-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode)

3、依赖

<dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongodb-driver-reactivestreams</artifactId>
      <version>4.2.2</version>
</dependency>

三、相关代码

参考:QuickStartQuickTour

1、ObservableSubscriber.java和ConsumerSubscriber.java

这两个类照搬了QuickTour中的实现。

// ObservableSubscriber.java
public class ObservableSubscriber<T> implements Subscriber<T> {

//    private final List<T> received;		// 不作暂存
    private final List<RuntimeException> errors;
    private final CountDownLatch latch;
    private volatile Subscription subscription;
    private volatile boolean completed;

    /**
     * Construct an instance
     */
    public ObservableSubscriber() {
//        this.received = new ArrayList<>();
        this.errors = new ArrayList<>();
        this.latch = new CountDownLatch(1);
    }

    @Override
    public void onSubscribe(final Subscription s) {
        subscription = s;
    }

    @Override
    public void onNext(final T t) {
//        received.add(t);
    }

    @Override
    public void onError(final Throwable t) {
        if (t instanceof RuntimeException) {
            errors.add((RuntimeException) t);
        } else {
            errors.add(new RuntimeException("Unexpected exception", t));
        }
        onComplete();
    }

    @Override
    public void onComplete() {
        completed = true;
        latch.countDown();
    }

    /**
     * Gets the subscription
     *
     * @return the subscription
     */
    public Subscription getSubscription() {
        return subscription;
    }

    /**
     * Get error from subscription
     *
     * @return the error, which may be null
     */
    public RuntimeException getError() {
        if (errors.size() > 0) {
            return errors.get(0);
        }
        return null;
    }

    /**
     * Await completion or error
     *
     * @return this
     */
    public ObservableSubscriber<T> await() {
        return await(60, TimeUnit.SECONDS);
    }

    /**
     * Await completion or error
     *
     * @param timeout how long to wait
     * @param unit the time unit
     * @return this
     */
    public ObservableSubscriber<T> await(final long timeout, final TimeUnit unit) {
        subscription.request(Integer.MAX_VALUE);
        try {
            if (!latch.await(timeout, unit)) {
                throw new MongoTimeoutException("Publisher onComplete timed out");
            }
        } catch (InterruptedException e) {
            throw new MongoInterruptedException("Interrupted waiting for observeration", e);
        }
        if (!errors.isEmpty()) {
            throw errors.get(0);
        }
        return this;
    }
}
// ConsumerSubscriber.java
public class ConsumerSubscriber<T> extends ObservableSubscriber<T> {

    private final Consumer<T> consumer;

    public ConsumerSubscriber(final Consumer<T> consumer) {
        this.consumer = consumer;
    }

    @Override
    public void onNext(T t) {
        super.onNext(t);
        this.consumer.accept(t);
    }
}

2、调用程序ReactiveStreamDemo.java

// ReactiveStreamDemo.java
public class ReactiveStreamDemo {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        MongoClient client = MongoClients.create("mongodb://gavin:123456@192.168.0.100/crawlers");
        MongoDatabase database = client.getDatabase("crawlers");
        MongoCollection<FootballTeam> collection = database.getCollection("fb_team_details", FootballTeam.class);
		// 实体类自动映射
        CodecRegistry registry = CodecRegistries.fromRegistries(
                MongoClientSettings.getDefaultCodecRegistry(),
                CodecRegistries.fromProviders(
                        PojoCodecProvider.builder().automatic(true).build()
                )
        );

        collection = collection.withCodecRegistry(registry);
        FindPublisher<FootballTeam> findPublisher = collection.find(FootballTeam.class).limit(2);

        AtomicInteger count = new AtomicInteger(0);
        ObservableSubscriber<FootballTeam> subscriber = new ConsumerSubscriber<>(document -> {
            count.addAndGet(1);
            System.out.println(document);
        });
        findPublisher.subscribe(subscriber);
        // 等待任务结束
        subscriber.await(30 * 60, TimeUnit.SECONDS);
        long end = System.currentTimeMillis();

        System.out.printf("\ncount: %d, time: %f seconds\n", count.get(), (end - start) / 1000.0);
    }
}

输出结果:

FootballTeam{id=604f7af6a0eaf9ea4bfb2445, info=FootballTeamInfo{id='null', name_cn='布莱克本', name_en='Blackburn Rovers', league='英冠', city='兰开郡', players='29'}, players=[FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='特里布尔', number='19', position='中场', age='28', height='181', weight='72', birthday='1993-03-09', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='埃利奥特', number='16', position='前锋', age='17', height='170', weight='64', birthday='2003-04-04', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='贝里斯', number='22', position='后卫', age='19', height='188', weight='82', birthday='2002-01-30', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='科里.伊文斯', number='29', position='中场', age='30', height='180', weight='70', birthday='1990-07-30', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='托马斯·卡明斯基', number='1', position='守门员', age='28', height='190', weight='70', birthday='1992-10-23', habit_foot='左右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='艾恩斯利·皮尔斯', number='13', position='守门员', age='22', height='185', weight='0', birthday='1998-04-23', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='斯科特·沃顿', number='28', position='后卫', age='23', height='182', weight='0', birthday='1997-10-03', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='阿亚拉', number='5', position='后卫', age='30', height='190', weight='84', birthday='1990-11-07', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='唐宁', number='6', position='中场', age='36', height='180', weight='0', birthday='1984-07-22', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='道格拉斯', number='15', position='后卫', age='31', height='176', weight='64', birthday='1989-09-04', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='约翰逊', number='4', position='中场', age='33', height='178', weight='0', birthday='1987-04-28', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='达拉赫·勒尼汉', number='26', position='后卫', age='26', height='187', weight='76', birthday='1994-03-16', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='Amari'i Bell', number='17', position='后卫', age='26', height='180', weight='0', birthday='1994-05-05', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='瑞恩·尼亚姆贝', number='2', position='后卫', age='23', height='183', weight='76', birthday='1997-12-04', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='刘易斯·特拉维斯', number='27', position='中场', age='23', height='183', weight='0', birthday='1997-10-16', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='积及·迪云樸', number='18', position='中场', age='22', height='177', weight='0', birthday='1998-12-28', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='祖·罗斯韦尔', number='8', position='中场', age='26', height='185', weight='77', birthday='1995-01-11', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='本内特', number='31', position='中场', age='32', height='179', weight='69', birthday='1988-12-18', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='达克', number='23', position='中场', age='27', height='175', weight='71', birthday='1993-12-31', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='阿姆斯特朗', number='7', position='前锋', age='24', height='173', weight='69', birthday='1997-02-10', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='本·布雷顿', number='20', position='前锋', age='21', height='183', weight='75', birthday='1999-04-18', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='贾拉德-布兰斯韦特', number='30', position='后卫', age='18', height='195', weight='0', birthday='2002-06-27', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='安东尼斯·斯特吉亚基斯', number='41', position='守门员', age='21', height='196', weight='0', birthday='1999-03-16', habit_foot='左右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='乔丹·伊斯特姆', number='45', position='守门员', age='19', height='181', weight='0', birthday='2001-09-08', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='巴克利', number='21', position='中场', age='21', height='173', weight='0', birthday='1999-10-13', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='乔·兰金', number='24', position='后卫', age='21', height='183', weight='0', birthday='1999-07-26', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='刘易斯·霍尔特比', number='10', position='中场', age='30', height='176', weight='0', birthday='1990-09-18', habit_foot='左脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='提尔希斯多兰', number='39', position='前锋', age='19', height='170', weight='0', birthday='2001-12-28', habit_foot='右脚'}, FootballPlayer{id='null', team_id='36', team_name='布莱克本', name='山姆·加拉格尔', number='9', position='前锋', age='25', height='193', weight='0', birthday='1995-09-15', habit_foot='右脚'}], trainer=[FootballTrainer{id='null', name='Tony Mowbray', position='主教练'}]}
FootballTeam{id=604f7af6a0eaf9ea4bfb2447, info=FootballTeamInfo{id='null', name_cn='卢顿', name_en='Luton Town', league='英冠', city='', players='32'}, players=[FootballPlayer{id='null', team_id='135', team_name='卢顿', name='布里', number='26', position='后卫', age='23', height='178', weight='74', birthday='1997-12-11', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='加洛维', number='23', position='后卫', age='24', height='186', weight='0', birthday='1996-03-17', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='迪尤斯伯里-哈尔', number='22', position='中场', age='22', height='178', weight='0', birthday='1998-09-06', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='因斯', number='39', position='前锋', age='29', height='178', weight='0', birthday='1992-01-30', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='西蒙·斯拉格', number='12', position='守门员', age='27', height='191', weight='84', birthday='1993-03-17', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='汤姆·洛克', number='15', position='后卫', age='26', height='184', weight='75', birthday='1994-12-03', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='乔·莫雷尔', number='28', position='中场', age='24', height='185', weight='81', birthday='1997-01-03', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='詹姆斯·科林斯', number='19', position='前锋', age='30', height='188', weight='86', birthday='1990-12-01', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='迪昂·佩雷拉', number='30', position='前锋', age='21', height='175', weight='0', birthday='1999-03-25', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='阿德巴约', number='29', position='前锋', age='23', height='193', weight='0', birthday='1998-01-07', habit_foot=''}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='', number='1', position='守门员', age='29', height='188', weight='76', birthday='1991-06-16', habit_foot=''}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='索尼·布拉德利', number='5', position='后卫', age='29', height='193', weight='90', birthday='1991-09-13', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='格伦雷', number='16', position='中场', age='26', height='184', weight='73', birthday='1994-09-03', habit_foot=''}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='丹.波茨', number='3', position='后卫', age='26', height='173', weight='0', birthday='1994-04-13', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='马蒂.皮尔森', number='6', position='后卫', age='27', height='190', weight='72', birthday='1993-08-03', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='Pelly-Ruddock Mpanzu', number='17', position='中场', age='26', height='175', weight='0', birthday='1994-03-22', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='伯里', number='8', position='中场', age='28', height='177', weight='72', birthday='1992-07-12', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='卡泽格·卢阿卢阿', number='25', position='前锋', age='30', height='180', weight='76', birthday='1990-12-10', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='科尔尼克', number='7', position='前锋', age='25', height='180', weight='84', birthday='1995-04-09', habit_foot=''}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='希尔顿', number='9', position='前锋', age='32', height='183', weight='71', birthday='1989-02-25', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='乔治·蒙库尔', number='14', position='中场', age='27', height='175', weight='64', birthday='1993-08-18', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='克拉克', number='18', position='前锋', age='27', height='183', weight='73', birthday='1993-09-22', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='山姆·诺姆比', number='27', position='前锋', age='22', height='180', weight='0', birthday='1998-10-22', habit_foot=''}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='E.凯恩', number='32', position='中场', age='30', height='168', weight='84', birthday='1990-07-10', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='卡尔·奈史密斯', number='24', position='前锋', age='29', height='186', weight='78', birthday='1992-02-18', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='顿尼克利夫', number='4', position='中场', age='28', height='183', weight='0', birthday='1992-12-30', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='TQ Addy', number='-', position='前锋', age='19', height='0', weight='0', birthday='2002-02-01', habit_foot=''}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='Tiernan Parker', number='31', position='守门员', age='19', height='185', weight='0', birthday='2001-08-04', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='马丁·克拉尼', number='2', position='后卫', age='34', height='183', weight='0', birthday='1986-09-26', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='科里黑豹', number='35', position='后卫', age='20', height='186', weight='0', birthday='2000-10-19', habit_foot='左脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='杰克·佩克', number='34', position='中场', age='21', height='180', weight='0', birthday='2000-01-09', habit_foot='右脚'}, FootballPlayer{id='null', team_id='135', team_name='卢顿', name='Jack Chambers', number='-', position='中场', age='20', height='173', weight='0', birthday='2000-07-12', habit_foot=''}], trainer=[FootballTrainer{id='null', name='Nathan Jones', position='主教练'}]}

count: 2, time: 2.831000 seconds

参考:
1、QuickStart
2、QuickTour

MongoTemplate的bulkOps方法是同步的,因为它返回BulkOperations对象,BulkOperations是一个同步的操作类。BulkOperations的execute()方法会阻塞当前线程,直到所有的操作执行完毕。因此,如果需要异步执行MongoDB的批量操作,可以使用MongoDB异步操作API,或者使用Java的CompletableFuture等工具类来实现异步操作。以下是一个使用CompletableFuture异步执行MongoDB批量操作示例代码: ``` import java.util.List; import java.util.concurrent.CompletableFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.BulkOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private MongoTemplate mongoTemplate; public CompletableFuture<Void> batchUpdateUsers(List<User> users) { CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { BulkOperations bulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, User.class); for (User user : users) { Query query = new Query(Criteria.where("id").is(user.getId())); Update update = new Update().set("name", user.getName()).set("age", user.getAge()); bulkOps.updateOne(query, update); } bulkOps.execute(); }); return future; } } ``` 在这个示例代码中,我们使用了CompletableFuture.runAsync方法来异步执行MongoDB批量更新操作。在这个方法中,我们首先使用mongoTemplate的bulkOps方法创建BulkOperations对象,然后使用BulkOperations对象执行批量更新操作。返回的CompletableFuture对象可以用于异步等待异步操作的结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值