I have this code:
var pipeline = new BsonDocument[]
{
new BsonDocument("$lookup",
new BsonDocument
{
{ "from", "comments" },
{ "let",
new BsonDocument("id", "$_id") },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("$expr",
new BsonDocument("$eq",
new BsonArray
{
"$postId",
"$$id"
}))),
new BsonDocument("$sort", new BsonDocument("time", -1)),
new BsonDocument("$limit", Filters.defaultCommentsLimitPerPost),
}
},
{ "as", "comments" }
}),
new BsonDocument("$limit", 3),
new BsonDocument("$skip", page - 1),
};
var pipeline = PipelineDefinition<Post, Post>.Create(Filters.GetJoinComments(page));
var result = await collectionPosts.Aggregate(pipeline).ToListAsync();
How can I also get the total count of all documents, ignoring $limit and $skip?
an example for a post document:
{"_id":null,"time":{"$numberLong":"637396703347196085"},"text":"some text","totalCommentsCount":{"$numberInt":"0"},"likes":{"$numberInt":"0"},"category":{"$numberInt":"0"},"videoUrl":null}
an example for a comment document:
{"_id":{"$oid":"5f9dbaf79d10c42f64f46f53"},"text":"a comment","time":{"$numberLong":"637397765330317024"},"likes":{"$numberInt":"0"},"postId":{"$oid":"5f9089dd818de4309403d21b"}}
The query you tried is very much appreciated.
I have additionally added
$sort to osrt by _id. If you don't need, remove the sort
$group to group all documents into data (Because _id:null). At the same time we get the total counts.
$unwind to deconstruct the data array
I thin you use this for pagination, right? If so, you need to keep $sort and first should be $skip, following should be $limit as I mentioned
And the working query.
db.post.aggregate([
{
$lookup: {
from: "comment",
let: {
"pId": "$_id"
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$postId",
"$$pId"
]
}
}
}
],
as: "comments"
}
},
{
$sort: { _id: 1 }
},
{
$group: {
_id: null,
data: { $push: "$$ROOT" },
totalRecords: { $sum: 1 }
}
},
{ $unwind: "$data" },
{ $skip: 1 },
{ $limit: 1 }
])
Working Mongo playground
Related
I am receiving request data from api server,
The api server code is like this
public List<api_model> getList(Dictionary<string, object> param)
{
List<api_model> tempList = new List<api_model>();
List<api_model> resultList = new List<api_model>();
JsonRes.GetListRes res;
try
{
GetListRequest jsonReq = new GetListRequest();
jsonReq.Session = param;
string strJsonReq = jsonReq.TransformText();
string strUri = String.Format("'API ADRESS'");
string strJsonRes = httpUtils.HttpRequest(strUri, "POST", strJsonReq).ToString();
using (JsonTextReader reader = new JsonTextReader(new System.IO.StringReader(strJsonRes)))
{
JsonSerializer serializer = new JsonSerializer();
res = (JsonRes.GetListRes)serializer.Deserialize(reader, typeof(JsonRes.GetListRes));
}
if (res.outputCode.Equals("1"))
{
foreach (JsonRes.GetListRes.Data data in res.dataList)
{
List<api_model.array> arrayList = new List<api_model.array>();
foreach (JsonRes.GetListRes.array ar in data.arrayList)
{
api_model.array arrays = api_model api_model.array
{
detailCode = ar.detailCode,
foodCount = ar.foodCount
};
arrayList.Add(arrays);
}
api_model um = new api_model
{
className = data.className,
arrays = arrayList
};
tempList.Add(bm);
}
resultList = tempList;
}
}
catch (Exception ex)
{
CommonUtils.errorLog(ex.ToString());
throw ex;
}
return resultList ;
}
In this code, the client sends the request data
{
"foodCode": "01",
"array": [
{
"detailCode": "001",
"foodCount": "1"
},
{
"detailCode": "002",
"foodCount": "1"
},
{
"detailCode": "003",
"foodCount": "1"
},
{
"detailCode": "004",
"foodCount": "1"
}
]
}
With this request data, the api server gives response data like this
{
"Code": "00",
"Msg": "SUCCESS",
"Data": [
{
"foodNmae": "meat",
"array": [
{
"detailCode": "001",
"foodCount": "1"
},
{
"detailCode": "002",
"foodCount": "1"
},
{
"detailCode": "003",
"foodCount": "1"
},
{
"detailCode": "004",
"foodCount": "1"
},
{
"detailCode": "005",
"foodCount": "1"
}
]
},
{
"foodNmae": "seafood",
"array": [
{
"detailCode": "001",
"foodCount": "1"
},
{
"detailCode": "002",
"foodCount": "1"
},
{
"detailCode": "003",
"foodCount": "1"
},
{
"detailCode": "004",
"foodCount": "0"
},
{
"detailCode": "005",
"foodCount": "1"
}
]
}
]
}
After comparing request parameters and response parameters, I want to filter them and put them in the list
I want to use a lambda expression to compare and put it in a list.
The data that should be included in the list is only foodNmae = meat
I coded this far
resultList = tempList;
I want to use this code to extract the desired data using a lambda expression.
You seem to be struggling for a few days, I hope anyone can help
var Array = ((IEnumerable)(param["array"]));
resultList .AddRange(tempList.Where(um => um.array[0].foodCount.Equals(Array)));
I don't know how to fix this part
resultList .AddRange(tempList.Where(um => um.array[0].foodCount.Equals(Array)));
I have multiple document like below in mongo collection(giving just one sample).
{
"_id": "5fdb",
"createddate": "2020-12-17",
"orders": [
{
"_id": "4c65",
"sourcesystemrecordid": null,
"accepteddate": "2020-12-19",
"fulfillment": [
{
"_id": "7d3ceb",
"createdby": "Azekry",
"systemid": "123",
"systemrecordname": "source1"
}
]
}
]
}
Under fulfilment, I want to update "systemid" value from "123" to "789" for all the documents where "systemrecordname" = "source1" and for that I have written below piece of code but the data is not updated. Can you help me on this?
foreach (var item in resultFromDatabse)
{
var ordr = item.orders;
foreach (var e in ordr)
{
var actualval = "789";
foreach (var ef in e.fulfillment.Where(x => x.systemrecordname == "source1"))
{
filter = builder.Eq("systemrecordname", ef.systemrecordname);
var update = Builders<EquipmentDemandPlan>.Update.Set("orders.$[e].fulfillment.$[ef].systemid", actualval);
UpdateOneModel<EquipmentDemandPlan> updateOne = new UpdateOneModel<EquipmentDemandPlan>(filter, update)
{
ArrayFilters = new List<ArrayFilterDefinition> {
new BsonDocumentArrayFilterDefinition<BsonDocument>(new BsonDocument("ef.systemrecordname", ef.systemrecordname))
}
};
bulkupdate.Add(updateOne);
}
}
}
collection.BulkWriteAsync(bulkupdate);
you only need arrayFilters in $set
db.collection.update({
"orders.fulfillment.systemrecordname": "source1"
},
{
$set: {
"orders.$[o].fulfillment.$[f].systemid": "789"
}
},
{
arrayFilters: [
{
"o._id": {
$exists: true
}
},
{
"f.systemrecordname": "source1"
}
],
multi: true
})
mongoplayground
I want to retrieve all the documents of a collection from mongoDB in C# .Net Web API. Below code is working fine but It is returning BsonDocument
var client = new MongoClient(connectionString);
var db = client.GetDatabase("STRDB");
var mongoCollection = db.GetCollection<BsonDocument>(collection);
var documents = mongoCollection.AsQueryable();
return Ok(documents);
From above code I am getting data in below format (After JSON.stringify() in angular)
[
[
{
"name":"_id",
"value":"5de9f351baca28556c6a4b71"
},
{
"name":"Name",
"value":"Harsha"
},
{
"name":"Age",
"value":20
},
{
"name":"Gender",
"value":"M"
},
{
"name":"Skills",
"value":[
{
"name":"Java",
"value":""
},
{
"name":"Mule",
"value":true
},
{
"name":"Angular",
"value":""
}
]
}
],
[
{
"name":"_id",
"value":"5de9f358baca28556c6a4b72"
},
{
"name":"Name",
"value":"Anji"
},
{
"name":"Age",
"value":21
},
{
"name":"Gender",
"value":"M"
},
{
"name":"Skills",
"value":[
{
"name":"Java",
"value":""
},
{
"name":"Mule",
"value":true
},
{
"name":"Angular",
"value":true
}
]
}
]
]
How to receive it in proper JSON format OR how to convert this BSON document in JSON as I am unable to process this output.
Try the following, with conversion.
var client = new MongoClient(connectionString);
var db = client.GetDatabase("STRDB");
var mongoCollection = db.GetCollection<BsonDocument>(collection);
var documents = mongoCollection.AsQueryable();
return Ok(documents.ToList().ConvertAll(BsonTypeMapper.MapToDotNetValue));
In Elasticsearch Document describe about Function Score Query show code as below
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"functions": [
{
"filter": { "match": { "test": "bar" } },
"random_score": {},
"weight": 23
},
{
"filter": { "match": { "test": "cat" } },
"weight": 42
}
],
"max_boost": 42,
"score_mode": "max",
"boost_mode": "multiply",
"min_score" : 42
}
}
}
I write this query to object initializer syntax
var searchRequest = new SearchRequest<ProductType>
{
Query = new FunctionScoreQuery()
{
Query = new MatchAllQuery {},
Boost = 5,
Functions = new List<IScoreFunction>
{
Filters...?
},
MaxBoost = 42,
ScoreMode = FunctionScoreMode.Max,
BoostMode = FunctionBoostMode.Max,
MinScore = 42
}
};
How to build filters in Functions?
The IScoreFunction interface allow only ExponentialDecayFunction, GaussDateDecayFunction, LinearGeoDecayFunction, FieldValueFactorFunction, RandomScoreFunction, WeightFunction, ScriptScoreFunction
Functions is a collection of IScoreFunction. In the example JSON, the first function is a random score function, and the second, a weight function. The linked Query DSL example has examples of the different functions, and here's an example to match the JSON above
var client = new ElasticClient();
var searchRequest = new SearchRequest<ProductType>
{
Query = new FunctionScoreQuery()
{
Query = new MatchAllQuery { },
Boost = 5,
Functions = new List<IScoreFunction>
{
new RandomScoreFunction
{
Filter = new MatchQuery
{
Field = "test",
Query = "bar"
},
Weight = 23
},
new WeightFunction
{
Filter = new MatchQuery
{
Field = "test",
Query = "cat"
},
Weight = 42
}
},
MaxBoost = 42,
ScoreMode = FunctionScoreMode.Max,
BoostMode = FunctionBoostMode.Multiply,
MinScore = 42
}
};
var searchResponse = client.Search<ProductType>(searchRequest);
Consider I have a JSON data as:
{
"entities":[
{
"republish": false,
"OrgID": "",
"createdby": "730",
"questions": [
{
"sequence": "5",
"QuestionId": "57BB6DDC-A90A-10EE-E224-EC658A825871",
"metadata": [
{
"key": "Group",
"value": 0
},
{
"key": "Part",
"value": "0"
}
]
},
{
"sequence": "4",
"QuestionId": "57BB6DDC-A90A-10EE-E224-EC658A825871",
"metadata": [
{
"key": "Group",
"value": 1
},
{
"key": "Part",
"value": "A"
}
]
},
{
"sequence": "3",
"QuestionId": "57BB6DDC-A90A-10EE-E224-EC658A825871",
"metadata": [
{
"key": "Group",
"value": 1
},
{
"key": "Part",
"value": "B"
}
]
}
]
}
]
}
As you can see I have a list of questions available and in each question, I have a metadata which holds Key-Value pair.
Above example demonstrates, I have 3 questions and out of it 2 question, metadata key-value is "Group 1".
Now I want to do is combine the questions with a same key-value pair and treat it as one.
so in my final case, I will have 2 questions instead of 3. And out of that one question will have two separate questions inside.
And I want to achieve this using Linq query. And if possible please use Newtonsoft for parse if needed. I have been stuck for long onto this.
Things I have done:
public virtual HttpResponseMessage AddQuestionsToStandardMaster(TaxonomyMetaData objQuestion)
{
List<ResponseEntity> objResponseList = new List<ResponseEntity>();
try
{
if (ModelState.IsValid)
{
foreach (var objEntity in objQuestion.Entities)
{
EntityResponse objentityresponse = new EntityResponse();
ResponseEntity objResponse = new ResponseEntity();
}
List<Question> objQuestionList = new List<Question>();
if (objEntity.Questions.Length > 0)
{
foreach (var item in objEntity.Questions)
{
int questionTypeid = 0;
dynamic objQuestionJson = JObject.Parse(item.ToString())
}
}
}
Question objCurrentQuestion = new Question();
Question objQuestionforDelete = new Question();
JObject itemToParese = new JObject();
string SingleQuestionJson = objQuestionJson.GetValue("QuestionData").ToString();
string questionstem = "";
Regex rgx = new Regex("/\'");
objCurrentQuestion.Sequence = Convert.ToInt32(objQuestionJson.GetValue("sequence"));
objCurrentQuestion.tag = objQuestionJson.tag.ToObject<JToken[]>(); ;
objCurrentQuestion.metadata = objQuestionJson.metadata.ToObject<JToken[]>();
objCurrentQuestion.SingleQuestionJson = rgx.Replace(SingleQuestionJson, "'");
objCurrentQuestion.QuestionsType = questionTypeid;
objCurrentQuestion.QuestionsId = new Guid(objQuestionJson.GetValue("QuestionId").ToString());
objCurrentQuestion.VersionNo = Convert.ToInt32(objQuestionJson.GetValue("VersionNo"));
objCurrentQuestion.DisplayQuestionId = Convert.ToString(objQuestionJson.GetValue("DisplayQuestionId"));
objCurrentQuestion.OriginalQuestionId = Convert.ToString(objQuestionJson.GetValue("OriginalQuestionId"));
objCurrentQuestion.PassageText = Convert.ToString(objQuestionJson.GetValue("passage_text"));
objCurrentQuestion.PassageCode = Convert.ToString(objQuestionJson.GetValue("passage_id"));
objCurrentQuestion.PassageTitle = Convert.ToString(objQuestionJson.GetValue("passage_title"));
objCurrentQuestion.IsPublished = Convert.ToByte(true);
objCurrentQuestion.ProductId = objEntity.ProductID;
foreach (var metadata in objCurrentQuestion.metadata)
{
switch (metadata["key"].ToString())
{
case "Group":
objCurrentQuestion.Group = Convert.ToInt32(metadata["value"].ToString());
break;
case "Part":
objCurrentQuestion.Part = metadata["value"].ToString();
break;
}
}
objQuestionList.Add(objCurrentQuestion);
int counter = 1;
//Here I get the data in a group which needs to coverted to JSOn and then replace the original JSON data with this. But I know this is irrelevant to what we need to achieve.
var yui = objQuestionList.Where(tma => tma.Group == counter).Select(t => t).GroupBy(s => new { s.Group }).Where(p => p.Count() > 1).ToList();
//After proper conversion I need to enter this data to a database.
I am a bit unclear on what do you mean by make it
combine the questions with a same key-value pair and treat it as one
But here is how you can group by the JSON into groups in metadata you can do a custom select to what ever you want.
var text = #"{
""entities"":[
{
""republish"": false,
""OrgID"": """",
""createdby"": ""730"",
""questions"": [
{
""sequence"": ""5"",
""QuestionId"": ""57BB6DDC-A90A-10EE-E224-EC658A825871"",
""metadata"": [
{
""key"": ""Group"",
""value"": 0
},
{
""key"": ""Part"",
""value"": ""0""
}
]
},
{
""sequence"": ""4"",
""QuestionId"": ""57BB6DDC-A90A-10EE-E224-EC658A825871"",
""metadata"": [
{
""key"": ""Group"",
""value"": 1
},
{
""key"": ""Part"",
""value"": ""A""
}
]
},
{
""sequence"": ""3"",
""QuestionId"": ""57BB6DDC-A90A-10EE-E224-EC658A825871"",
""metadata"": [
{
""key"": ""Group"",
""value"": 1
},
{
""key"": ""Part"",
""value"": ""B""
}
]
}
]
}
]
}";
var json = JObject.Parse(text);
var groupedData = from entity in json["entities"]
from question in entity["questions"]
group question by question["metadata"][0]["value"] into questionGroup
select questionGroup;
foreach (var data in groupedData)
{
Console.WriteLine("_____________________");
Console.WriteLine("Group");
Console.WriteLine(data.Key);
foreach (var question in data)
{
Console.WriteLine(question["QuestionId"]);
}
Console.WriteLine("_____________________");
}
If "Group" is not always the fist item in the array you can do
question["metadata"].First(md => md.Value<string>("key") == "Group")["value"]
to get it.