使用 C# 驱动程序通过 Elemmatch 查询 MongoDB
Query MongoDB with Elemmatch using C# driver
我在将查询(相对简单)从 Mongo Shell 转换为 C#(可以是 linq 或过滤器构建器)时遇到问题。
我想通过某些字段(在我的示例中 EntityId
和 ActivityDate
)和数组中存在的字段(在我的示例中 UnCommonFields
)进行查询。
数据示例:
{
"_id" : ObjectId("5ded105e90424e1c0e6fda05"),
"EntryId" : NumberLong(1111111),
"EntityId" : "10000007",
"EntityType" : NumberInt(5),
"ActivityItemId" : "1,4,16172532",
"ActivityDate" : ISODate("2015-04-13T03:50:55.000-0400"),
"CreateDate" : ISODate("2017-12-13T19:07:07.757-0500"),
"UpdateDate" : ISODate("2017-12-13T19:07:07.757-0500"),
"ActivityItemStatus" : NumberInt(2),
"ActivityTypeId" : NumberInt(2),
"Currency" : "USD",
"Amount" : "-10.7800",
"ActivityItemDescription" : "Whosebug example",
"DisplayLevel" : NumberInt(10),
"UnCommonFields" : [
{
"k" : "CardPresent",
"v" : NumberLong(2)
},
{
"k" : "PreAuthDate",
"v" : ISODate("2015-04-11T08:47:05.000-0400")
},
{
"k" : "TransactionDate",
"v" : ISODate("2015-04-13T03:50:55.000-0400")
},
{
"k" : "ActivityItemStatus",
"v" : NumberLong(2)
},
{
"k" : "MerchantName",
"v" : "Whosebug POS"
},
{
"k" : "TerminalCity",
"v" : "TLV"
},
{
"k" : "TerminalState",
"v" : "IL"
},
{
"k" : "TerminalCountry",
"v" : "IL"
},
{
"k" : "Fee",
"v" : 0.0
},
{
"k" : "IsDecline",
"v" : false
},
{
"k" : "BillingAmount",
"v" : -10.78
},
{
"k" : "BillingCurrency",
"v" : "USD"
},
{
"k" : "ForeignAmount",
"v" : -10.78
},
{
"k" : "ForeignCurrency",
"v" : "USD"
},
{
"k" : "FxRate",
"v" : 1.0
},
{
"k" : "MaskedCardNumber",
"v" : "530000XXXXXX6699"
}
]
}
我想在 Mongo shell 上编写的查询如下所示:
db.getCollection("ActivityWriterTest").find(
{$and:
[
{EntityId:"10000007"},
{ ActivityDate: { $gte: ISODate("2015-04-12T03:50:55.000"), $lte: ISODate("2015-04-14T03:50:55.000") } },
{UnCommonFields : { $elemMatch : {"k" : "ForeignAmount", "v" : {$in: [-10.78, -15.85] } }}}
]
})
这是我在 C# 代码中编写的部分:它包含两个第一个过滤器并且按预期工作
_activityContext.ActivityData.Find(x => x.EntityId == accountHolderId && x.ActivityDate >= requestDetails.FromDate && x.ActivityDate <= requestDetails.ToDate)
我尝试以多种方式实现 elemmactch,但没有成功..
知道如何将 elemmatch 翻译和集成为查询的一部分吗?
我使用Mongo数据库驱动2.10
您没有展示您的 C# class 的外观,但我假设您使用 System.Object
作为 UnCommonFields.v
,因为那里有不同类型的值。
要构建 $elemMatch 查询,您需要使用来自 MongDB C# 驱动程序的 Builders<T>.Filter
类型。假设Model
代表你的实体,Uncommonfield
代表嵌套对象,你可以运行下面查询:
var query = Builders<Model>.Filter.And(
Builders<Model>.Filter.Eq(x => x.EntityId, accountHolderId),
Builders<Model>.Filter.Gte(x => x.ActivityDate, requestDetails.FromDate),
Builders<Model>.Filter.Lte(x => x.ActivityDate, requestDetails.ToDate),
Builders<Model>.Filter.ElemMatch(x => x.UnCommonFields,
Builders<Uncommonfield>.Filter.And(
Builders<Uncommonfield>.Filter.Eq(x => x.k, "ForeignAmount"),
Builders<Uncommonfield>.Filter.In(f => f.v, new object[]{ -10.78, -15.85 })
)
)
);
var doc = _mongoDBCollection.Find(query).First();
LINQ 版本:
var q = from doc in _mongoDBCollection.AsQueryable()
where doc.EntityId == accountHolderId
where doc.ActivityDate >= requestDetails.FromDate
where doc.ActivityDate <= requestDetails.ToDate
where doc.UnCommonFields.Any(x => x.k == "ForeignAmount" && new object[] { -10.78, -15.85 }.Contains(x.v))
select doc;
我在将查询(相对简单)从 Mongo Shell 转换为 C#(可以是 linq 或过滤器构建器)时遇到问题。
我想通过某些字段(在我的示例中 EntityId
和 ActivityDate
)和数组中存在的字段(在我的示例中 UnCommonFields
)进行查询。
数据示例:
{
"_id" : ObjectId("5ded105e90424e1c0e6fda05"),
"EntryId" : NumberLong(1111111),
"EntityId" : "10000007",
"EntityType" : NumberInt(5),
"ActivityItemId" : "1,4,16172532",
"ActivityDate" : ISODate("2015-04-13T03:50:55.000-0400"),
"CreateDate" : ISODate("2017-12-13T19:07:07.757-0500"),
"UpdateDate" : ISODate("2017-12-13T19:07:07.757-0500"),
"ActivityItemStatus" : NumberInt(2),
"ActivityTypeId" : NumberInt(2),
"Currency" : "USD",
"Amount" : "-10.7800",
"ActivityItemDescription" : "Whosebug example",
"DisplayLevel" : NumberInt(10),
"UnCommonFields" : [
{
"k" : "CardPresent",
"v" : NumberLong(2)
},
{
"k" : "PreAuthDate",
"v" : ISODate("2015-04-11T08:47:05.000-0400")
},
{
"k" : "TransactionDate",
"v" : ISODate("2015-04-13T03:50:55.000-0400")
},
{
"k" : "ActivityItemStatus",
"v" : NumberLong(2)
},
{
"k" : "MerchantName",
"v" : "Whosebug POS"
},
{
"k" : "TerminalCity",
"v" : "TLV"
},
{
"k" : "TerminalState",
"v" : "IL"
},
{
"k" : "TerminalCountry",
"v" : "IL"
},
{
"k" : "Fee",
"v" : 0.0
},
{
"k" : "IsDecline",
"v" : false
},
{
"k" : "BillingAmount",
"v" : -10.78
},
{
"k" : "BillingCurrency",
"v" : "USD"
},
{
"k" : "ForeignAmount",
"v" : -10.78
},
{
"k" : "ForeignCurrency",
"v" : "USD"
},
{
"k" : "FxRate",
"v" : 1.0
},
{
"k" : "MaskedCardNumber",
"v" : "530000XXXXXX6699"
}
]
}
我想在 Mongo shell 上编写的查询如下所示:
db.getCollection("ActivityWriterTest").find(
{$and:
[
{EntityId:"10000007"},
{ ActivityDate: { $gte: ISODate("2015-04-12T03:50:55.000"), $lte: ISODate("2015-04-14T03:50:55.000") } },
{UnCommonFields : { $elemMatch : {"k" : "ForeignAmount", "v" : {$in: [-10.78, -15.85] } }}}
]
})
这是我在 C# 代码中编写的部分:它包含两个第一个过滤器并且按预期工作
_activityContext.ActivityData.Find(x => x.EntityId == accountHolderId && x.ActivityDate >= requestDetails.FromDate && x.ActivityDate <= requestDetails.ToDate)
我尝试以多种方式实现 elemmactch,但没有成功.. 知道如何将 elemmatch 翻译和集成为查询的一部分吗?
我使用Mongo数据库驱动2.10
您没有展示您的 C# class 的外观,但我假设您使用 System.Object
作为 UnCommonFields.v
,因为那里有不同类型的值。
要构建 $elemMatch 查询,您需要使用来自 MongDB C# 驱动程序的 Builders<T>.Filter
类型。假设Model
代表你的实体,Uncommonfield
代表嵌套对象,你可以运行下面查询:
var query = Builders<Model>.Filter.And(
Builders<Model>.Filter.Eq(x => x.EntityId, accountHolderId),
Builders<Model>.Filter.Gte(x => x.ActivityDate, requestDetails.FromDate),
Builders<Model>.Filter.Lte(x => x.ActivityDate, requestDetails.ToDate),
Builders<Model>.Filter.ElemMatch(x => x.UnCommonFields,
Builders<Uncommonfield>.Filter.And(
Builders<Uncommonfield>.Filter.Eq(x => x.k, "ForeignAmount"),
Builders<Uncommonfield>.Filter.In(f => f.v, new object[]{ -10.78, -15.85 })
)
)
);
var doc = _mongoDBCollection.Find(query).First();
LINQ 版本:
var q = from doc in _mongoDBCollection.AsQueryable()
where doc.EntityId == accountHolderId
where doc.ActivityDate >= requestDetails.FromDate
where doc.ActivityDate <= requestDetails.ToDate
where doc.UnCommonFields.Any(x => x.k == "ForeignAmount" && new object[] { -10.78, -15.85 }.Contains(x.v))
select doc;