C# 使用字典生成$或查询<;字符串,列表<;字符串>&燃气轮机;

C# 使用字典生成$或查询<;字符串,列表<;字符串>&燃气轮机;,c#,mongodb,linq,mongodb-query,C#,Mongodb,Linq,Mongodb Query,我在这里挣扎。我对在mongo做任何稍微复杂的事情都是新手 在mongo中提供以下文件: { Id = 1, SharedId = "K1", Tag = "V1" } { Id = 2, SharedId = "K1", Tag = "V2" } { Id = 3, SharedId = "K1", Tag = "V3" } { Id = 4, SharedId = "K2", Tag = "V1" } { Id = 5, SharedId = "K2", Tag = "V2" } { Id

我在这里挣扎。我对在mongo做任何稍微复杂的事情都是新手

在mongo中提供以下文件:

{ Id = 1, SharedId = "K1", Tag = "V1" }
{ Id = 2, SharedId = "K1", Tag = "V2" }
{ Id = 3, SharedId = "K1", Tag = "V3" }
{ Id = 4, SharedId = "K2", Tag = "V1" }
{ Id = 5, SharedId = "K2", Tag = "V2" }
{ Id = 6, SharedId = "K2", Tag = "V3" }
我有一个方法
GetRecords(Dictionary docs)
,该方法的键是
SharedId
,该列表包含
标记的列表。例如:

[
    { "K1", [ "V1", , "V3" ] },
    { "K2", [ "V2", "V3" ] }
]
我想摘录以下记录:

1, 3, 5, 6
我当前的方法是这样的

GetRecords(Dictionary<string, List<string>> docs)
{
    var filter = Builders<Dto>.Filter.Where(d =>
        !string.IsNullOrEmpty(d.SharedId) &&
        docs.Keys.Contains(d.SharedId))
}
GetRecords(字典文档)
{
var filter=Builders.filter.Where(d=>
!string.IsNullOrEmpty(d.SharedId)&&
docs.key.Contains(d.SharedId))
}

如果我试图用我正在使用的东西做得更进一步,mongo会抛出许多错误,通常是
不受支持的
等等。类似于
文档[d.SharedId]。任何(I=>docs.Contains(I))
都会让mongodriver非常不安。

如果你指的是这样的结构,从你问题中的符号来看有点不清楚(显示序列化JSON表单):

或者像这样:

[
  { "K1": [ "V1", "V3" ] },
  { "K2": [ "V2", "V3" ] }
]
using MongoDB.Bson;
using MongoDB.Driver;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
  class Program
  {
    static void Main(string[] args)
    {
      MainAsync().Wait();
    }

    static async Task MainAsync()
    {
      var client = new MongoClient();
      var db = client.GetDatabase("test");
      var entities = db.GetCollection<Entity>("entities");

      try
      {
        /*
         * Meaning a serialized structure like:
         * { "K1": [ "V1", "V2" ], "K2": [ "V2", "V3" ] } 
         */
        Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>
        {
          { "K1", new List<string> { "V1", "V3" } },
          { "K2", new List<string> { "V2", "V3" } }
        };

        string output = JsonConvert.SerializeObject(dict);
        Console.WriteLine(output);

        /*
         *  Meaning a serialized structure like:
         *  [
         *    { "K1": [ "V1", "V2" ] },
         *    { "K2": [ "V2", "V3" ] }
         *  ]
         */
        List<Dictionary<string, List<string>>> alt = new List<Dictionary<string, List<string>>>
        {
          {  new Dictionary<string, List<string>> { { "K1", new List<string> {  "V1", "V3" } } } },
          {  new Dictionary<string, List<string>> { { "K2", new List<string> {  "V2", "V3" } } } },
        };

        string output2 = JsonConvert.SerializeObject(alt);
        Console.WriteLine(output2);

        // Build query from 'dict' form
        List<FilterDefinition<Entity>> orConditions = new List<FilterDefinition<Entity>>();
        foreach (KeyValuePair<string, List<string>> entry in dict)
        {
          orConditions.Add(
            Builders<Entity>.Filter.Eq(p => p.SharedId, entry.Key) &
            Builders<Entity>.Filter.Where(p => entry.Value.Contains(p.Tag))
          );
        };
        var query1 = Builders<Entity>.Filter.Or(orConditions);
        /*
         * Builds -
          {
            "$or" : [
                {
                  "SharedId" : "K1",
                  "Tag" : { "$in" : [ "V1", "V3" ] }
                },
                {
                  "SharedId" : "K2",
                  "Tag" : { "$in" : [ "V2", "V3" ] }
                }
            ]
          }
        */
        Console.WriteLine("Output 1");
        var cursor1 = await entities.Find(query1).ToListAsync();
        foreach (var doc in cursor1)
        {
          Console.WriteLine(doc.ToBsonDocument());
        }

        // Build the query from 'alt' form
        orConditions = new List<FilterDefinition<Entity>>(); // clear the list

        foreach(var item in alt)
        {
          foreach(KeyValuePair<string,List<string>> entry in item)
          {
            orConditions.Add(
              Builders<Entity>.Filter.Eq(p => p.SharedId, entry.Key) &
              Builders<Entity>.Filter.Where(p => entry.Value.Contains(p.Tag))
            );
          }
        }

        var query2 = Builders<Entity>.Filter.Or(orConditions);

        /* Serializes just the same */
        Console.WriteLine("Output 2");
        var cursor2 = await entities.Find(query2).ToListAsync();
        foreach (var doc in cursor2)
        {
          Console.WriteLine(doc.ToBsonDocument());
        }


      }
      catch (Exception ex)
      {
        Console.WriteLine(ex);
      }

    }
  }

  public class Entity
  {
    public int id;
    public string SharedId { get; set; }
    public string Tag { get; set; }
  }
}
无论哪种方式,基本上都是迭代单数字典的键/值对,或者对“字典列表”进行几乎相同的迭代

最终结果意味着从以下任一初始形式构造一个如下查询:

      {
        "$or" : [
            {
              "SharedId" : "K1",
              "Tag" : { "$in" : [ "V1", "V3" ] }
            },
            {
              "SharedId" : "K2",
              "Tag" : { "$in" : [ "V2", "V3" ] }
            }
        ]
      }
实现这一点的基本方法是使用
foreach
迭代并创建
FilterDefinition
列表,然后将其提供给
Builders.Filter.Or

示例清单包含如下代码:

[
  { "K1": [ "V1", "V3" ] },
  { "K2": [ "V2", "V3" ] }
]
using MongoDB.Bson;
using MongoDB.Driver;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
  class Program
  {
    static void Main(string[] args)
    {
      MainAsync().Wait();
    }

    static async Task MainAsync()
    {
      var client = new MongoClient();
      var db = client.GetDatabase("test");
      var entities = db.GetCollection<Entity>("entities");

      try
      {
        /*
         * Meaning a serialized structure like:
         * { "K1": [ "V1", "V2" ], "K2": [ "V2", "V3" ] } 
         */
        Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>
        {
          { "K1", new List<string> { "V1", "V3" } },
          { "K2", new List<string> { "V2", "V3" } }
        };

        string output = JsonConvert.SerializeObject(dict);
        Console.WriteLine(output);

        /*
         *  Meaning a serialized structure like:
         *  [
         *    { "K1": [ "V1", "V2" ] },
         *    { "K2": [ "V2", "V3" ] }
         *  ]
         */
        List<Dictionary<string, List<string>>> alt = new List<Dictionary<string, List<string>>>
        {
          {  new Dictionary<string, List<string>> { { "K1", new List<string> {  "V1", "V3" } } } },
          {  new Dictionary<string, List<string>> { { "K2", new List<string> {  "V2", "V3" } } } },
        };

        string output2 = JsonConvert.SerializeObject(alt);
        Console.WriteLine(output2);

        // Build query from 'dict' form
        List<FilterDefinition<Entity>> orConditions = new List<FilterDefinition<Entity>>();
        foreach (KeyValuePair<string, List<string>> entry in dict)
        {
          orConditions.Add(
            Builders<Entity>.Filter.Eq(p => p.SharedId, entry.Key) &
            Builders<Entity>.Filter.Where(p => entry.Value.Contains(p.Tag))
          );
        };
        var query1 = Builders<Entity>.Filter.Or(orConditions);
        /*
         * Builds -
          {
            "$or" : [
                {
                  "SharedId" : "K1",
                  "Tag" : { "$in" : [ "V1", "V3" ] }
                },
                {
                  "SharedId" : "K2",
                  "Tag" : { "$in" : [ "V2", "V3" ] }
                }
            ]
          }
        */
        Console.WriteLine("Output 1");
        var cursor1 = await entities.Find(query1).ToListAsync();
        foreach (var doc in cursor1)
        {
          Console.WriteLine(doc.ToBsonDocument());
        }

        // Build the query from 'alt' form
        orConditions = new List<FilterDefinition<Entity>>(); // clear the list

        foreach(var item in alt)
        {
          foreach(KeyValuePair<string,List<string>> entry in item)
          {
            orConditions.Add(
              Builders<Entity>.Filter.Eq(p => p.SharedId, entry.Key) &
              Builders<Entity>.Filter.Where(p => entry.Value.Contains(p.Tag))
            );
          }
        }

        var query2 = Builders<Entity>.Filter.Or(orConditions);

        /* Serializes just the same */
        Console.WriteLine("Output 2");
        var cursor2 = await entities.Find(query2).ToListAsync();
        foreach (var doc in cursor2)
        {
          Console.WriteLine(doc.ToBsonDocument());
        }


      }
      catch (Exception ex)
      {
        Console.WriteLine(ex);
      }

    }
  }

  public class Entity
  {
    public int id;
    public string SharedId { get; set; }
    public string Tag { get; set; }
  }
}

alt表单不是我需要的东西,很抱歉让它变得不清楚。如果我想返回相反的结果呢?因此,我不想返回
1、3、5和6
,而是希望查询返回不匹配的内容,所以文档
2和4
?它只是
在哪里(p=>!entry.Value.Contains(p.Tag))