For example we have following document in elastic:
{
"name": "Bob",
"age": "22",
"phrase": "ohohoho",
"date": "2022-10-20T00:00:00Z"
}
string phrase ;
DateTime? date;
Then we want put following:
{
"name": "not Bob",
"age": "22",
"phrase": null,
"date": null
}
in c#:
var updateRequest = new UpdateRequest<T, T>(entity)
{
ScriptedUpsert = true,
Script = new InlineScript(
$"if (someCondition) {{ctx._source.putAll(params.entity);}} else {{ctx.op = \"noop\";}}")
{
Lang = "painless",
Params = new Dictionary<string, object>() { { "entity", entity } },
},
Upsert = Activator.CreateInstance<T>()
};
but in the end it will not update phrase and date.
It makes following request:
POST /myIndex/_update/b90278fd-1a66-40bf-b775-d076122c6c02
{
"script": {
"source": ""if (someCondition) {{ctx._source.putAll(params.entity);}} else {{ctx.op = \"noop\";}}"",
"lang": "painless",
"params": {
"entity": {
"name": "",
"age": 22
}
}
},
"upsert": {
"age": 0
}
}
Idk why but it skips all fields with null.
How to update nullable fields to null?
NEST does not support sending null values by default.
You can have a check in script such that if a value is not passed then you can remove it from document.
var updateRequest = new UpdateRequest<T, T(entity)
{
ScriptedUpsert = true,
Script = new InlineScript($"if (params.entity.phrase==null)ctx._source.remove('phrase');")
{
Lang = "painless",
Params = new Dictionary<string, object>() { { "entity", entity } },
},
Upsert = Activator.CreateInstance<T>()
};
You can check for more details here
var group = new BsonDocument
{
{
"_id", new BsonDocument {
{"ActivityType", "$ActivityType"},
}
},
// {
// "Result", new BsonDocument("$push", new BsonDocument
// {
// // { "$slice",-1},
// { "SessionRecords", "$SessionRecords" },
// }
// )
//},
{
"Result", new BsonDocument("$push", new BsonDocument(
"$slice", new BsonArray
{
//new BsonDocument("$slice",new BsonDocument("SessionRecords","$SessionRecords")),
new BsonArray().Add("$SessionRecords.TemplateId"),
-1,
}
))
}
};
this is my query and may data is like this
it return all array elements data is like
[
{
"_id": "62f110c25a1c144e4b4a00ec",
"ActivityType":"Working",
"SessionRecords": [{
"TemplateId": "6229dded08714fdbcdf1c969",
"SecondsCounter": 0,
"BreathCounter": 0,
},
{
"TemplateId": "6229dded08714fdbcdf1c969",
"SecondsCounter": 0,
"BreathCounter": 0,
},
]
},
]
Im facing a litle problem in Deserializing BsonDocuments type, I couldn't find the reason, but I have some clues, maybe, it's about {0 fields}, because the error tel me about the column I have {0 fields}. I also realised that its a {} (empty array).
MY MONGO QUERY ON ROBO 3T AND THE RESULT
MY C# MONGO QUERY
var connString = "mongodb+srv";
var client = new MongoClient(connString);
var database = client.GetDatabase("Base");
var collection = database.GetCollection<BsonDocument>("collection");
var match1 = new BsonDocument("$match", new BsonDocument("PartnerId", "2021"));
var match2 = new BsonDocument("$match", new BsonDocument("CD_CLIENTE", codCond));
var project = new BsonDocument { { "$project", new BsonDocument { { "_id", 0 }, { "CD_CLIENTE", 1 }, { "CD_ACESSO", 1 },
{ "ID_ACESSO", 1 },{ "NOME", 1 },{ "NU_TELEFONE", 1 }, { "EMAIL", 1 }, { "NU_KIPER_RF", 1 }, { "NU_KIPER_TAG", 1 },
{ "FG_KIPER_MOBILE", 1 },{ "KEY_HASH", 1 },}}}; MY MONGO AND RESULT
var sort = new BsonDocument("$sort", new BsonDocument("NOME", 1));
var pipeline = new[] { match1, match2, project, sort };
var result = collection.Aggregate<BsonDocument>(pipeline).ToList();
var lista = JsonConvert.DeserializeObject<List<UsuariosAcessos>>(result.ToJson());
The error is here:
var lista = JsonConvert.DeserializeObject<List<UsuariosAcessos>>(result.ToJson());
Exatly when I try to Deserialise an that "empty array" to Model int?. I found a work around, because I just need to know if, we have or dont not something in NU_KIPER_TAG and NU_KIPER_RF, so, I did this new Mongo query.
NEW MONGO QUERY USING $COND
db.dbACESSO.aggregate([
{
$match: { PartnerId: "2021", CD_CLIENTE: 4003}
},
{
$project: {_id:0, CD_CLIENTE:1, CD_ACESSO:1, ID_ACESSO:1, NOME:1, NU_TELEFONE:1,EMAIL:1, FG_KIPER_MOBILE:1,
TAG:{$cond: [{ $eq: [ "$NU_KIPER_TAG", {}]}, 0, 1 ]}, CONTROLE:{$cond: [{ $eq: [ "$NU_KIPER_RF", {}]}, 0, 1 ]},
APPATIVO:{$cond: [{ $eq: [ "$KEY_HASH", {}]}, "", "$KEY_HASH" ]}}
}
])
I couldnt translate it to C#, I tried hard, but i'm not familiarized with the sintaxe. I also googled for a sample with no success.
I think its something like:
var project = new BsonDocument {
{
"$project", new BsonDocument { { "_id", 0 }, { "CD_CLIENTE", 1 }, { "CD_ACESSO", 1 },{ "ID_ACESSO", 1 },{ "NOME", 1 }
,{ "NU_TELEFONE", 1 }, { "EMAIL", 1 }, { "NU_KIPER_RF", 1 }, { "NU_KIPER_TAG", 1 },{ "FG_KIPER_MOBILE", 1 },{ "KEY_HASH", 1 },
{"TAG", new BsonDocument{{"$cond", new BsonDocument {{ "$eq", "$NU_KIPER_TAG", "{}"}}, 0, 1 ]}, } }
}
}
};
Try this way, it will work!
var project = new BsonDocument
{
{
"$project", new BsonDocument
{
{ "_id", 0},
{ "CD_CLIENTE", 1},
{ "CD_ACESSO", 1 },
{ "NOME", 1},
{ "EMAIL", 1 },
{ "FG_KIPER_MOBILE", 1 },
{ "GRUPO", "$GRUPO.NM_DESCRICAO" },
{ "UNIDADE", "$UNIDADE.NM_DESCRICAO" },
{ "NU_TELEFONE", new BsonDocument{{ "$cond", new BsonArray{new BsonDocument{{"$eq", new BsonArray{ "$NU_TELEFONE", new BsonDocument { } } }}, "","$NU_TELEFONE" } }}},
{ "TAG", new BsonDocument{{ "$cond", new BsonArray{new BsonDocument{{"$eq", new BsonArray{ "$NU_KIPER_TAG", new BsonDocument { } } }}, 0,1 } }}},
{ "CONTROLE", new BsonDocument{{ "$cond", new BsonArray{new BsonDocument{{"$eq", new BsonArray{ "$NU_KIPER_RF", new BsonDocument { } } }}, 0,1 } }}},
{ "APPATIVO", new BsonDocument{{ "$cond", new BsonArray{new BsonDocument{{"$eq", new BsonArray{ "$KEY_HASH", new BsonDocument { } } }}, "", "$KEY_HASH" } }}},
}
}
};
The empty array will be represented for: new BsonDocument { }
{ "NU_TELEFONE", new BsonDocument{{ "$cond", new BsonArray{new BsonDocument{{"$eq", new BsonArray{ "$NU_TELEFONE", new BsonDocument { } } }}, "","$NU_TELEFONE" } }}},
What about using the fluent C# like this:
var connString = "mongodb+srv";
var client = new MongoClient(connString);
var database = client.GetDatabase("Base");
var collection = database.GetCollection<UsuariosAcessos>("collection"); //Here you put you Model
var filter = Builders<UsuariosAcessos>.Filter.Eq(x => x.PartnerId, cliente)
& Builders<UsuariosAcessos>.Filter.Eq(x => x.CD_CLIENTE, codCond);
var lista = collection.Aggregate().Match(filter).Project(x => new UsuariosAcessos
{
CD_CLIENTE = x.CD_CLIENTE,
ID_ACESSO = x.ID_ACESSO,
CD_ACESSO = x.CD_ACESSO,
NOME = x.NOME,
NU_TELEFONE = x.NU_TELEFONE,
EMAIL = x.EMAIL,
NU_KIPER_RF = x.NU_KIPER_RF,
NU_KIPER_TAG = x.NU_KIPER_TAG,
FG_KIPER_MOBILE = x.FG_KIPER_MOBILE,
KEY_HASH = x.KEY_HASH
}).ToList();
About your problem at Deserialization time, I think it's not possible to translate {} (empty array) to int or int?, it's appear to be the reason your deserialization is not working, try to change your model.
FROM:
public int? NU_KIPER_TAG { get; set; }
public int? NU_KIPER_RF { get; set; }
TO:
public object NU_KIPER_TAG { get; set; }
public object NU_KIPER_RF { get; set; }
Its not you are looking for, but, maybe your Deserialization are going to Work. After that, you can convert the data. Hope this helps.
I am trying to use c# to insert each new subdocument into an array at the top position using driver version 2.4.2.
In mongo the following command works well:
db.getCollection('Operation').update(
{_id: ObjectId('586e9ec5ab3d05173cd88957') },
{$push: {'location': {$each: [ { 'value' : 'Site', 'time' : ISODate('2017-02-24T16:05:44.204Z'), 'user' : 'user1' } ], $position: 0 } } }
)
Then the result is:
{
"_id" : ObjectId("586e9ec5ab3d05173cd88957"),
"location" : [
{
"value" : "Site",
"time" : ISODate("2017-02-24T16:05:44.204Z"),
"user" : "user1"
}
]
}
But so far I do not succeed in getting the same result in C#. I have tried so far:
var filter = Builders<BsonDocument>.Filter.Eq("_id", ObjectId.Parse("586e9ec5ab3d05173cd88957"));
var update = Builders<BsonDocument>.Update.PushEach("location", new List<BsonArray>() { new BsonArray { new BsonDocument { { "value", "Site" }, { "time", DateTime.UtcNow }, { "user", "user1" } } } }, position: 0);
collection.UpdateOne(filter, update);
And also no succes trying to specify all in text:
collection.UpdateOne("{ '_id': ObjectId('586e9ec5ab3d05173cd88957') }", "{ '$push': {'location': { '$each': [ { 'value' : 'Site', 'time' : ISODate('2017-02-24T16:05:44.204Z'), 'user' : 'user1' } ], $position: 0 } } }");
Any suggestions?
PushEach expects just a BsonArray parameter, not a List<BsonArray>.
You should be doing something like
var update = updateBuilder.PushEach("location", locationBSONArray);
There is no need to serialize to bson document.
Took me a while because of a typo. The answer of user1892538 was correct. This works:
var update = Builders<BsonDocument>.Update.PushEach("location", new BsonArray { new BsonDocument { { "value", "Site" }, { "time", DateTime.UtcNow }, { "user", "user1" } } }, position: 0);
How to convert this command for c# .net?
db.logs.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [ lng , lat ] },
distanceField: "dist.distance",
maxDistance: 5,
includeLocs: "dist.location",
num: 1000,
spherical: true
},
}
])
Finally, It's work fine.
BsonDocument geoPoint = new BsonDocument
{
{"type","Point"},
{"coordinates",new BsonArray(new Double[]{double.Parse(lon), double.Parse(lat)})}
};
BsonDocument query = new BsonDocument
{
{
"$eq", new BsonArray {"City", "Bangkok" }
}
};
BsonDocument geoNearOptions = new BsonDocument
{
{"spherical", true},
{"limit", 10000}, //need to test to see what limit is appropriate, should we do a filter first?
{"maxDistance", 400},
{"query",filter},
{"near",geoPoint},
{"distanceField","dist.distance"},
{"includeLocs", "dist.location"},
};
var stage = new BsonDocumentPipelineStageDefinition<BsonDocument, BsonDocument>(new BsonDocument { { "$geoNear", geoNearOptions } });
var colAggregate = collection2.Aggregate().AppendStage(stage).Sort(new BsonDocument { { "_id", 1 } });