|
53 | 53 | object-value) |
54 | 54 | :else (list {:key1 key1 :key2 "" :value object-value}))) |
55 | 55 |
|
56 | | -(defn flatten-array-value [item end_time] |
57 | | - (map |
58 | | - #(assoc % :end_time end_time) |
59 | | - (cond |
60 | | - (map? item) (mapcat (fn [[key1 val]] (flatten-value-object (name key1) val)) item) |
61 | | - :else (list {:key1 "" :key2 "" :value item})))) |
| 56 | +(defn flatten-array-value |
| 57 | + "Flattens a single values array entry into key1/key2/value rows. |
| 58 | + Supports both old format (value is a map) and new Facebook API breakdown |
| 59 | + format where breakdown fields are siblings of value and end_time." |
| 60 | + ([item end_time] |
| 61 | + (flatten-array-value item end_time {})) |
| 62 | + ([item end_time breakdown-fields] |
| 63 | + (map |
| 64 | + #(merge % {:end_time end_time} breakdown-fields) |
| 65 | + (cond |
| 66 | + (map? item) (mapcat (fn [[key1 val]] (flatten-value-object (name key1) val)) item) |
| 67 | + :else (list {:key1 (or (first (vals breakdown-fields)) "") |
| 68 | + :key2 (if (> (count breakdown-fields) 1) |
| 69 | + (second (vals breakdown-fields)) |
| 70 | + "") |
| 71 | + :value item}))))) |
62 | 72 |
|
63 | 73 | (def ads-action-stats-types #{:actions :properties :conversion_values |
64 | 74 | :action_values :canvas_component_avg_pct_view |
|
73 | 83 |
|
74 | 84 | (def serialized-lists-types #{:issues_info :frequency_control_specs}) |
75 | 85 |
|
| 86 | +(defn extract-breakdown-fields |
| 87 | + "Extracts breakdown fields from a values array entry. |
| 88 | + Breakdown fields are any fields that are not :value or :end_time. |
| 89 | + Returns a map of breakdown field names (as strings) to their values." |
| 90 | + [entry] |
| 91 | + (let [known-keys #{:value :end_time}] |
| 92 | + (into {} (keep (fn [[k v]] |
| 93 | + (when-not (known-keys k) |
| 94 | + [(name k) (str v)])) |
| 95 | + entry)))) |
| 96 | + |
76 | 97 | (defn flatten-array |
77 | 98 | "flattens array of object with same structure prefixing its keys with array-name |
78 | 99 | returns list of key-value pairs" |
79 | 100 | [array array-name] |
80 | 101 | (cond (= array-name :values) |
81 | | - (mapcat #(flatten-array-value (:value %) (:end_time %)) array) |
| 102 | + (mapcat #(let [breakdowns (extract-breakdown-fields %) |
| 103 | + breakdown-keys (sort (keys breakdowns)) |
| 104 | + key1 (if (seq breakdown-keys) (get breakdowns (first breakdown-keys)) nil) |
| 105 | + key2 (if (> (count breakdown-keys) 1) (get breakdowns (second breakdown-keys)) nil) |
| 106 | + breakdown-map (cond-> {} |
| 107 | + key1 (assoc :key1 key1) |
| 108 | + key2 (assoc :key2 key2))] |
| 109 | + (flatten-array-value (:value %) (:end_time %) breakdown-map)) array) |
82 | 110 | (some? (ads-action-stats-types array-name)) |
83 | 111 | (map #(assoc % :ads_action_name (name array-name)) array) |
84 | 112 | (some? (serialized-lists-types array-name)) |
|
0 commit comments