最近特殊原因,需要查询表数据,分别两张表,结构大概如下:
public partial class ItemRelationPO : DbExtField
{
/// <summary>
/// 道具ID 唯一
/// </summary>
[BsonId]
[BsonElement("ItemOid")]
public ulong ItemOid { get; set; }
/// <summary>
/// 父节点
/// </summary>
public ulong Parent { get; set; }
/// <summary>
/// 所有者ID
/// </summary>
public ulong Owner { get; set; }
/// <summary>
/// 关联字段
/// </summary>
public ulong Associated { get; set; }
/// <summary>
/// 祖先节点
/// </summary>
// public string AncestorsStr { get; set; }
}
public partial class GameItemPO : DbExtField
{
/// <summary>
/// 组件ID
/// </summary>
[BsonId]
[BsonElement("ItemOid")]
public ulong ItemOid { get; set; }
/// <summary>
/// 模板ID
/// </summary>
public long TemplateId { get; set; }
/// <summary>
/// 数量
/// </summary>
public long Count { get; set; }
/// <summary>
/// NFT 信息
/// </summary>
public NftInfoPO NftInfo { get; set; }
/// <summary>
/// 是否是容器
/// </summary>
public bool IsContainer { get; set; }
/// <summary>
/// 容器容量
/// </summary>
public long Capacity { get; set; }
/// <summary>
/// CD 信息
/// </summary>
public ItemCDlInfoPO CdInfo { get; set; }
/// <summary>
/// 道具失效时间----
/// </summary>
[BsonRepresentation(BsonType.String)]
public DateTimeOffset ExpireEndTime { get; set; } = DateTimeOffset.MinValue;
}
两张表数据大概在1000W,我需要查询两张表数据,
方式1:分别两次查询,然后拼接
Stopwatch stopwatch = Stopwatch.StartNew();
var relationFilter = Builders<ItemRelationPO>.Filter.In(a => a.Owner, playerIds);
var data = await ItemRelationDb.Find(relationFilter).ToListAsync();
var ids = data.Select(a => a.ItemOid).ToList();
var filter = Builders<GameItemPO>.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<ItemRelationPO>.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<GameItem>(pipeline)
.ToListAsync();
测试结果:发现,两次访问所需时间比使用管道查询性能要高