简体   繁体   中英

Use LINQ in C# to find MondoDB records when values in a list field match a criteria value from a list

I want to use LINQ to return all records in a MongoDB collection where the field in the record is a list of strings and any string in the list matches any string value in a list of strings used as the search criteria:

Mongo Record in Collection ("Item"):

{
    "_id": ...,
    "StringList": [
        "string1",
        "string2",
        "string3"
    ],
    ...
}

Search Criteria:

var criteria = new List<string> { "string2", "string4" };

My Code:

var foundItems = iMongoDataProvider.FindAll<Item>()
                           .Where(x =>x.StringList.ContainsAny(criteria)).ToList();

Based on the above, the Mongo record should be returned since one of the StringList values matches one of the values in the search criteria . Nothing is returned even though I can manually peruse the collection and find the matching record. What am I doing wrong? Can someone provide an example that will do what I need? Thanks!

have you tried somethinglike:

using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System.Linq;
using System.Linq.Expressions;

var foundItems = _collection.FindAll(x=> criteria.Any(cc=> xx.StringList.Contains(cc))).ToList();

Where _collection is IMongoCollection<TEntity> _collection

What you are looking for is ElemMatch Filter ( https://docs.mongodb.com/v3.2/reference/operator/query/elemMatch/ ) :

var foundItems = collection.Find(Builders<Item>.Filter.ElemMatch(
                     x => x.StringList,
                     s=>criteria.Contains(s)));

where collection is your IMongoCollection<Item> I see, that you are using FindAll , that means, that your MongoDb driver is of the version 1.x (see here more about it: FindAll in MongoDB .NET Driver 2.0 ) I would suggest to update your driver, because this version isnot uptodate. Or are the any important reason don't to do it?

This filter query on server. Sure you could get your data as IEnumerable and filter it locally:

var foundItems = collection.Find(x=>true)
                   .ToEnumerable()
                   .Where(x => x.StringList.Intersect(criteria).Any());

If your data is not so huge and you are fine with filtering on client it's a good way too.

And if you are doing already FindAll , that means you get get all the data, you could query it with intersect :

var foundItems = iMongoDataProvider.FindAll<Item>()
                           .Where(x => x.StringList.Intersect(criteria).Any());

What you want is to know if the intersection of the two lists has any values:

 .Where(x =>x.StringList.Intersect(criteria).Any())

I'm not sure what the problem is with your code but here is working code

void Main()
{
    List<string> []StringList = new List<string>[] {
             new List<string> {    "string1", "string2", "string3" },
             new List<string> {    "string11", "string12", "string13" },
             new List<string> {    "string21", "string22", "string4" }
    };

    var criteria = new List<string> { "string2", "string4" };

    var foundItems = StringList
                      .Where(x => x.Intersect(criteria).Any()).ToList();

    foundItems.Dump();
}

I tested this using LinqPad (which I recommend to anyone working in Linq and it is free).

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