From 816c0cd6182b1f2cf552fc6ed47139ed7a973dac Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Mon, 10 Oct 2016 10:26:22 +0200 Subject: Support for generic aggregations. --- common/datastorequery.cpp | 66 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp index 8b14951..7b7d3a3 100644 --- a/common/datastorequery.cpp +++ b/common/datastorequery.cpp @@ -150,11 +150,47 @@ class Reduce : public FilterBase { public: typedef QSharedPointer Ptr; + struct Aggregator { + Query::Reduce::Aggregator::Operation operation; + QByteArray property; + QByteArray resultProperty; + + Aggregator(Query::Reduce::Aggregator::Operation o, const QByteArray &property_, const QByteArray &resultProperty_) + : operation(o), property(property_), resultProperty(resultProperty_) + { + + } + + void process() { + if (operation == Query::Reduce::Aggregator::Count) { + mResult = mResult.toInt() + 1; + } else { + Q_ASSERT(false); + } + } + + void process(const QVariant &value) { + if (operation == Query::Reduce::Aggregator::Collect) { + mResult = mResult.toList() << value; + } else { + Q_ASSERT(false); + } + } + + QVariant result() const + { + return mResult; + } + private: + QVariant mResult; + }; + QHash mAggregateValues; QSet mReducedValues; QByteArray mReductionProperty; QByteArray mSelectionProperty; Query::Reduce::Selector::Comparator mSelectionComparator; + QList mAggregators; Reduce(const QByteArray &reductionProperty, const QByteArray &selectionProperty, Query::Reduce::Selector::Comparator comparator, FilterBase::Ptr source, DataStoreQuery *store) : FilterBase(source, store), @@ -167,8 +203,7 @@ public: virtual ~Reduce(){} - static QByteArray getByteArray(const QVariant &value) - { + static QByteArray getByteArray(const QVariant &value) { if (value.type() == QVariant::DateTime) { return value.toDateTime().toString().toLatin1(); } @@ -178,8 +213,7 @@ public: return QByteArray(); } - static bool compare(const QVariant &left, const QVariant &right, Query::Reduce::Selector::Comparator comparator) - { + static bool compare(const QVariant &left, const QVariant &right, Query::Reduce::Selector::Comparator comparator) { if (comparator == Query::Reduce::Selector::Max) { return left > right; } @@ -196,8 +230,17 @@ public: QVariant selectionResultValue; QByteArray selectionResult; auto results = indexLookup(mReductionProperty, reductionValue); + + QVariantList list; for (const auto r : results) { readEntity(r, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { + for (auto &aggregator : mAggregators) { + if (!aggregator.property.isEmpty()) { + aggregator.process(getProperty(entityBuffer.entity(), aggregator.property)); + } else { + aggregator.process(); + } + } auto selectionValue = getProperty(entityBuffer.entity(), mSelectionProperty); if (!selectionResultValue.isValid() || compare(selectionValue, selectionResultValue, mSelectionComparator)) { selectionResultValue = selectionValue; @@ -205,10 +248,13 @@ public: } }); } - int count = results.size(); + + QMap aggregateValues; + for (auto &aggregator : mAggregators) { + aggregateValues.insert(aggregator.resultProperty, aggregator.result()); + } + readEntity(selectionResult, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { - QMap aggregateValues; - aggregateValues.insert("count", count); callback({uid, entityBuffer, Sink::Operation_Creation, aggregateValues}); foundValue = true; }); @@ -462,7 +508,11 @@ void DataStoreQuery::setupQuery() f->propertyFilter = filter->propertyFilter; baseSet = f; } else if (auto filter = stage.dynamicCast()) { - baseSet = Reduce::Ptr::create(filter->property, filter->selector.property, filter->selector.comparator, baseSet, this); + auto reduction = Reduce::Ptr::create(filter->property, filter->selector.property, filter->selector.comparator, baseSet, this); + for (const auto &aggregator : filter->aggregators) { + reduction->mAggregators << Reduce::Aggregator(aggregator.operation, aggregator.propertyToCollect, aggregator.resultProperty); + } + baseSet = reduction; } else if (auto filter = stage.dynamicCast()) { baseSet = Bloom::Ptr::create(filter->property, baseSet, this); } -- cgit v1.2.3