web-dev-qa-db-fra.com

Requête MongoDB en utilisant 'ObjectId'

J'ai inséré documents dans MongoDB sans id. Et je veux les récupérer en cherchant dans leur MongoDB ObjectId , auquel on a attribué par défaut.

Voici ma tentative

var query_id = Query.EQ("_id", "50ed4e7d5baffd13a44d0153");
var entity = dbCollection.FindOne(query_id);
return entity.ToString();

Et j'obtiens l'erreur suivante-

Une exception de première chance du type 'System.NullReferenceException' s'est produite

Quel est le problème?

24
Mike Barnes

Vous devez créer une instance de ObjectId, puis interroger à l'aide de cette instance. Sinon, votre requête compare ObjectIds à une chaîne et ne parvient pas à trouver les documents correspondants.

Cela devrait fonctionner:

var query_id = Query.EQ("_id", ObjectId.Parse("50ed4e7d5baffd13a44d0153"));
var entity = dbCollection.FindOne(query_id);
return entity.ToString();
50
soulcheck

Dans C # pour le dernier officiel MongoDB.Driver write this-

var filter_id = Builders<MODEL_NAME>.Filter.Eq("id", ObjectId.Parse("50ed4e7d5baffd13a44d0153"));
var entity = dbCollection.Find(filter).FirstOrDefault();
return entity.ToString();

Nous pouvons obtenir le même résultat sans convertir id de chaîne en ObjectId. Mais ensuite, nous devrons ajouter l'attribut [BsonRepresentation(BsonType.ObjectId)] avant id dans la classe de modèle.

Le code peut même être encore simplifié en utilisant expression lambda -

var entity = dbCollection.Find(document => document.id == "50ed4e7d5baffd13a44d0153").FirstOrDefault();
return entity.ToString();
21
Minhas Kamal

Si vous êtes ici en 2018 et que vous souhaitez copier/coller un code qui fonctionne toujours ou une syntaxe de chaîne pure

    [Fact]
    public async Task QueryUsingObjectId()
    {
        var filter = Builders<CosmosParkingFactory>.Filter.Eq("_id", new ObjectId("5b57516fd16cb04bfc35fcc6"));
        var entity = stocksCollection.Find(filter);
        var stock = await entity.SingleOrDefaultAsync();
        Assert.NotNull(stock);

        var idString = "5b57516fd16cb04bfc35fcc6";
        var stringFilter = "{ _id: ObjectId('" + idString + "') }";
        var entityStringFiltered = stocksCollection.Find(stringFilter);
        var stockStringFiltered = await entityStringFiltered.SingleOrDefaultAsync();
        Assert.NotNull(stockStringFiltered);
    }
2
Kdog

La réponse sélectionnée est correcte. Pour les personnes confondues par Query.EQ, voici un autre moyen d'écrire une mise à jour de base (met à jour l'ensemble du document mongodb):

string mongoDocumentID = "123455666767778";
var query = new QueryDocument("_id", ObjectId.Parse(mongoDocumentID)); 
var update = new UpdateDocument { { "$set", documentToSave } };
mongoCollection.Update(query, update, UpdateFlags.Multi);

L'objet ObjectId est nécessaire lorsque vous souhaitez effectuer une recherche par ID d'objet, sinon il compare une chaîne à un type d'objet et ne correspondra pas. Mongo est très strict en ce sens, que le nom du champ soit correct ou non.

2
smakus

Vous pouvez aussi le faire de cette façon, sa 

public static ObjectId GetInternalId(string id)
    {
        if (!ObjectId.TryParse(id, out ObjectId internalId))
            internalId = ObjectId.Empty;

        return internalId;
    }

alors dans votre méthode, vous pouvez faire quelque chose comme ça

ObjectId internalId = GetMongoId.GetInternalId(id);
        return await YourContext.YourTable.Find(c => c.InternalId == internalId).FirstOrDefaultAsync();

Remarque: id param dans GetInternalId est un paramètre de cette méthode. Si vous avez besoin de cela:

public async Task<YourTable> Find(string id)
    {
        ObjectId internalId = GetMongoId.GetInternalId(id);
        return await YourContext.YourTable.Find(c => c.InternalId == internalId).FirstOrDefaultAsync();
    }

J'espère que ça aide aussi.

0
Raul Baez