如何在Firestore中查询集合并将文档汇总为“每天”,“每周”?

时间:2020-08-26 13:49:01

标签: javascript google-cloud-firestore nosql-aggregation

我的目标是将文档聚合到per dayper week中。

存储在Firestore中的文档模板。

document = {
  iat: new Date() // Wed Aug 26 2020 HH:MM:SS GMT+... (... Time),
  bill: PropTypes.number,
}

预期输出是

data = {
  labels: [
            08/26/2020,
            08/27/2020,
            ...
          ],
  datasets: [
    ...
    data: [
            bill1 + bill2,
            bill3 + bill4 + bill5,
            bill6,
            bill7 + bill8
          ],
  ],
}

我尝试过的。输出是每个文档。

firebase
  .firestore()
  .collection("tickets")
  .orderBy("exp")
  .get()
  .then((snapshot) => {
    if (!snapshot.empty) {

      setData({
        labels: snapshot.docs.map((doc) => {
          const data = doc.data();
          const exp = data.exp ? new Date(data.exp.seconds * 1000 + data.exp.milliseconds).toString().split(" ").slice(1, 5).join(" ") : null;

          return exp;
        }),
        datasets: [
          {
            data: snapshot.docs.map((doc) => {
              const data = doc.data();
              const bill = data.bill ? data.bill : null;

              return bill;
            }),
          },
        ],
      });

tl:dr

我看到的问题是,每天(或每小时)将iat键合并成一个键更容易。虽然很难根据bill键的合并来合并iat键。

我现在能想到的是使用嵌套逻辑来解决它,我想如果您有更简单的解决方案,那将是一个神秘的问题。

找到解决方案后,我会在一个小时后回来。

非常感谢。

1 个答案:

答案 0 :(得分:0)

这是我的解决方案,一个神秘的解决方案。

// explaining how dataReduced works.
// acc / accumulator intially does not hold value.
// Therefore, on the first iteration acc[key] = acc[key] returns undefined so we fill it with a value { bill: 0, ...cur }.
// accumulator value is remembered across iteration.
// For comparison, in for loop statement, accumulator is similar to `let i = 0; for (i = 0; condition, execution);`
console.log(
  dataDateEqualized.reduce((acc, { bill, ...cur }) => {
    console.log("acc ", acc, " bill ", bill, " cur ", cur);
    const key = Object.entries(cur).join();

    console.log("acc ", acc, " key ", key, " before ", acc[key]);
    acc[key] = acc[key] || { bill: 0, ...cur };

    console.log("acc ", acc, " after ", acc[key], " bill ", bill);
    return (acc[key].bill += bill); // this is intentional
  }, {})
);
      firebase
        .firestore()
        .collection("tickets")
        .orderBy("exp")
        .get()
        .then((snapshot) => {
          if (!snapshot.empty) {
            const data = snapshot.docs.map((doc) => {
              return doc.data();
            });

            // console.log(data);

            const dataDateEqualized = data.map((data) => {
              const date = new Date(
                new Date(data.exp.seconds * 1000).setHours(0, 0, 0, 0)
              );
              const bill = data.bill;

              return { "exp": date, bill };
            });

            // console.log(dataDateEqualized);

            const dataReduced = Object.values(
              dataDateEqualized.reduce((acc, { bill, ...r }) => {
                const key = Object.entries(r).join("-");
                acc[key] = acc[key] || { ...r, bill: 0 };
                return (acc[key].bill += bill, acc);
              }, {})
            );

            // console.log(dataReduced);

            // console.log(dataReduced.map(data => data.exp.toString().split(" ").slice(1, 4).join(" ")))

            setData({
              labels: dataReduced.map(data => data.exp.toString().split(" ").slice(1, 4).join(" ")),
              datasets: [
                {
                  label: "Revenue Report",
                  fill: false,
                  lineTension: 0.1,
                  backgroundColor: "rgba(75,192,192,0.4)",
                  borderColor: "rgba(75,192,192,1)",
                  borderCapStyle: "butt",
                  borderDash: [],
                  borderDashOffset: 0.0,
                  borderJoinStyle: "miter",
                  pointBorderColor: "rgba(75,192,192,1)",
                  pointBackgroundColor: "#fff",
                  pointBorderWidth: 1,
                  pointHoverRadius: 5,
                  pointHoverBackgroundColor: "rgba(75,192,192,1)",
                  pointHoverBorderColor: "rgba(220,220,220,1)",
                  pointHoverBorderWidth: 2,
                  pointRadius: 1,
                  pointHitRadius: 10,
                  data: dataReduced.map(data => data.bill),
                }
              ]
            })

          } else if (snapshot.empty) setData();
        })
        .catch((error) => setError(error.message));