---
# System prepended metadata

title: taimall patch script
tags: [airaRetail]

---

---
tags: airaRetail
---


```js
const HOUR = 3600000
const TIMEZONE_OFFSET = 8 * HOUR
const dateOf = (millis) => {
    const isoDateTime = (new Date(millis + TIMEZONE_OFFSET)).toISOString() // 1970-01-01T00:00:00.000Z
    const [ date ] = isoDateTime.split("T") // 1970-01-01
    return date.split("-").join("") // 19700101
}
const hourOf = (millis) => {
    const isoDateTime = (new Date(millis + TIMEZONE_OFFSET)).toISOString() // 1970-01-01T00:00:00.000Z
    const [ _, time ] = isoDateTime.split("T") // 00:00:00.000Z
    const [ hour ] = time.split(":") // 00
    return parseInt(hour) // 0 ~ 23
}
const START_TIME = 1711296000000 // 臺灣時間 2024-03-25 00:00:00
const END_TIME = 1715788800000 // 臺灣時間 2024-05-16 00:00:00
const DAY = 86400000
function* allDates() {
    let millis = START_TIME
    while (millis <= END_TIME - 1) {
        yield {
            startTime: millis,
            endTime: millis + DAY - 1,
        }
        millis += DAY
    }
}
const typeOf = (age) => {
    if (age < 25) return "Age-1"
    if (age >= 25 && age < 35) return "Age-2"
    if (age >= 35 && age < 50) return "Age-3"
    return "Age-4"
}
const SOURCE = "DemographicRow"
const count = (filter) => db[SOURCE].countDocuments(filter)
const load = (filter, skip, limit) => db[SOURCE].find(filter).skip(skip).limit(limit)
const addRecord = (stats, { timestamp: millis, uuid, deviceId, data_objects }) => {
    const hour = hourOf(millis)
    for (const { age } of data_objects) {
        if (!age) continue
        const type = typeOf(age)
        stats[uuid] = stats[uuid] || {}
        stats[uuid][deviceId] = stats[uuid][deviceId] || {}
        stats[uuid][deviceId][type] = stats[uuid][deviceId][type] || Array(24).fill(0)
        stats[uuid][deviceId][type][hour] += 1
    }
}
const DESTINATION = "DemographicMeta"
const save = (statId, $set) => db[DESTINATION].updateOne(statId, { $set }, { upsert: true })
const LIMIT = 2000
const main = () => {
    for (const { startTime, endTime } of allDates()) {
        const filter = {
            $and: [
                { timestamp: { $gte: startTime} },
                { timestamp: { $lte: endTime} },
            ]
        }
        const total = count(filter)
        console.log({ total })
        if (!total) continue
        const pages = Math.ceil(total / LIMIT)
        let page = 1
        const stats = {}
        const dateCode = dateOf(startTime)
        while (page <= pages) {
            console.log(`date ${dateCode}, page ${page}/${pages}`)
            const skip = (page - 1) * LIMIT
            const cursor = load(filter, skip, LIMIT)
            while (cursor.hasNext()) addRecord(stats, cursor.next())
            page += 1
        }
        for (const uuid in stats) { // uuid:"IN"|"OUT"
            for (const deviceId in stats[uuid]) { // uuid:"camera-1"
                for (const type in stats[uuid][deviceId]) { // type: "Age-1"
                    const statId = { dateCode, type, uuid, deviceId }
                    const $set = { ...statId, data: stats[uuid][deviceId][type] }
                    save(statId, $set)
                }
            }
        }
    }
}
main()
```

```
{
    $and: [
        {uuid: "IN"},
        {deviceId: "camera-1"},
      	{"data_objects.0.age": {$exists: true}},
      	{"data_objects.0.age": {$gte: 25}},
        {"data_objects.0.age": {$lt: 35}},
        {"datetime": /^2024\/5\/14/}
    ]
}
```


```json
{
  dateCode: {
    '$in': [
      '20240331', '20240401', '20240402',
      '20240403', '20240404', '20240405',
      '20240406', '20240407', '20240408',
      '20240409', '20240410', '20240411',
      '20240412', '20240413', '20240414',
      '20240415', '20240416', '20240417',
      '20240418', '20240419', '20240420',
      '20240421', '20240422', '20240423',
      '20240424', '20240425', '20240426',
      '20240427', '20240428', '20240429',
      '20240430'
    ]
  },
  uuid: { '$in': [ 'IN' ] }
}
```

```json
{
    datetime: /^2024\/5\/15/,
    "data_objects.0.age": {$lt: 25}
}
```