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

问题描述

我的目标是将文档聚合到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键。

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

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

非常感谢。

解决方法

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

// 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 "," key ",key," before ",acc[key]);
    acc[key] = acc[key] || { bill: 0,...cur };

    console.log("acc "," after ",acc[key],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)
              );
              const bill = data.bill;

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

            // console.log(dataDateEqualized);

            const dataReduced = Object.values(
              dataDateEqualized.reduce((acc,...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,0.4)",borderColor: "rgba(75,1)",borderCapStyle: "butt",borderDash: [],borderDashOffset: 0.0,borderJoinStyle: "miter",pointBorderColor: "rgba(75,pointBackgroundColor: "#fff",pointBorderWidth: 1,pointHoverRadius: 5,pointHoverBackgroundColor: "rgba(75,pointHoverBorderColor: "rgba(220,220,pointHoverBorderWidth: 2,pointRadius: 1,pointHitRadius: 10,data: dataReduced.map(data => data.bill),}
              ]
            })

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