如何获取 moor_flutter 中的聚合数据?

How to get aggregated data in moor_flutter?

假设我有 2 个简单的表 UsersOrders:

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

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();
}

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

我所做的是:

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

你会通过例子加深理解:

@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);
}

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

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

谢谢。

这感觉像是一个 hacky 解决方法,但我最终做的是我创建了 2 个 类,分别称为 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();
}

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