【问题标题】:How to get aggregated data in moor_flutter?如何在 moor_flutter 中获取聚合数据?
【发布时间】:2021-06-15 17:58:52
【问题描述】:

假设我有 2 个简单的表 UsersOrders

  • Users 有列 Id

  • Orders 具有列 IdUserId

如何使用moor_flutter轻松获取用户的所有订单并将其作为以下模型的流返回?

class UserModel {
  final String id;
  final List<OrderModel> orderModels;

  UserModel(this.id, this.orders);
}

class OrderModel {
  final String id;

  OrderModel(this.id);
}

This 是官方文档,但并未涵盖此用例。

EFCore 和 C# 的等效调用是:

public async Task<IEnumerable<UserModel>> GetUserOrders(String userId)
{
    return await _db.Users
        .Include(user  => user.Orders)
        .Where(user => user.Id == userId)
        .Select(user => new UserModel
        {
            Id = user.Id,
            OrderModels = user.Orders.Select(order => new OrderModel
            {
                Id = null,
            }).ToList()
        })
    .ToListAsync();
}

【问题讨论】:

    标签: flutter dart flutter-moor


    【解决方案1】:

    我最近遇到了same problem。根据文档中给定的示例,我对使用联接感到困惑。

    我所做的是:

    创建的类(仅在数据库文件中。参见下面的示例)有两个您要加入(组合)的对象。我在一类数据库中编写了查询。

    通过例子你会得到更好的理解:

    @UseMoor(
      tables: [OfflineProductMasters, OfflineProductWiseStocks],
    )
    class MyDatabase extends _$MyDatabase {
      // we tell the database where to store the data with this constructor
      MyDatabase() : super(_openConnection());
    
      // you should bump this number whenever you change or add a table definition. Migrations
      // are covered later in this readme.
    
      @override
      int get schemaVersion => 1;
    
      Future<List<ProductWithStock>> getProductWiseStock(String searchString, int mappingOfflineSalesTypeId) async {
        try {
          final rows = await (select(offlineProductMasters).join([innerJoin(offlineProductWiseStocks, offlineProductMasters.itemId.equalsExp(offlineProductWiseStocks.itemId))])
            ..where(offlineProductWiseStocks.salesTypeId.equals(mappingOfflineSalesTypeId) & offlineProductMasters.productName.like('$searchString%'))
            ..limit(50)
          ).get();
          return rows.map((row) {
            return ProductWithStock(
              row.readTable(offlineProductMasters),
              row.readTableOrNull(offlineProductWiseStocks),
            );
          }).toList();
        }catch(exception){
          print(exception);
          return Future.value([]);
        }
      }
    }
    
    class ProductWithStock {
      final OfflineProductMaster offlineProductMaster;
    
      final OfflineProductWiseStock? productWithStock;
    
      ProductWithStock(this.offlineProductMaster, this.productWithStock);
    }
    

    现在您已经了解了如何使用此类查询的结构。希望你会这样写你的查询。

    不知道你解决了没有。如果解决了,请发布答案,以便其他人获得帮助。

    谢谢。

    【讨论】:

    • 我最终做的事情是相似的。您的代码是想法的一部分,但没有直接回答我的问题。我会添加一个答案。
    【解决方案2】:

    这感觉像是一个 hacky 解决方法,但我最终做的是我创建了两个名为 HabitWithLogsHabitModel 的类。我将查询结果放入HabitWithLogs 实例中,然后将它们分组到HabitModel 实例中。

    数据类:

    class HabitWithLog {
      final Habit habit;
      final HabitLog? habitLog;
    
      HabitWithLog({required this.habit, required this.habitLog}) : assert(habitLog == null || habitLog.habitId == habit.id);
    }
    
    class HabitModel {
      final Habit habit;
      final List<HabitLog> habitLogs;
    
      HabitModel({required this.habit, required this.habitLogs});
    }
    

    道法:

    Future<List<HabitModel>> getAllHabits() async {
      // Get habits and order
      final query0 = (_db.select(_db.habits)..orderBy([(t) => OrderingTerm(expression: t.order, mode: OrderingMode.asc)]));
    
      // Join with habit logs
      final query1 = query0.join([
        leftOuterJoin(_db.habitLogs, _db.habitLogs.habitId.equalsExp(_db.habits.id)),
      ]);
    
      // Naive way that return the same habit multiple times
      final hwlList = query1.map((rows) => HabitWithLog(
            habit: rows.readTable(_db.habits),
            habitLog: rows.readTableOrNull(_db.habitLogs),
          ));
    
      // Group hwlList by habits
      final groups = (await hwlList.get()).groupListsBy((hwl) => hwl.habit);
    
      // Map grouping
      return groups.entries
          .map((group) => HabitModel(
                habit: group.key,
                habitLogs: (group.value[0].habitLog == null) ? List<HabitLog>.empty() : group.value.map((hwl) => hwl.habitLog!).toList(),
              ))
          .toList();
    }
    

    映射流感觉很糟糕,不应该是实现这一点的唯一方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-08
      • 2017-12-29
      • 2020-03-13
      • 2017-10-10
      • 2021-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多