简体   繁体   中英

Get mongodb documents with certain fields(projections) using Spring-Integration (annotations only)

I am trying to get all documents from a mongodb collection which were modfied in last 5 minutes with certain fields only (say field1, field2, field3 and so on). How to write a LiteralExpression to get specific fields (projections)?

My current Literal Expression return documents containing all fields (_id is timestamp of document creation in my collection):

public String getLiteralExpression(){
        long innerBoundary = Instant.now().minus(5, ChronoUnit.MINUTES).toEpochMilli();
        long outerBoundary = Instant.now().toEpochMilli();
        String expression = new StringBuilder()
                .append("{'_id': {'$gt': ")
                .append(innerBoundary)
                .append(", '$lt' : ")
                .append(outerBoundary)
                .append("}}")
                .toString();
        return expression;
    }
}

Which is being invoked in InboundChannelAdapter as

@Bean
@InboundChannelAdapter(value = "pubSubChannel", poller = @Poller(fixedRate = "30000"))
public MessageSource<Object> DbReadingMessageSource() {

    Expression expression = new SpelExpressionParser().parseExpression("@myBean.getLiteralExpression()");

    MongoDbMessageSource messageSource = new MongoDbMessageSource(mongoTemplate, expression);
    messageSource.setCollectionNameExpression(new LiteralExpression(mongoTemplate.getCollectionName(MyEntity.class)));
    IntegrationFlows.from(messageSource);
    return messageSource;
}

Is there a way where I can just use MongoTemplate or MongoDbFactory instead of a LiteralExpression to fetch only certain fields (projection) in form of MongoDbMessageSource or any other format which can be fed to my pubsubChannel pipeline.

It's a fact that the expression as a second MongoDbMessageSource argument can be resolved to the org.springframework.data.mongodb.core.query.Query object. So, it might not be just a plain literal expression . For your projection use-case you may write something like:

new BasicQuery([QUERY_STRING], [FIELD_STRING])

to be returned from your @myBean.getLiteralExpression() .

That Query API is pretty flexible and provides a lot of fluent hooks to be configured for the final MongoDB query. For example it has a fields() for include/exclude callbacks for specific fields you would like to be returned.

More info about Query API in the Spring Data MongoDB manual: https://docs.spring.io/spring-data/mongodb/docs/2.1.5.RELEASE/reference/html/#mongodb-template-query

If you would like to use MongoTemplate directly instead, you need to write a custom code which should be called from the MethodInvokingMessageSource wrapper with the same @InboundChannelAdapter configuration. In that code you still need to build such a Query object to be able to delegate to the MongoTemplate.find() . That is exactly what is done in the MongoDbMessageSource .

Out of question: your DbReadingMessageSource() configuration is slightly wrong. You can't call IntegrationFlows.from(messageSource); from that bean definition. The MongoDbMessageSource must be configured as a separate @Bean and already without @InboundChannelAdapter annotation. The IntegrationFlow has to be another @Bean and there you really can use your DbReadingMessageSource() from that from() . But again: without @InboundChannelAdapter . See Reference Manual: https://docs.spring.io/spring-integration/docs/current/reference/html/#java-dsl-inbound-adapters

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM