Mongo query to fetch selective fields from the collection [duplicate] - mongodb

This question already has answers here:
How to select a single field for all documents in a MongoDB collection?
(24 answers)
Closed 4 years ago.
Is it possible to fetch selective fields from mongo collections.
Say if my collections is
USer_info
{"_id" : ObjectId("56e0a3a2d59feaa43fba49d5", "date":"2018-07-23T00:00:00.000Z", "Name":"ABC", "ID": "1234", "Subjects":"[Maths, Physics, Science, Music]"}
{"_id" : ObjectId("56e0a3a2d5hjhfjtaese45d5", "date":"2018-07-23T00:00:00.000Z", "Name":"BCS", "ID": "3456", "Subjects":"[CS, Physics, Business]"}
{"_id" : ObjectId("56e0a3a2d59feaa43fba49d6", "date":"2018-07-23T00:00:00.000Z", "Name":"XYZ", "ID": "786", "Subjects": "[Agricultar, Business, Music]"}
Query to list only Name and SUbjects fields:
{"Name":"ABC", "Subjects":"[Maths, Physics, Science, Music]"}
{"Name":"BCS", "Subjects":"[CS, Physics, Business]"}
{"Name":"XYZ", "Subjects": "[Agricultar, Business, Music]"}
Not sure if this a duplicate, but i did not get anything similar so posting it.

You have to define projection part of .find() method to specify which fields should be returned. You alsow have to explicitly exclude _id, try:
col.find({}, { "_id": 0, "Name": 1, "Subjects": 1 })

Related

Is updating Embedded Documents in MongoDB a Manual process?

I am not overly familiar with Mongodb yet , but I have a question about embedded documents.
I have seen a number of posts which show you how to update embedded documents through some update query.
My question is this: If I have a collection with embedded documents - which is denormalised for performance ; and one of the embedded documents changes, then do I need to manually update all the embedded documents or is there some way of specifying the link in MongoDB to Auto-Update?
For Example:
An Order record might look like the structure below. Note there is a Product item in one of the rows.
Lets say the ItemName field changed to "Product1a" in the product from a different collection and I want to update the product in every single order where this exists. Is that a manual process - or is there a way od setting it up in Mongodb to auto-update embedded documents?
{
"id": "ccc1beb1-e022-11e9-97f0-e7e789106ab2",
"type": "order",
"orderNumber": "ORD-100209857x",
"orderDate": "2019-09-26T17:42:31.000+12:00",
"orderItems": [
{
"discount": 0,
"price": 24.4944,
"product": {
"id": "ccc1beb1-e022-11e9-97f0-e7e789106ab2",
"itemNumber": "prd1",
"itemName": "Product1"
},
"qty": 4,
"rowTotal": 97.96,
"taxAmount": 9.8
},
{
"discount": 0,
"price": 3.21,
"itemName": "Shipping",
"qty": 1,
"rowTotal": 3.21,
"taxAmount": 0
}
]
}
Not sure what you mean by manual process, but here is some sample code to update all the documents
db.collection.updateMany({}, {$set:{"orderItems.product.itemName": "updatedProductName"}})
Let me know if this is not what you are looking for.

fetch record(s) based on array element value in mongoDB [duplicate]

This question already has answers here:
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 3 years ago.
I have a collection named test something like below
{"_id": ObjectId("ciwhciwiwh686ddd")
"playerName": "Jon Doe"
"Player Team": "Team1"
"points": [
{"date": "01-01-2018", "score": 145},
{"date": "01-01-2019", "score": 200}
]
}
Went thru mongoDB official documents and tried following methods
db.test.find({"Player Team": "Team1"}, {"points": {"date":"01-01-2018"}})
I also tried
db.test.find({"Player Team": "Team1"}, {"points.date":"01-01-2018"})
I'm getting Unsupported projection option:
The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.
db.test.find({"Player Team": "Team1"}, {"points": {$elemMatch {"date":"01-01-2018"}}})

How to connect to collections by nested fields in MongoDB

I am struggling with some query in MongoDB. Let's say I have standings collection which looks like
{
"competitions: {id: "1", name:"someLeague"},
"standings": [
{
"type": "TOTAL",
"table": [
{
"position": "1",
"team": {
"id": "123",
"name": "XYZ"
},
won: "1",
draw: "2",
lost: "3",
points: "4",
},
{
"position": "2",
"team": {
"id": "321",
"name": "ABC"
}
...
And the fixtures collection which looks like
{
matchDay: "YYYY-MM-DD",
homeTeam: {id: "123", name:"ABC"},
awayTeam: {id: "321", name:"XYZ"},
}
Is it possible to connect this two collection this way that field "homeTeam" in fixtures collection will contain all information including points, won games etc. from standings where type would be total? And same thing with the field awayTeam, with the proviso that information of team would be from array where standings type is away.
There is no means in MongoDB to reference a document of collection A in collection B so that find queries on collection B automatically provide attributes of the referenced document. However, as of MongoDB 3.2 it is possible to use $lookup command as part of an aggregation (see https://stackoverflow.com/a/33511166/3976662) to JOIN (similar to standard SQL) over multiple collections during the query. In your case, you can consider using $lookup in conjunction with $unwind - similar to the example in the MongoDB docs. Spring Data Mongo supports $lookup since 1.10.

How to join two collection in mongo without lookup

I have two collection, there name are post and comment.
The model structure is in the following.
I want to use aggregation query post and sort by comments like length sum, currently I can query a post comments like length sum in the following query statement.
My question is how can I query post and join comment collection in Mongo version 2.6. I know after Mongo 3.2 have a lookup function.
I want to query post collection and sort by foreign comments likes length. Is it have a best way to do this in mongo 2.6?
post
{
"_id": ObjectId("5a39e22c27308912334b4567"),
"uid": "0",
"content": "what is hello world mean?",
}
comment
/* 1 */
{
"_id": ObjectId("5a595d8c2703892c3d8b4567"),
"uid": "1",
"post_id": "5a39e22c27308912334b4567",
"comment": "hello world",
"like": [
"2"
]
}
/* 2 */
{
"_id": ObjectId("5a595d8c2703892c3d8b4512"),
"uid": "2",
"post_id": "5a39e22c27308912334b4567",
"comment": "hello stackoverflow",
"like": [
"1",
"2"
]
}
Query a post comments like sum
db.getCollection('comment').aggregate([
{
"$match": {
post_id: "5a39e22c27308912334b4567"
}
},
{
"$project": {
"likeLength": {
"$size": "$like"
},
"post_id": "$post_id"
}
},
{
"$group": {
_id: "$post_id",
"likeLengthSum": {
"$sum": "$likeLength"
}
}
}
])
There is no "best" way to query, as it'll really depend on your specific needs, but... you cannot perform a single query across multiple collections (aside from the $lookup aggregation pipeline function in later versions, as you already are aware).
You'll need to make multiple queries: one to your post collection, and one to your comment collection.
If you must perform a single query, then consider storing both types of documents in a single collection (with some identifier property to let you filter on either posts or comments, within your query).
There is no other way to join collections in the current MongoDB v6 without $lookup,
I can predict two reasons that causing you the issues,
The $lookup is slow and expensive - How to improve performance?
$lookup optimization:
Follow the guideline provided in the documentation
Use indexs:
You can use the index on the reference collection's fields, as per your sample data you can create an index for post_id field, an index for uid field, or a compound index for both the fields on the basis of your use cases
You can read more about How to Improve Performance with Indexes and Document Filters
db.comment.createIndex({ "post_id": -1 });
db.comment.createIndex({ "uid": -1 });
// or
db.comment.createIndex({ "post_id": -1, "uid": -1 });
Document Filters:
Use the $match, $limit, and $skip stages to restrict the documents that enter the pipeline
You can refer to the documentation for more detailed examples
{ $skip: 0 },
{ $limit: 10 } // as per your use case
Limit the $lookup result:
Try to limit the result of lookup by $limit stage,
Try to coordinate or balance with improved query and the UI/Use cases
You want to avoid $lookup - How to improve the collection schema to avoid $lookup?
Store the analytics/metrics:
If you are trying to get the total counts of the comments in a particular post then you must store the total count in the post collection whenever you get post get a new comment
{
"_id": ObjectId("5a39e22c27308912334b4567"),
"uid": "0",
"content": "what is hello world mean?",
// new fields
"total_comments": 10
}
Store minimum reference data:
If you want to show the comments of a particular post, you can limit the result for ex: show 5 comments per post
You can also store a max of 5 latest comments in the post collection to avoid the $lookup, whenever you get the latest comment then add it and just remove the oldest comment from 5 comments
{
"_id": ObjectId("5a39e22c27308912334b4567"),
"uid": "0",
"content": "what is hello world mean?",
// new fields
"total_comments": 10,
"comments": [
{
"_id": ObjectId("5a595d8c2703892c3d8b4567"),
"uid": "1",
"comment": "hello world"
},
{
"_id": ObjectId("5a595d8c2703892c3d8b4512"),
"uid": "2",
"comment": "hello stackoverflow"
}
]
}
Must read about Reduce $lookup Operations
Must read about Improve Your Schema

Querying MongoDB (Using Edge Collection - The most efficient way?)

I've written Users, Clubs and Followers collections for the sake of an example the below.
I want to find all user documents from the Users collection that are following "A famous club". How can I find those? and Which way is the fastest?
More info about 'what do I want to do - Edge collections'
Users collection
{
"_id": "1",
"fullname": "Jared",
"country": "USA"
}
Clubs collection
{
"_id": "12",
"name": "A famous club"
}
Followers collection
{
"_id": "159",
"user_id": "1",
"club_id": "12"
}
PS: I can get the documents using Mongoose like the below way. However, creating followers array takes about 8 seconds with 150.000 records. And second find query -which is queried using followers array- takes about 40 seconds. Is it normal?
Clubs.find(
{ club_id: "12" },
'-_id user_id', // select only one field to better perf.
function(err, docs){
var followers = [];
docs.forEach(function(item){
followers.push(item.user_id)
})
Users.find(
{ _id:{ $in: followers } },
function(error, users) {
console.log(users) // RESULTS
})
})
There is no an eligible formula to manipulate join many-to-many relation on MongoDB. So I combined collections as embedded documents like the below. But the most important taks in this case creating indexes. For instance if you want to query by followingClubs you should create an index like schema.index({ 'followingClubs._id':1 }) using Mongoose. And if you want to query country and followingClubs you should create another index like schema.index({ 'country':1, 'followingClubs._id':1 })
Pay attention when working with Embedded Documents: http://askasya.com/post/largeembeddedarrays
Then you can get your documents fastly. I've tried to get count of 150.000 records using this way it took only 1 second. It's enough for me...
ps: we musn't forget that in my tests my Users collection has never experienced any data fragmentation. Therefore my queries may demonstrated good performance. Especially, followingClubs array of embedded documents.
Users collection
{
"_id": "1",
"fullname": "Jared",
"country": "USA",
"followingClubs": [ {"_id": "12"} ]
}
Clubs collection
{
"_id": "12",
"name": "A famous club"
}