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

对着背影说爱祢 提交于 2021-01-28 08:47:03

问题


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!


回答1:


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




回答2:


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());



回答3:


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).



来源:https://stackoverflow.com/questions/41490392/use-linq-in-c-sharp-to-find-mondodb-records-when-values-in-a-list-field-match-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!