// Sekcja 6.4.6. Pozostałe funkcje.

// $size
db.products.aggregate([
    {$project:
    {_id: 0,
        productName: '$name',
        tags:1,
        tagCount: {$size:'$tags'}}
    }
])

//    /*  Oczekiwane wyniki.
//
//     { "productName" : "Bardzo duża taczka",
//     "tags" : [ "narzędzia", "ogród", "ziemia" ],
//     "tagCount" : 3 }
//
//     { "productName" : "Gumowe rękawice robocze, kolor czarny",
//     "tags" : [ "ogród" ],
//     "tagCount" : 1 }
//
//     */

// $literal
// Przyjmujemy założenie, że chcemy utworzyć pole o nazwie useCount
// i przypisać mu wartość 0.
db.categories.aggregate([
    {$project: {categoryName: '$name',
        useCount: 0
    }
    },
    {$out: 'categoryUseCount'}
])




//    /* Wynik.
//
//     assert: command failed: {
//     "errmsg" : "exception: The top-level _id field is the only field currently supported for exclusion",
//     "code" : 16406,
//     "ok" : 0
//     } : aggregate failed
//
//     Co? Co się stało?
//
//     Z perspektywy MongoDB próbujemy wykluczyć pole 'useCount', więc serwer
//     informuje, że można wykluczyć jedynie pole '_id'.
//
//     Ratunkiem jest użycie $literal.
//
//     */

db.categories.aggregate([
    {$project:
    {_id: 0,
        categoryName: '$name',
        useCount: {$literal: 0}}   //1
    },
    {$out: 'categoryUseCount'}
])

//    /*  Oczekiwane wyniki.
//
//     { "categoryName" : "Narzędzia ogrodowe", "useCount" : 0 }
//
//
//     /*  Co w poniższym przypadku?
//
//     db.categories.aggregate([
//     {$project:
//     {categoryName: '$name',
//     useCount: -2 }          //1
//     },
//     {$out: 'categoryUseCount'}
//
//     ])
//
//     db.categories.aggregate([
//     {$project:
//     {categoryName: '$name',
//     name: 0 }          //1
//     },
//     {$out: 'categoryUseCount'}
//     ])
//
//
//     */

db.categories.aggregate([
    {$project: {
        someNumber: 3}
    }
]);

db.categories.aggregate([
    {$project: {
        someNumber: {$literal: 3}}
    }
]);

// Błędne podejście.

db.categories.aggregate([
    {$project: {
        dollarSign: '$'}
    }
]);

// Prawidłowe podejście.
db.categories.aggregate([
    {$project: {
        dollarSign: {$literal: '$'}}
    }
]);

//    /* Wynik.
//
//     assert: command failed: {
//     "errmsg" : "exception: '$' by itself is not a valid FieldPath",
//     "code" : 16872,
//     "ok" : 0
//     } : aggregate failed
//
//     */

db.categories.aggregate([
    {$project:
    {catgyName: '$name',
        someNumber: {$literal: 3},
        dollarSign: {$literal:'$'}}
    }
]);

//    /*
//     { "catgyName" : "Narzędzia ogrodowe", "userCount" : 0, "numberOne" : 1, "dollarSign" : "$" }
//
//     Próbujemy NumberOne: opcja 1 jest szczególnie myląca. Nie powoduje
//     błędu, ale pole nie jest wyświetlane. Podobnie użycie $cokolwiek
//     nie spowoduje wygenerowania błędu.
//
//     */

db.categories.aggregate([
    {$project: {_id: 0,
        catgyName: '$name',
        numberOne: 1,
        dollarSign: '$something'
    }
    }
]);

//    /* Wartość zwrotna - brakujące pola dla numberOne i dollarSign.
//
//     { "catgyName" : "Narzędzia ogrodowe" }
//
//
//     */

// ******************* $map

//    /*
//
//     { skews: [ 1, 1, 2, 3, 5, 8 ] }
//
//     Poniższe użycie polecenia $project:
//
//     { $project: { adjustments: { $map: { input: "$skews",
//     as: "adj",
//     in: { $add: [ "$$adj", 12 ] } } } } }
//
//     Funkcja $map przekształci dokument danych wejściowych na następujący
//     dokument danych wyjściowych.
//
//     { adjustments: [ 13, 13, 14, 15, 17, 20 ] }
//
//     Wcześniej widziałaś jak konwersja powoduje utworzenia wiersza
//     podsumowania na podstawie ilości sztuk produktu i jego nazwy.
//     W tym celu wykorzystaliśmy $let i $substring. Teraz zobaczysz
//     jeszcze inną wersję. W omawianym przykładzie pobieramy pojedyncze
//     zamówienie, a następnie konwertujemy tablicę wierszy zamówienia na
//     tablicę podsumowania nie używając przy tym $unwind.
//
//
//
//     */


db.orders.aggregate([
    {$project: {
        orderSummary: {
            $map: {
                input: '$line_items',
                as: 'item',
                in: {
                    $concat: [
                        {$substr:['$$item.quantity',0,10]},
                        ' ', '$$item.name']
                }
            }
        }}
    }
]).pretty()

db.orders.aggregate([
    {$project: {
        orderSummary: {
            $map: {
                input: '$line_items',
                as: 'item',
                in: {
                    descr: {$concat: [
                        {$substr:['$$item.quantity',0,10]},
                        ' ', '$$item.name']},
                    price: '$$item.pricing.sale'
                }
            }
        }}
    }
]).pretty()


// ******************* $let

//    /* Wcześniej w sekcji dotyczącej funkcji ciągu tekstowego - $substr,
//     pokazałem potok konwertujący liczbę na postać ciągu tekstowego.
//     Wykorzystamy dwa operatory $project w celu przygotowania przykładu 
//     znacznie łatwiejszego do zrozumienia. Jednak można zrobić coś podobnego,
//     zdefiniować skomplikowane wyniki pośrednie za pomocą funkcji $let.
//
//
//     */

db.orders.aggregate([
    {$unwind: '$line_items'},
    {$project: {
        orderSummary: {
            $let: {
                vars: {
                    orderQuantity:                                 //1
                    {$substr:['$line_items.quantity',0,10]}
                },
                in: {                                              //2
                    $concat: ['$$orderQuantity', ' ',
                        '$line_items.name']
                }
            }
        }
    }}
])


//    /* Oczekiwane wyniki.
//
//     { "_id" : ObjectId("6a5b1476238d3b4dd5000048"),
//     "orderSummary" : "1 Bardzo duża taczka" }
//     { "_id" : ObjectId("6a5b1476238d3b4dd5000048"),
//     "orderSummary" : "2 Gumowe rękawice robocze, kolor czarny" }
//
//     */
