最近特殊原因,需要查询表数据,分别两张表,结构大概如下:
public partial class ItemRelationPO : DbExtField
{
///
/// 道具ID 唯一
///
[BsonId]
[BsonElement("ItemOid")]
public ulong ItemOid { get; set; }
///
/// 父节点
///
public ulong Parent { get; set; }
///
/// 所有者ID
///
public ulong Owner { get; set; }
///
/// 关联字段
///
public ulong Associated { get; set; }
///
/// 祖先节点
///
// public string AncestorsStr { get; set; }
}
public partial class GameItemPO : DbExtField
{
///
/// 组件ID
///
[BsonId]
[BsonElement("ItemOid")]
public ulong ItemOid { get; set; }
///
/// 模板ID
///
public long TemplateId { get; set; }
///
/// 数量
///
public long Count { get; set; }
///
/// NFT 信息
///
public NftInfoPO NftInfo { get; set; }
///
/// 是否是容器
///
public bool IsContainer { get; set; }
///
/// 容器容量
///
public long Capacity { get; set; }
///
/// CD 信息
///
public ItemCDlInfoPO CdInfo { get; set; }
///
/// 道具失效时间----
///
[BsonRepresentation(BsonType.String)]
public DateTimeOffset ExpireEndTime { get; set; } = DateTimeOffset.MinValue;
}
两张表数据大概在1000W,我需要查询两张表数据,
方式1:分别两次查询,然后拼接
Stopwatch stopwatch = Stopwatch.StartNew();
var relationFilter = Builders.Filter.In(a => a.Owner, playerIds);
var data = await ItemRelationDb.Find(relationFilter).ToListAsync();
var ids = data.Select(a => a.ItemOid).ToList();
var filter = Builders.Filter.In(o => o.ItemOid, ids);
var listItems = await GameItemDb.Find(filter).ToListAsync();
//拼接成大类
var result = ItemRepositoryUtility.ConvertPOToDomain(listItems, _mapper, data);
stopwatch.Stop();
_logger.LogInformation("原始查询:{ml}", stopwatch.ElapsedMilliseconds);
方式2:使用管道查询
stopwatch.Restart();
var playerIdsBson = playerIds.Select(id => new BsonInt64((long)id)).ToList();
_logger.LogInformation("Player IDs Bson: " + string.Join(", ", playerIdsBson));
var relationFilter2 = Builders.Filter.In(a => (long)a.Owner, playerIdsBson);
_logger.LogInformation("Filter: " + relationFilter2.ToBsonDocument().ToJson());
var filterBson = new BsonDocument
{
{ "Owner", new BsonDocument { { "$in", new BsonArray(playerIdsBson) } } }
};
var pipeline = new BsonDocument[]
{
new("$match", filterBson),
new ("$lookup",new BsonDocument{
{ "from", GameItemDb.CollectionNamespace.CollectionName },
{ "localField", "_id" },
{ "foreignField", "_id" },
{ "as", "gameItems" }
}),
new("$unwind", "$gameItems"),
new BsonDocument("$project", new BsonDocument
{
{ "_id", 0 },
{ "ItemOid", 1 },
{ "Parent", 1 },
{ "Owner", 1 },
{ "Associated", 1 },
//{"item","$gameItems" }
{ "TemplateId", "$gameItems.TemplateId" },
{ "Count", "$gameItems.Count" },
{ "NftInfo", "$gameItems.NftInfo" },
// { "Types","$gameItems._t"}
})
};
var result2 = await ItemRelationDb.Aggregate(pipeline)
.ToListAsync();
测试结果:发现,两次访问所需时间比使用管道查询性能要高