how to concate all the members id from that mongodb collection? - javascript

I have a collection named group on the mongoDb database . The collection includes 2 or more object and each object contains an array named members . what is the best possible and efficient way to concate and get all the members data from the database. what would be the mongoDB query ?
my collection looks like
[
{
id: ObjcetId("15215252"),
groupName: "travellers of Bangladesh",
members: ["1","2","3"]
},
{
id: ObjcetId("32643724362"),
groupName: "People from Bangladesh",
members: ["4","5","6"]
}
]
and i Want just this exact data
members: ["1","2","3","4","5","6"]

Use can use aggregations
$unwind to deconstruct the array
$group to reconstruct the array
Here is the code
db.collection.aggregate([
{ $unwind: "$members" },
{
$group: {
_id: null,
members: { $push: "$members" }
}
}
])
Working Mongo playground

Related

Why is $elemMatch return the first document, instead of the all matches documents?

I'm trying to execute a query that returns all the documents that match based on query parameters.
I have the following schema:
_id: ObjectId('631b875491b16c38eecfa4e9')
brandName: "Nick"
categories: Array
products: Array
0: Object
productName: "Vans Shoes dsds Old Skool"
description: "amazing Shoes."
categoryId: ObjectId('62f3eaff3ded19dcce71081e')
price: 240
numberOfBuyers: 0
_id: ObjectId(631b875491b16c38eecfa4ec)
1: Object
2: Object
3: Object
__v: 0
The following query should give me all the documents that match, but it returns only the first document:
const products = await Brand.find(
{
_id: brandId
},
{
products: {
$elemMatch: {
categoryId: categoryId,
price: {
$gte: minPrice,
$lte: maxPrice
}
}
}
})
What is wrong?
You are querying on "Brand" documents. This means your query tells Mongoose: if one of the products is matching (categoryId and price), return the (whole) Brand document.
In order to retrieve only specific elements of this array, you should include your $elemMatch object in the projection step of your find call:
const products = await Brand.find({
_id: brandId
}, {
//include other properties you want to include in your output document
products: {
$elemMatch: {
categoryId: "62f3eaff3ded19dcce71081e",
price: 240
}
}
}
})
Update after comment
Your products array will only contain the first element that was matched. This is intended behaviour (as described here: cs/manual/reference/operator/projection/elemMatch/):
Definition
$elemMatch
The
$elemMatch
operator limits the contents of an field from the query results to contain only the first element matching the
$elemMatch
condition.
In order to get several results you should probably use an aggregation pipeline using $unwind and $group.

Return unique document per Mongo IN query

I'm querying a Collection that has 350k+ Documents. I'm querying a field using the IN clause where the IN is an array of 27k+ fields.
This actually seems to return rather fast in Mongoose. However, some of the matches of each item in the IN can have multiple Documents associated with them. I'd like to only have 1 Document returned per each match (sorted by another field). Is this possible?
Example
Let's say I have a Collection of Fruit.
[
{type:'apple', price:10},{type:'apple', price:5},{type:'apple', price:3},
{type:'orange', price:2},
{type:'pear', price:12}, {type:'pear', price:2}
]
So, currently I have
const types = ['apple', 'orange', 'pear'];
//Will return full example above
//Returns 12k Docs in real app but bc multiple Docs are returned per item in IN
Fruit.find({type: { $in: types }}, (err, results) => {
if (err) return console.error(err);
console.log(results);
});
I'd like to just have
[
{type:'apple', price:10}
{type:'orange', price:2},
{type:'pear', price:12}
]
How can I adjust my query to do something like this? Thanks!
returned. So instead of all documents matching the type - I just get only 1 with the highest price.
You need to $group by type and use $max to get highest prices:
db.collection.aggregate([
{
$match: { type: { $in: ['apple', 'orange', 'pear'] } }
},
{
$group: {
_id: "$type",
price: { $max: "$price" }
}
},
{
$project: {
type: "$_id",
_id: 0,
price: 1
}
}
])
Mongo Playground

MongoDB, mongoose, update object inside array

I have the following MongoDB model:
const Relation = mongoose.model('Relation',{
name :{
type: String,
},
port:{
type: Number,
},
services: { type : Array , "default" : [] }
});
Each port is a unique number for each document.
A collection could have the following values:
{
"port":"116", //unique number
"name":"xzy",
services: [
{"id":'1', "trust":"good"},
{"id":'2', "trust":"bad"},
]
}
How can for example make the "trust" value "bad" for the object with the "id"= 1 ??
I assume I should first find the collection that matchs the port number "116" and then find the object inside the Services array that has the "id" of 1.
How can I do that in mongoose?
You can use $ positional operator to update value inside an array
Relation.findOneAndUpdate(
{ "port": "116", "services.id": "1" },
{ "$set": { "services.$.trust": "bad" }}
)

Using $lookup on an array of objects to join two documents in MongoDB [duplicate]

This question already has answers here:
MongoDB join data inside an array of objects
(2 answers)
Closed 4 years ago.
I have many Shop documents that each contain a field products which is an array of objects where the key is the product ID and the value is the quantity in stock:
{ products: [{"a": 3}, {"b": 27}, {"c": 4}] }
I have a collection Products where each product has a document containing productId, name, etc:
{ productId: "a", "name": "Spanner"}
I would like to pull in/aggregate/join the product information for each of those items. I know how to do it when the field is a single ID, and I have seen this answer which describes how to do it for an array of IDs. But I am having a bit of trouble wrapping my head around what to do with an array of objects containing IDs.
Desired output:
{
products: [
{ {productId: "a", "name": "Spanner"}: 3 }
]
}
(And no, it is not within my control to switch to a relational database.)
I think if you want to using ID for reference, try to avoid place it as object keys, instead make it as object property like { products: [{"productId": $_id, "quantity": 3}]}, that could be a reason for downvote.
But if you cant change it, you can using $objectToArray in aggregation to convert your array.
One more thing, your desire output is unreal because object property in js cant not be an object.
Try it:
db.Shop.aggregate(
// Pipeline
[
// Stage 1
{
$unwind: {
path : "$products"
}
},
// Stage 2
{
$project: {
products: { $objectToArray: "$products" }
}
},
// Stage 3
{
$unwind: {
path : "$products"
}
},
// Stage 4
{
$project: {
productId: "$products.k",
productQuantity: "$products.v"
}
},
// Stage 5
{
$lookup: {
"from" : "products",
"localField" : "productId",
"foreignField" : "productId",
"as" : "products"
}
},
// Stage 6
{
$unwind: {
path : "$products"
}
},
// Stage 7
{
$project: {
productId: "$productId",
productQuantity: "$productQuantity",
productName: "$products.name"
}
},
]);
Good luck

Array of values

For example I have n doc in MongoDB collection
Films = new Mongo.Collection('films');
Film.insert({name: 'name n', actor: 'John'}); // *n
And I want to show array with only name values
var names = ['name 1', 'name 2',..,'name n'];
Any idea how to do it ?
And guys , ols write in comments correct title value of my question, to help other guys to find it, thx :)
You didn't provided any criteria for grouping name as an array.
You can use following query to get all names:
db.collection.distinct("name")
OR you can use MongoDB's aggregation to get all name by grouping them with some condition, if required. The query will be like following:
db.collection.aggregate({
$group: {
_id: null, //add condition if require
name: {
$push: "$name"
}
}
}, {
$project: {
name: 1,
_id: 0
}
})
If you want only distinct name then replace $push with $addToSet.

Categories

Resources