我应该在C#中使用MongoDb的哪个过滤器定义?

时间:2018-03-07 18:01:01

标签: c# asp.net mongodb asp.net-core mongodb-.net-driver

想象一下这种情况:

我有一个名为过滤器的实体,其中包含:

string Text { get; set; } string State { get; set; }

所以在我的Mongo系列中我有这些文件(过滤器):

{
"id" : "1",
"State" : "333",
"Text" : "SD"
},
{
"id" : "2",
"State" : "444",
"Text" : "X"
}

现在我有一项服务,它应该返回所有文本和状态匹配的文件。

想象一下,我的服务会收到IEnumerable<string> textsIEnumerable<string> states这个值:

"states" : ["333","444"],
"texts" : ["SD"]

该服务应该返回[],因为没有州&#34; 333&#34; 州&#34; 444&#34的过滤器; 同时使用文字&#34; SD&#34; 。如果我的收藏有这些文件,它只会返回结果:

{
"id" : "1",
"State" : "333",
"Text" : "SD"
},
{
"id" : "2",
"State" : "444",
"Text" : "SD"
}

然后回复是:

{
"id" : "1",
"State" : "333",
"Text" : "SD"
},
{
"id" : "2",
"State" : "444",
"Text" : "SD"
}

我为这种情况创建过滤器定义的实际代码是:

    private FilterDefinition<MyFilterEntity> CreateFilterForMyFilterEntity(IEnumerable<string> texts, IEnumerable<string> states)
    {
        var filterBuilder = Builders<MyFilterEntity>.Filter;
        var filter = filterBuilder.Empty;

        if (ListNotNullOrEmpty(texts))
        {
            filter = filter & filterBuilder.In(rf => rf.Text, texts);
        }

        if (ListNotNullOrEmpty(states))
        {
            filter = filter & filterBuilder.In(rf => rf.State, states);
        }

        return filter;
    }

但是对于我的示例,此代码返回响应:

{
"id" : "1",
"State" : "333",
"Text" : "SD"
}

如前所述,应该是[]

有没有办法解决这种情况?谢谢。

我正在使用ASP.NET Core 2.0和MongoDb.Driver 2.5.0。

1 个答案:

答案 0 :(得分:1)

您可以指定预期过滤器的列表,然后使用$or查询,如下所示,在返回结果之前,您需要检查预期过滤器的长度是否与返回结果的长度具有相同的值。

在MongoShell中,您的查询可能如下所示:

db.Filter.find(
  {
     $or: [
       { State: "333", Text: "SD" },
       { State: "444", Text: "SD" }
     ]
   }
 )

你的C#逻辑可能如下所示:

var states = new[] { "333", "444" };
var texts = new[] { "SD" };
var expectedNumberOfResults = states.Length * texts.Length;

IEnumerable<FilterClass> result;
var filters = from state in states
              from text in texts
              select Builders<FilterClass>.Filter.Where(f => f.Text == text && f.State == state);

FilterDefinition<FilterClass> q = Builders<FilterClass>.Filter.Or(filters);

var query = collection.Find(q);

if(query.Count() == expectedNumberOfResults)
{
    result = query.ToList();
}
else
{
    result = Enumerable.Empty<FilterClass>();
}