Skip to content

Commit

Permalink
Combine Objects describing Funnel Steps into one (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
winsmith authored Feb 23, 2023
1 parent 4cb1a6a commit 01b027d
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 35 deletions.
10 changes: 4 additions & 6 deletions Sources/DataTransferObjects/Query/CustomQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public struct CustomQuery: Codable, Hashable, Equatable {
limit: Int? = nil, context: QueryContext? = nil,
threshold: Int? = nil, metric: TopNMetricSpec? = nil,
dimension: DimensionSpec? = nil, dimensions: [DimensionSpec]? = nil,
steps: [Filter]? = nil, stepNames: [String]? = nil)
steps: [FunnelStep]? = nil)
{
self.queryType = queryType
self.compilationStatus = compilationStatus
Expand All @@ -42,7 +42,6 @@ public struct CustomQuery: Codable, Hashable, Equatable {
self.dimension = dimension
self.dimensions = dimensions
self.steps = steps
self.stepNames = stepNames
}

public init(queryType: CustomQuery.QueryType,
Expand All @@ -59,7 +58,7 @@ public struct CustomQuery: Codable, Hashable, Equatable {
limit: Int? = nil, context: QueryContext? = nil,
threshold: Int? = nil, metric: TopNMetricSpec? = nil,
dimension: DimensionSpec? = nil, dimensions: [DimensionSpec]? = nil,
steps: [Filter]? = nil, stepNames: [String]? = nil)
steps: [FunnelStep]? = nil)
{
self.queryType = queryType
self.compilationStatus = compilationStatus
Expand All @@ -81,7 +80,6 @@ public struct CustomQuery: Codable, Hashable, Equatable {
self.dimension = dimension
self.dimensions = dimensions
self.steps = steps
self.stepNames = stepNames
}

public enum QueryType: String, Codable, CaseIterable, Identifiable {
Expand Down Expand Up @@ -138,7 +136,7 @@ public struct CustomQuery: Codable, Hashable, Equatable {
public var dimensions: [DimensionSpec]?

/// Only for funnel Queries: A list of filters that form the steps of the funnel
public var steps: [Filter]?
public var steps: [FunnelStep]?

/// Only for funnel Queries: An optional List of names for the funnel steps
public var stepNames: [String]?
Expand Down Expand Up @@ -192,7 +190,7 @@ public struct CustomQuery: Codable, Hashable, Equatable {
self.dimension = try container.decodeIfPresent(DimensionSpec.self, forKey: CustomQuery.CodingKeys.dimension)
self.metric = try container.decodeIfPresent(TopNMetricSpec.self, forKey: CustomQuery.CodingKeys.metric)
self.dimensions = try container.decodeIfPresent([DimensionSpec].self, forKey: CustomQuery.CodingKeys.dimensions)
self.steps = try container.decodeIfPresent([Filter].self, forKey: CustomQuery.CodingKeys.steps)
self.steps = try container.decodeIfPresent([FunnelStep].self, forKey: CustomQuery.CodingKeys.steps)
self.stepNames = try container.decodeIfPresent([String].self, forKey: CustomQuery.CodingKeys.stepNames)

if let intervals = try? container.decode(QueryTimeIntervalsContainer.self, forKey: CustomQuery.CodingKeys.intervals) {
Expand Down
11 changes: 11 additions & 0 deletions Sources/DataTransferObjects/Query/FunnelStep.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Foundation

public struct FunnelStep: Codable, Hashable, Equatable {
public init(filter: Filter? = nil, name: String) {
self.filter = filter
self.name = name
}

public let filter: Filter?
public let name: String
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ extension CustomQuery {
var query = self

guard let steps = steps else { throw QueryGenerationError.keyMissing(reason: "Missing key 'steps'") }
let stepNames = stepNames ?? []

let stepFilters = steps.compactMap({ $0.filter })
let stepNames = steps.compactMap({ $0.name })

// Generate Filter Statement
let stepsFilters = Filter.or(.init(fields: steps))
let stepsFilters = Filter.or(.init(fields: stepFilters))
let queryFilter = filter && stepsFilters

// Generate Aggregations
let aggregationNamePrefix = "_funnel_step_"
var aggregations = [Aggregator]()
for (index, step) in steps.enumerated() {
for (index, step) in stepFilters.enumerated() {
aggregations.append(.filtered(.init(
filter: step,
aggregator: .thetaSketch(.init(
Expand Down
14 changes: 8 additions & 6 deletions Tests/QueryGenerationTests/CompileDownTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ final class CompileDownTests: XCTestCase {
let appID2 = UUID()

func testFunnel() throws {
let steps: [Filter] = [
.selector(.init(dimension: "type", value: "appLaunchedRegularly")),
.selector(.init(dimension: "type", value: "dataEntered")),
.selector(.init(dimension: "type", value: "paywallSeen")),
.selector(.init(dimension: "type", value: "conversion"))


let steps: [FunnelStep] = [
.init(filter: .selector(.init(dimension: "type", value: "appLaunchedRegularly")), name: "Regular Launch"),
.init(filter: .selector(.init(dimension: "type", value: "dataEntered")), name: "Data Entered"),
.init(filter: .selector(.init(dimension: "type", value: "paywallSeen")), name: "Paywall Presented"),
.init(filter: .selector(.init(dimension: "type", value: "conversion")), name: "Conversion"),
]

let query = CustomQuery(queryType: .funnel, relativeIntervals: relativeIntervals, granularity: .all, steps: steps)

let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false)
Expand Down
25 changes: 9 additions & 16 deletions Tests/QueryGenerationTests/FunnelQueryGenerationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,13 @@
import XCTest

final class FunnelQueryGenerationTests: XCTestCase {
let steps: [Filter] = [
.selector(.init(dimension: "type", value: "appLaunchedRegularly")),
.selector(.init(dimension: "type", value: "dataEntered")),
.selector(.init(dimension: "type", value: "paywallSeen")),
.selector(.init(dimension: "type", value: "conversion"))
let steps: [FunnelStep] = [
.init(filter: .selector(.init(dimension: "type", value: "appLaunchedRegularly")), name: "Regular Launch"),
.init(filter: .selector(.init(dimension: "type", value: "dataEntered")), name: "Data Entered"),
.init(filter: .selector(.init(dimension: "type", value: "paywallSeen")), name: "Paywall Presented"),
.init(filter: .selector(.init(dimension: "type", value: "conversion")), name: "Conversion"),
]

let stepNames: [String] = [
"Regular Launch",
"Data Entered",
"Paywall Presented",
"Conversion"
]


let tinyQuery = CustomQuery(
queryType: .groupBy,
dataSource: "telemetry-signals",
Expand Down Expand Up @@ -142,7 +135,7 @@ final class FunnelQueryGenerationTests: XCTestCase {
)

func testExample() throws {
let startingQuery = CustomQuery(queryType: .funnel, granularity: .all, steps: steps, stepNames: stepNames)
let startingQuery = CustomQuery(queryType: .funnel, granularity: .all, steps: steps)
let generatedTinyQuery = try startingQuery.precompiledFunnelQuery()

XCTAssertEqual(tinyQuery.filter, generatedTinyQuery.filter)
Expand All @@ -153,7 +146,7 @@ final class FunnelQueryGenerationTests: XCTestCase {
func testWithAdditionalFilters() throws {
let additionalFilter = Filter.selector(.init(dimension: "something", value: "other"))

let startingQuery = CustomQuery(queryType: .funnel, filter: additionalFilter, granularity: .all, steps: steps, stepNames: stepNames)
let startingQuery = CustomQuery(queryType: .funnel, filter: additionalFilter, granularity: .all, steps: steps)
let generatedTinyQuery = try startingQuery.precompiledFunnelQuery()

let expectedFilter = Filter.and(.init(fields: [
Expand All @@ -179,7 +172,7 @@ final class FunnelQueryGenerationTests: XCTestCase {
)
]

let startingQuery = CustomQuery(queryType: .funnel, relativeIntervals: relativeTimeIntervals, granularity: .all, steps: steps, stepNames: stepNames)
let startingQuery = CustomQuery(queryType: .funnel, relativeIntervals: relativeTimeIntervals, granularity: .all, steps: steps)
let generatedTinyQuery = try startingQuery.precompiledFunnelQuery()

XCTAssertEqual(startingQuery.relativeIntervals, generatedTinyQuery.relativeIntervals)
Expand Down
7 changes: 3 additions & 4 deletions Tests/QueryTests/CustomQueryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,9 @@ final class CustomQueryTests: XCTestCase {
queryType: .funnel,
granularity: .all,
steps: [
.selector(.init(dimension: "something", value: "one")),
.selector(.init(dimension: "other", value: "two")),
],
stepNames: ["Step One", "Step Two"]
.init(filter: .selector(.init(dimension: "something", value: "one")), name: "Step One"),
.init(filter: .selector(.init(dimension: "other", value: "two")), name: "Step Twp"),
]
)
}
}

0 comments on commit 01b027d

Please sign in to comment.