π $project
Including fields in a projectionβ
A document from the books collection looks like:
{
_id: '0395623650',
title: 'Platero y yo / Platero and I (Spanish-English Bilingual Edition) (English and Spanish Edition)',
authors: [
{
_id: '64cc2db4830ba29148db5180',
name: 'Juan RamΓ³n JimΓ©nez'
}
],
pages: 64,
year: 1994,
synopsis: 'Selections from a classic of world literature present a picture of life in the town of Moguer, in Andalusia, Spain.\n' +
'\n' +
'\n' +
' Presents a picture of life in the town of Moguer, in Andalusia, Spain, as seen through the eyes of a wandering poet and his faithful donkey.\n',
cover: 'https://images.isbndb.com/covers/36/57/9780395623657.jpg',
attributes: [
{
key: 'edition',
value: 'F First Edition Thus'
},
{
key: 'dimensions',
value: 'Height: 10.499979 Inches, Length: 6.999986 Inches, Weight: 2.0502990366 Pounds, Width: 0.12499975 Inches'
},
{
key: 'isbn13',
value: '9780395623657'
},
{
key: 'msrp',
value: 1.99
},
{
key: 'isbn',
value: '0395623650'
},
{
key: 'isbn10',
value: '0395623650'
}
],
totalInventory: 1,
available: 1,
binding: 'Hardcover',
language: 'en',
longTitle: 'Platero y yo / Platero and I (Spanish-English Bilingual Edition) (English and Spanish Edition)',
publisher: 'Clarion Books'
}
If we're interested in the titles, we can use $project to select just the fields we're interested in. As an example, to get just the book's title and year, we'll write:
- Atlas UI
- MongoDB Shell
[
{
$project: { title: 1, year: 1 }
}
]
db.books.aggregate([
{
$project: { title: 1, year: 1 }
}
])
- 1 means, "Show that field." Once you start an inclusion projection, you can't exclude other fields. You just keep adding the fields you want to see.
- 0 means, "Hide that field." Once you start an exclusion projection, you can't include other fields. You just keep adding the fields you don't want to see.
- The primary key
_idfield is shown by default.
So we can exclude fields and show all fields except attributes using:
- Atlas UI
- MongoDB Shell
[
{
$project: { attributes: 0 }
}
]
db.books.aggregate([
{
$project: { attributes: 0 }
}
])
π Show only title and cover.
Answer
- Instruqt
- Atlas UI
- MongoDB Shell
Open the 100_aggregation_pipeline_match file in the Instruqt IDE or GitHub Codespaces. Run the Startup Code, that will import all the neccessary modules and connect to the local MongoDB cluster. Then, run the $project cell. You can then add your code to show only the title and cover fields in a new cell.
const showOnlyTitleAndCover = [
{
$project: { title: 1, cover: 1 }
}
];
const cursor = await books.aggregate( showOnlyTitleAndCover );
await cursor.forEach((b) => {
console.log(b);
});
[
{
$project: { title: 1, cover: 1 }
}
]
db.books.aggregate([
{
$project: { title: 1, cover: 1 }
}
])
Excluding fieldsβ
π Exclude the cover, attributes, and _id fields from the result.
Answer
- Instruqt
- Atlas UI
- MongoDB Shell
Open the 100_aggregation_pipeline_match file in the Instruqt IDE or GitHub Codespaces. Run the Startup Code, that will import all the neccessary modules and connect to the local MongoDB cluster. Then, run the $project cell.
const removeAttributesAndCover = [
{
$project: {_id: 0, attributes: 0, cover: 0}
}
];
const cursor = await books.aggregate( removeAttributesAndCover );
await cursor.forEach((b) => {
console.log(b);
});
[
{
$project: {_id: 0, attributes: 0, cover: 0}
}
]
db.books.aggregate([{$project: {_id: 0, attributes: 0, cover: 0}}])
Including and excluding fieldsβ
You can't include and exclude fields in the same projection. If you start including, you must keep including, and vice versa.
For instance, this will fail:
db.books.aggregate([{$project: {title: 1, attributes: 0}}])
MongoServerError: Invalid $project :: caused by :: Cannot do exclusion on field attributes in inclusion projection
The only exception to this rule is the _id field, which we can exclude in an inclusion projection.
db.books.aggregate([{$project: {title: 1, _id: 0}}])
Challenge πβ
π 1. Find books with more than 2 available copies.β
Answer
- JavaScript
- mongosh
- C#
- Python
- Java
await books.aggregate([
{ $match: {available: {$gt: 2}}}
]).toArray();
db.books.aggregate([
{ $match: {available: {$gt: 2}}}
]);
var pipeline = booksCollection.Aggregate()
.Match(b => b.Available > 2);
var plentifulBooks = pipeline.ToList();
if (plentifulBooks != null)
{
foreach (var book in plentifulBooks)
{
Console.WriteLine($"Title: {book.Title} - Available: {book.Available}");
}
}
else
{
Console.WriteLine("Empty Collection");
}
books_two_copies = books.aggregate([
{"$match": {"available": {"$gt": 2}}}
])
for book in books_two_copies:
print(book)
books.aggregate(
List.of(
Aggregates.match(gt(
"available", 2)))
).forEach(document -> System.out.println(document.toJson()));
π 2. Find books with more than 2 available copies. Return only book titles and publication year.β
Answer
- JavaScript
- mongosh
- C#
- Python
- Java
await books.aggregate([
{ $match: {available: {$gt: 2}}},
{ $project: {title: 1, year: 1, _id: 0}}
]).toArray();
db.books.aggregate([
{ $match: {available: {$gt: 2}}},
{ $project: {title: 1, year: 1, _id: 0}}
]);
var pipeline = booksCollection.Aggregate()
.Match(b => b.Available > 2)
.Project(b => new { b.Title, b.Year });
var plentifulBooks = pipeline.ToList();
if (plentifulBooks != null)
{
foreach (var book in plentifulBooks)
{
Console.WriteLine($"Title: {book.Title} - Year: {book.Year}");
}
}
else
{
Console.WriteLine("Empty Collection");
}
books_two_copies = books.aggregate([
{ "$match": { "available": { "$gt": 2 } } },
{ "$project": { "title": 1, "year": 1, "_id": 0 } }
])
for book in books_two_copies:
print(f"Title: {book['title']} - Publication Year: {book['year']}")
books.aggregate(
List.of(
Aggregates.match(gt(
"available", 2)),
Aggregates.project(Projections.include("title", "year")),
Aggregates.project(Projections.exclude("_id")))
).forEach(document -> System.out.println(document.toJson()));