0
votes

Le filtre conditionnel récupère un objet partiel

comment récupérer un objet partiel?

       {
            Id:123,
            Name:"david",
            Languages:null
       }
        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();
                }
            }

si j'appelle la fonction get (123, "cn") j'espère obtenir:

XXX

au lieu de null.

comment corriger la requête pour répondre à ma demande?


1 commentaires

Dans votre exemple, qu'est-ce que cn? Avez-vous besoin que la sortie soit limitée à ce que vous souhaitez afficher uniquement à des fins d'affichage?


3 Réponses :


0
votes

Je pense que cela fera le travail:

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 };
}


1 commentaires

L'identifiant est juste un fichier pour l'exemple, j'ai plus de champs dont j'ai besoin de db



0
votes

Si vous souhaitez afficher les langues uniquement lorsqu'elles correspondent (et nulles si aucune ne correspond), essayez ce qui suit

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;
}

Vous obtiendrez l'objet que vous souhaitez en fonction de l'ID .. puis plus loin, il ne retournera que les langues qui correspondent à la langue que vous passez (nulle ou non).


0 commentaires

0
votes

Cela fonctionne. Je ne sais pas ce que vous entendez par "au lieu de null".

Une chose mineure, que vous ne voudriez pas inclure Languges , à la place vous avez projeté le Languages ​​ à une plage de tableau avec le [-1] . Il s'agit donc simplement de retourner le dernier élément du tableau. Le code final est:

> db.ItemWithLanguages.find ()

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

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

...

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


0 commentaires