get additional data on same collection in Mongodb C# - mongodb

I have a collection called "User". I'm passing userid to get the record. In addition to that i also need additional 10 last updatedAt(DateTime) record excluding the userid record but added together. So, total returned result will be 11 in this case. Is that possible using same query? I tried using Or and lookup but can't make it work as expected.
Any help is appreciated.
User collection:
[{
"id" : "123456",
"name" : "foo",
"addressIds" : [ObjectId(234567)]
} ,
"id" : "345678",
"name" : "bar",
"addressIds" : [ObjectId(678565), ObjectId(567456)]
}]
Address collection:
[{
"_id":"234567",
"district" : "district1",
"pincode" : "568923",
},
{
"_id":"678565",
"district" : "district2",
"pincode" : "568924",
},
{
"_id":"567456",
"district" : "district3",
"pincode" : "568925",
}]
Using facets, i have the User and the addressIds. Can i have the actual documents for AddressIds in User?

Edit:
You can use $facet, like this:
db.collection.aggregate([
{$sort: {date: -1}},
{$facet: {
byTate: [{$limit: 10}],
byUser: [{$match: {userId: 455845}}]
}
},
{$project: {
byDate: {
$filter: {
input: "$byDate",
as: "item",
cond: {$ne: ["$$item",{"$arrayElemAt": ["$byUser", 0]}]}
}
},
byUser: 1,
}
},
{
$project: {
byDate: {$slice: ["$byDate", 10]},
byUser: 1
}
}
])
You can see it works on the playground .
Switch between userId: 455845 / 455845 to see both cases.

Related

how to find duplicate records in mongo db query to use

I have below collection, need to find duplicate records in mongo, how can we find that as below is one sample of collection we have around more then 10000 records of collections.
/* 1 */
{
"_id" : 1814099,
"eventId" : "LAS012",
"eventName" : "CustomerTab",
"timeStamp" : ISODate("2018-12-31T20:09:09.820Z"),
"eventMethod" : "click",
"resourceName" : "CustomerTab",
"targetType" : "",
"resourseUrl" : "",
"operationName" : "",
"functionStatus" : "",
"results" : "",
"pageId" : "CustomerPage",
"ban" : "290824901",
"jobId" : "87377713",
"wrid" : "87377713",
"jobType" : "IBJ7FXXS",
"Uid" : "sc343x",
"techRegion" : "W",
"mgmtReportingFunction" : "N",
"recordPublishIndicator" : "Y",
"__v" : 0
}
We can first find the unique ids using
const data = await db.collection.aggregate([
{
$group: {
_id: "$eventId",
id: {
"$first": "$_id"
}
}
},
{
$group: {
_id: null,
uniqueIds: {
$push: "$id"
}
}
}
]);
And then we can make another query, which will find all the duplicate documents
db.collection.find({_id: {$nin: data.uniqueIds}})
This will find all the documents that are redundant.
Another way
To find the event ids which are duplicated
db.collection.aggregate(
{"$group" : { "_id": "$eventId", "count": { "$sum": 1 } } },
{"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }
)
To get duplicates from db, you need to get only the groups that have a count of more than one, we can use the $match operator to filter our results. Within the $match pipeline operator, we'll tell it to look at the count field and tell it to look for counts greater than one using the $gt operator representing "greater than" and the number 1. This looks like the following:
db.collection.aggregate([
{$group: {
_id: {eventId: "$eventId"},
uniqueIds: {$addToSet: "$_id"},
count: {$sum: 1}
}
},
{$match: {
count: {"$gt": 1}
}
}
]);
I assume that eventId is a unique id.

How to filter Mongodb $lookup results to get only the matched nested objects?

I have a customers collection such as;
{
"_id" : ObjectId("5de8c07dc035532b489b2e23"),
"name" : "sam",
"orders" : [{"ordername" : "cola"},{"ordername" : "cheesecake"}]
}
And waiters collection such as;
{
"_id" : ObjectId("5de8bc24c035532b489b2e20"),
"waiter" : "jack",
"products" : [{"name" : "cola", "price" : "4"},
{"name" : "water", "price" : "2"},
{"name" : "coffee", "price" : "8" }]
}
{
"_id" : ObjectId("5de8bdc7c035532b489b2e21"),
"waiter" : "susan",
"products" : [{"name" : "cheesecake", "price" : "12" },
{"name" : "apple pie", "price" : "14" }]
}
I want to join the objects from waiters collection into the customers collection by matching "products.name" and "orders.ordername". But, the result includes the whole document from the waiters collection, however, I want only the matched objects inside the document. Here is what I want;
ordered:[
{"name" : "cola", "price" : "4"},
{"name" : "cheesecake", "price" : "12" },
]
I tried $lookup with and without pipeline, and filter but could not get this result. Thanks in advance.
You had the right idea, we just have to "massage" the data a bit due to its structure like so:
db.collection.aggregate([
{
$addFields: {
"orderNames":
{
$reduce: {
input: "$orders",
initialValue: [],
in: {$concatArrays: [["$$this.ordername"], "$$value"]}
}
}
}
},
{
$lookup:
{
from: "waiters",
let: {orders: "$orderNames"},
pipeline: [
{
$unwind: "$products"
},
{
$match:
{
$expr:{$in: ["$products.name", "$$orders"]},
}
},
{
$group: {
_id: "$products.name",
price: {$first: "$products.price"}
}
},
{
$project: {
_id: 0,
price: 1,
name: "$_id"
}
}
],
as: "ordered"
}
}
])
It feels like you could benefit from a new collection of mapping items to prices. Could potentially save you a lot of time.

MongoDB - Grouping by inner-documents and retrieving top results

I'm trying to find the most common (and least common) skills stored in the mongo database. I'm using mongoose to retrieve the results.
The User is the root document, which each have an inner Profile document. The profile has an attribute of 'skills' which contain an array of ProfileSkillEntry's which has a title (the skill name).
return User.aggregate([{
$group: {
'_id': '$profile.skills.title',
'count': {
$sum: 1
}
}
}, {
$sort: {
'count': -1
}
}, {
$limit: 5
}]);
I expect it to combine all of the registered Users skills together, find the top 5 occurring and return that. Instead it seems to be grouping per-user and giving invalid results.
Example User document structure:
{
"_id" : ObjectId("..."),
"firstName" : "Harry",
"lastName" : "Potter",
"profile" : {
"_id" : ObjectId("..."),
"skills" : [
{
"_id" : ObjectId("..."),
"title" : "Java",
"description" : "Master",
"dateFrom" : "31/07/2019",
"coreSkill" : true
},
{
"_id" : ObjectId("..."),
"title" : "JavaScript",
"description" : "Proficient",
"dateFrom" : "31/07/2019",
"coreSkill" : false
}
],
}
}
Please use the below query. Just add the sort and limit as per your requirement
db.test.aggregate(
[{ $unwind: { path: "$profile.skills"} },
{ $group: { _id: "$profile.skills.title",
"count": { $sum: 1 }} }] )

mongoDB query to find the document in nested array

[{
"username":"user1",
"products":[
{"productID":1,"itemCode":"CODE1"},
{"productID":2,"itemCode":"CODE1"},
{"productID":3,"itemCode":"CODE2"},
]
},
{
"username":"user2",
"products":[
{"productID":1,"itemCode":"CODE1"},
{"productID":2,"itemCode":"CODE2"},
]
}]
I want to find all the "productID" of "products" for "user1" such that "itemCode" for the product is "CODE1".
What query in mongoDB should be written to do so?
If you only need to match a single condition, then the dot notation is sufficient.
In Mongo shell:
db.col.find({"products.itemCode" : "CODE1", "username" : "user1"})
This will return all users with nested product objects having itemCode "CODE1".
Updated
Wasn't clear on your requirements at first but this should be it.
If you want each product as a separate entry, then you would need to use the aggregate framework. First split the entries in the array using $unwind, then use $match for your conditions.
db.col.aggregate(
{ $unwind: "$products" },
{ $match: { username: "user1", "products.itemCode": "CODE1" } }
);
response:
{ "_id" : ObjectId("57cdf9c0f7f7ecd0f7ef81b6"), "username" : "user1", "products" : { "productID" : 1, "itemCode" : "CODE1" } }
{ "_id" : ObjectId("57cdf9c0f7f7ecd0f7ef81b6"), "username" : "user1", "products" : { "productID" : 2, "itemCode" : "CODE1" } }
The answer to your question is
db.col.aggregate([
{ $unwind: "$products" },
{ $match: { username: "user1", "products.itemCode": CODE1 } },
{ $project: { _id: 0, "products.productID": 1 } }
]);
In my case didn't work without [ ] tags.
You need multiple filter for this like below which is nothing but AND condition (assuming your collection name is collection1)
db.collection1.find({"username":"user1", "products.itemCode" : "CODE1"})

MongoDB - is this query possibile with denormalized model?

I have this simple Mongodb document:
{
"_id" : ObjectId("55663d9361cfa81a5c48d54f")
"name" : "Oliver",
"surname" : "Queen",
"age" : 25,
"friends" : [
{
"name" : "Jhon",
"surname" : "Diggle",
"age" : "30"
},
{
"name" : "Barry",
"surname" : "Allen",
"age" : "24"
}
]
}
Is it possbile, using denormalized model as above, to find all Oliver's friends with 24 years old?
I think it's really simple with normalized model; it's enough to do two queries.
For example the following query:
db.collection.find({name:"Oliver", "friends.age":24}, {_id:0, friends:1})
returns an array of Oliver's friends. Is it possible to make a selection of the internal document?
Using aggregation
db.collection.aggregate(
[
{ $match: { "name": "Oliver" }},
{ $unwind: "$friends" },
{ $match: { "friends.age": 24 }},
{ $group: { "_id": "$_id", friends: { "$push": "$friends" }}},
{ $project: { "_id": 0, "friends": 1 }}
]
)