Случайный документ в mongodb с использованием весенней загрузки [дубликат]

Многие многочисленные дубликаты этого вопроса задают вопрос о влиянии округления с плавающей запятой на конкретные числа. На практике легче понять, как это работает, глядя на точные результаты вычислений, а не просто на чтение. Некоторые языки предоставляют способы сделать это - например, преобразование float или double в BigDecimal в Java.

Так как это вопрос, связанный с языком, ему нужны языковые агностические инструменты, такие как как Десятичный преобразование с плавающей запятой .

Применяя его к числам в вопросе, рассматриваемым как удваивает:

0,1 преобразуется в 0,1000000000000000055511151231257827021181583404541015625,

0,2 преобразуется в 0.200000000000000011102230246251565404236316680908203125,

0,3 конвертируется в 0,29999999999999999989897769753748434595763683319091796875 и

0,30000000000000004 преобразуется в 0,3000000000000000444089209850062616169452667236328125.

Добавление первых двух чисел вручную или в десятичный калькулятор, такой как Full Precision Calculator , показывает точную сумму фактических входов: 0.3000000000000000166533453693773481063544750213623046875.

Если округлить до эквивалента 0,3, ошибка округления будет 0.0000000000000000277555756156289135105907917022705078125. Округление до эквивалента 0,30000000000000004 также дает ошибку округления 0,0000000000000000277555756156289135105907917022705078125.

Возвращаясь к конвертеру с плавающей запятой, необработанный шестнадцатеричный показатель для 0.30000000000000004 равен 3fd3333333333334, который заканчивается четной цифрой и, следовательно, является правильным результатом.

4
задан dit 13 March 2016 в 23:34
поделиться

2 ответа

Обновление:

Начиная с v2.0 данных Spring, вы можете сделать это:

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

Оригинальный ответ:

Уровни абстракции как spring-mongo, всегда будут отставать от выпущенных функций сервера. Таким образом, вам лучше всего самостоятельно структурировать структуру документа BSON для этапа конвейера.

Реализовать в пользовательском классе:

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);
    }
}

И затем использовать в своем коде:

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

Так как это реализует AggregationOperation, это хорошо работает с вспомогательными методами вывода операций. 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")))
    )
);

Итак, все это просто объект BSON в конце дня. Это всего лишь вопрос об использовании оболочки интерфейса, чтобы методы класса в Spring-Mongo интерпретировали результат и правильно определили ваш BSON-объект.

6
ответ дан dnickless 25 August 2018 в 22:49
поделиться

Blakes Seven ответил на это правильно, однако я хочу предложить более эффективную реализацию AggregationOperation, которая следует за стандартной реализацией Spring

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()));
    }

}

. После этого вы можете создать объект SampleOperation с помощью конструктора или позже изменить размер его с помощью метода setSize() и применить его к функции aggregate() как обычно.

Обновление: в SpringBoot 2.0.0+ и Spring Framework 5.0: Spring Mongo drop DBObject и заменить на org.bson.Document, поэтому последнее прошлое должно обновляться как:

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

}

И удалить @Override toDBObject

2
ответ дан V.Tran 25 August 2018 в 22:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: