簡體   English   中英

條件過濾器檢索部分對象

[英]Conditional filter retrieve partial object

如何檢索部分對象?

  {
    Id:123,
    Name:"david",
    Languages:[{b:"en"},{b:"ru"}]
  }
        public async Task<myObj> Get(long id, string lang=null)
            {
                FilterDefinition<myObj> filter = Builders<myObj>.Filter.Eq(s => s.Id, id) 
                                                   & Builders<myObj>.Filter.ElemMatch(l => l.Languages, s => s.b== lang);

                ProjectionDefinition<myObj> projection = Builders<Symptom>.Projection
                                          .Include(d => d.Id)
                                          .Include(d => d.Name)
                                          .Include(d => d.Languages[-1]);

                FindOptions<myObj> options = new FindOptions<myObj> { Projection = projection };
                using (IAsyncCursor<myObj> cursor = await db.Collection.FindAsync(filter, options))
                {
                    return cursor.SingleOrDefault();
                }
            }

如果我調用函數 get(123,"cn") 我希望得到:

       {
            Id:123,
            Name:"david",
            Languages:null
       }

而不是空。

如何修復查詢以滿足我的需求?

我認為這將完成工作:

public async Task<myObj> Get(long id, string lang = null)
{
    var res = await db.Collection.AsQueryable()
                                 .Where(m =>
                                        m.Id == id &&
                                        m.Languages.Any(l => l.b == lang))
                                 .SingleOrDefaultAsync();

    return res ?? new myObj { _Id = id, Languages = null };
}

如果您只想在匹配時顯示語言(如果沒有匹配則為 null),請嘗試以下操作

public async Task<myObj> Get(long id, string lang = null)
{
    FilterDefinition<myObj> filter = Builders<myObj>.Filter.Eq(s => s.Id, id) 
    var result = await collection.Find(filter).SingleOrDefaultAsync();
    if (result != null)
        result.Languages = result.Languages?.Where(lng => lng.b.Equals(lang)).ToList();
    return result;
}

您將根據 ID 獲得您想要的對象。然后它將僅返回與您傳遞的語言(空或其他)匹配的那些語言。

它正在工作。 我不知道你所說的“而不是空”是什么意思。

一個次要的事情,你想包括Languges ,而不是你投影Languages對數組范圍與[-1] 所以它只是返回數組的最后一個元素。 最后的代碼是:

> db.ItemWithLanguages.find()

{ "_id" : ObjectId("5dfb57c9692d22eefa6e0cfe"), "Id" : 123, "Name": "david", "Languages" : [ { "B" : "en" }, { "B" : "cn" } ] }

internal class MyObj
{
    public long Id { get; set; }

    [BsonId]
    [BsonElement("_id")]
    public ObjectId MyId { get; set; }

    public string Name { get; set; }

    public List<Language> Languages { get; set; }
}

internal class Language
{
    public string B { get; set; }
}

public static async Task<MyObj> Get(IMongoCollection<MyObj> collection, long id, string lang = null)
{
    FilterDefinition<MyObj> filter = Builders<MyObj>.Filter.Eq(s => s.Id, id)
                                     & Builders<MyObj>.Filter.ElemMatch(l => l.Languages, s => s.B == lang);

    // excluding d.Languages by not including it.
    // it makes Languages = null.
    ProjectionDefinition<MyObj> projection = Builders<MyObj>.Projection
        .Include(d => d.Id)
        .Include(d => d.Name);

    FindOptions<MyObj> options = new FindOptions<MyObj> { Projection = projection };
    using (IAsyncCursor<MyObj> cursor = await collection.FindAsync(filter, options))
    {
        return cursor.SingleOrDefault();
    }
}

...

string connectionString = "mongodb://localhost:27017";
var client = new MongoClient(connectionString);

var db = client.GetDatabase("test");
var myObjs = db.GetCollection<MyObj>("ItemWithLanguages");
MyObj ret;
Task.Run(async () => { ret = await Get(myObjs, 123, "cn"); }).ConfigureAwait(false).GetAwaiter()
    .GetResult();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM