Random documents from MongoDB using spring-data

后端 未结 2 808
萌比男神i
萌比男神i 2021-01-13 13:18

I\'m able to do it by using this mongodb native query:

db.books.aggregate(
   [ { $sample: { size: 15 } } ]
)

But how to do it in spr

相关标签:
2条回答
  • 2021-01-13 13:34

    Blakes Seven answered it correctly, however, I want to offer a nicer implementation of AggregationOperation, which follows standard Spring implementation

    import com.mongodb.BasicDBObject;
    import com.mongodb.DBObject;
    import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
    import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.util.Assert;
    
    public class SampleOperation implements AggregationOperation  {
    
        private int size;
    
        public SampleOperation(int size) {
            Assert.isTrue(size > 0, " Size must be positive!");
            this.size = size;
        }
    
        public AggregationOperation setSize(int size) {
            Assert.isTrue(size > 0, " Size must be positive!");
            this.size = size;
            return this;
        }
    
        @Override
        public DBObject toDBObject(AggregationOperationContext context) {
            return new BasicDBObject("$sample", context.getMappedObject(Criteria.where("size").is(size).getCriteriaObject()));
        }
    
    }
    

    After that, you can create SampleOperation object with constructor, or later change the size of it by setSize() method, and apply it to aggregate() function as normal.

    Update: In SpringBoot 2.0.0+ and Spring Framework 5.0: Spring Mongo drop DBObject and replace by org.bson.Document therefore the last past should be updated as:

        @Override
    public Document toDocument(AggregationOperationContext aggregationOperationContext) {
        return new Document("$sample", aggregationOperationContext.getMappedObject(Criteria.where("size").is(size).getCriteriaObject()));
    

    }

    And remove the @Override toDBObject

    0 讨论(0)
  • 2021-01-13 13:56

    Update:

    Starting with v2.0 of Spring Data you can do this:

    SampleOperation matchStage = Aggregation.sample(5);
    Aggregation aggregation = Aggregation.newAggregation(sampleStage);
    AggregationResults<OutType> output = mongoTemplate.aggregate(aggregation, "collectionName", OutType.class);
    

    Original answer:

    Abstraction layers like spring-mongo are always going to lag way behind server released features. So you are best off contructing the BSON document structure for the pipeline stage yourself.

    Implement in a custom class:

    public class CustomAggregationOperation implements AggregationOperation {
        private DBObject operation;
    
        public CustomAggregationOperation (DBObject operation) {
            this.operation = operation;
        }
    
        @Override
        public DBObject toDBObject(AggregationOperationContext context) {
            return context.getMappedObject(operation);
        }
    }
    

    And then use in your code:

    Aggregation aggregation = newAggregation(
        new CutomAggregationOperation(
            new BasicDBObject(
                "$sample",
                new BasicDBObject( "size", 15 )
            )
        )
    );
    

    Since this implements AggregationOperation this works well with the exising pipeline operation helper methods. i.e:

    Aggregation aggregation = newAggregation(
        // custom pipeline stage
        new CutomAggregationOperation(
            new BasicDBObject(
                "$sample",
                new BasicDBObject( "size", 15 )
            )
        ),
        // Standard match pipeline stage
        match(
            Criteria.where("myDate")
                .gte(new Date(new Long("949384052490")))
                .lte(new Date(new Long("1448257684431")))
        )
    );
    

    So again, everything is just a BSON Object at the end of the day. It's just a matter of having an interface wrapper so that the class methods in spring-mongo interpret the result and get your defined BSON Object correctly.

    0 讨论(0)
提交回复
热议问题