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?
3 Réponses :
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 };
}
L'identifiant est juste un fichier pour l'exemple, j'ai plus de champs dont j'ai besoin de db
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).
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();
}
}
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?