简体   繁体   中英

Query MongoDB with Elemmatch using C# driver

I'm having trouble translating a query (relatively simple) from Mongo Shell to C# (can be linq or filter builder). I want to query by some field(in my example EntityId and ActivityDate ) and by fields that exist on array(in my example UnCommonFields ).

Example of data:

{ 
    "_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" : "Stackoverflow 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" : "StackOverflow 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"
        }
    ]
}

The query that I want to write look like this on 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] } }}}
      ]
   })

This is the part that I wrote on my C# code: It's include two first filter and it's work as expected

_activityContext.ActivityData.Find(x => x.EntityId == accountHolderId && x.ActivityDate >= requestDetails.FromDate && x.ActivityDate <= requestDetails.ToDate)

I try to implement the elemmactch in several way, but not success.. Any idea how I can translate and integrate the elemmatch as part of my query?

I use MongoDB driver 2.10

You haven't shown how your C# class looks but I assume you're using System.Object for UnCommonFields.v since you have values of different types there.

To build $elemMatch query you need to use Builders<T>.Filter type from MongDB C# driver. Assuming Model represents your entity and Uncommonfield represents nested objects, you can run below query:

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 version:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM