
//*****************************  8.1.2   Podstawowe koncepcje indeksowania.

db.products.find({
    'details.manufacturer': 'Acme',
    'pricing.sale': {
      $lt: 7500
    }
  })

//*****************************  8.2.1  Typy indeksów.

//****** Dodanie indeksu unikatowego.
db.users.ensureIndex({username: 1}, {unique: true})

// Przetestowanie indeksu.
db.users.insert({username: "kbanker"})

//******  Przykład usunięcia powielonych danych.

// Najpierw usuwany poprzedni indeks.
db.users.dropIndex({username: 1})

// Można również użyć poniższych poleceń, aby pobrać nazwę indeksu i usunąć go po nazwie.
db.users.getIndexes()
db.users.dropIndex("username_1")

// Dodanie powielonego użytkownika i wyświetlenie dwóch użytkowników o nazwie "kbanker".
db.users.insert({username: "kbanker"})
db.users.find({username: "kbanker"}).pretty()

// Teraz używamy opcji dropDups.
db.users.ensureIndex({username: 1}, {unique: true, dropDups: true})

// Powielony użytkownik został usunięty.
db.users.find({username: "kbanker"}).pretty()

// Usunięcie indeksu.
db.users.dropIndex("username_1")

//******* Indeksy rzadkie.
// Utworzenie dwóch produktów z jedynie nazwą.
db.products.insert([{name: "test 1"},{name: "test 2"}])

// Wyszukanie produktów o kategorii null (powinny być tylko dwa wstawione przed chwilą).
db.products.find({category_ids: null})

// Próba dodania indeksu obejmującego pole "sku" BEZ określenia tego indeksu 
// jako rzadkiego. Operacja powinna zakończyć się niepowodzeniem.
db.products.ensureIndex({sku: 1}, {unique: true})

// Dodanie indeksu rzadkiego - teraz powinno się udać.
db.products.ensureIndex({sku: 1}, {unique: true, sparse: true})

// Usunięcie indeksu.
db.products.dropIndex("sku_1")

// Usunięcie dwóch dodanych przed chwilą produktów.
db.products.remove({sku: null})

// user_id w przykładzie. 
// UWAGA: NIE chcesz unikatowości, ponieważ wówczas użytkownik będzie mógł
// dodać tylko jedną opinię dla dowolnego produktu.
db.reviews.ensureIndex({user_id: 1}, {sparse:  true, unique: false})

// Inny użyteczny sposób na wyszukanie WSZYSTKICH indeksów w bazie danych.
db.system.indexes.find()

// Usunięcie utworzonego przed chwilą indeksu.
db.reviews.dropIndex("user_id_1")

//******* Indeksy hash.
db.products.findOne({name: "Bardzo duża taczka"})

db.recipes.ensureIndex({recipe_name: 'hashed'})


//*****************************  8.2.2  Administracja indeksem.


// *** Utworzenie indeksu obejmującego green.user.
use green
spec = {ns: "green.users", key: {'addresses.zip': 1}, name: 'zip'}
db.system.indexes.insert(spec, true)

// *** Usunięcie indeksu za pomocą rundCommand.
db.runCommand({deleteIndexes: "users", index: "zip"})

// *** Utworzenie nowego indeksu.
db.users.ensureIndex({zip: 1})

// *** Wyświetlenie wyników.
db.users.getIndexes()

// *** Usunięcie indeksu używającego green.
db.users.dropIndex("zip_1")

// *********************** Tworzenie indeksu.
db.values.ensureIndex({open: 1, close: 1})

// *** Nie będą wyświetlone żadne dane, ponieważ nie mamy do czynienia
// z długo wykonywaną operacją tworzenia indeksu.
db.currentOp()

// ********************** Indeksowanie w tle.
// Najpierw usuwamy poprzednią wersję indeksu.
db.values.dropIndex({open:1,close:1})

// Teraz przeprowadzamy indeksowanie w tle.
db.values.ensureIndex({open: 1, close: 1}, {background: true})

// *********************** Defragmentacja.
db.values.reIndex();


//*****************************  8.3.1  Identyfikacja wolno wykonywanych zapytań.

// Pobierz dane z http://mng.bz/ii49.
mongorestore  -d stocks dump/stocks

/*  Na początku możesz zobaczyć...
2015-01-02T11:41:54.221-0800 dump/stocks/values.bson
2015-01-02T11:41:54.221-0800    going into namespace [stocks.values]
2015-01-02T11:41:54.222-0800 dump/stocks/values.metadata.json not found. Skipping.
*/
// Następnie ...
/* .. na końcu.
4308303 objects found
2015-01-02T11:44:47.328-0800 dump/stocks/system.indexes.bson
2015-01-02T11:44:47.329-0800    going into namespace [stocks.system.indexes]
Restoring to stocks.system.indexes without dropping. Restored data will be inserted without raising errors; check your server log
2015-01-02T11:44:47.992-0800    Creating index: { name: "_id_", ns: "stocks.values", key: { _id: 1 } }
1 objects found
*/

//****  Rejestracja wykonywanego zapytania.
Use stocks 
db.values.find({"stock_symbol": "GOOG"}).sort({date: -1}).limit(1)

// Położenie dziennika może być inne. W systemie Ubuntu Server
// to jest plik /var/log/mongodb/mongod.log.
grep -E '([0-9])+ms' mongod.log 
grep -E '[0-9]+ms' mongod.log 

//*** Użycie narzędzia do profilowania zapytań.
db.setProfilingLevel(2)

db.setProfilingLevel(1, 50)

db.values.find({}).sort({close: -1}).limit(1)

//**** Profilowanie danych wyjściowych.

db.system.profile.find({millis: {$gt: 150}})

db.system.profile.find().sort({$natural: -1}).limit(5).pretty() 

//**** Użycie i zrozumienie polecenia Explain.

db.values.find({}).sort({close: -1}).limit(1).explain()

db.values.count()

//**** Dodanie indeksu.
db.values.ensureIndex({close: 1})

db.values.find({}).sort({close: -1}).limit(1).explain()

/* **** PO indeksie.
{
        "cursor" : "BtreeCursor close_1 reverse",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 18,
        "indexBounds" : {
                "close" : [
                        [
                                {
                                        "$maxElement" : 1
                                },
                                {
                                        "$minElement" : 1
                                }
                        ]
                ]
        },
        "server" : "localhost:27017",
        "filterSet" : false
}
*/

//**** Użycie zindeksowanego klucza.
db.values.find({close: {$gt: 500}}).explain()

//**** Optymalizator zapytań MongoDB i hint().
db.values.find({stock_symbol: "GOOG", close: {$gt: 200}})
db.values.find({stock_symbol: "GOOG", close: {$gt: 200}}).explain()

// Teraz dodajemy indeks.
db.values.ensureIndex({stock_symbol: 1, close: 1})
db.values.find({stock_symbol: "GOOG", close: {$gt: 200}}).explain()

db.values.getIndexKeys()

// Wyświetlenie planów zapytania.
db.values.dropIndex("stock_symbol_1_close_1")
db.values.ensureIndex({stock_symbol: 1})
db.values.ensureIndex({close: 1})

db.values.find({stock_symbol: "GOOG", close: {$gt: 200}}).explain(true)

query  = {stock_symbol: "GOOG", close: {$gt: 200}}
db.values.find(query).hint({close: 1}).explain()


//*****************************  8.3.3  Wzorce zapytania.

//**** Indeks w postaci pojedynczego klucza.
db.values.find({close: 100})
db.values.find({}).sort({close: 1})
db.values.find({close: {$gte: 100}})

db.values.find({close: {$gte: 100}}).sort({close: 1}).explain()

//**** Indeks klucza złożonego.

// Aby mieć pewność można utworzyć nowy indeks i usunąć pozostałe.
db.values.ensureIndex({close: 1, open: 1, date: 1})

db.values.dropIndex("date_1")
db.values.dropIndex("stock_symbol_1")
db.values.dropIndex("close_1")
db.values.getIndexes()


db.values.find({}).sort({close: 1})
db.values.find({close: {$gt: 1}})
db.values.find({close: 100}).sort({open: 1})
db.values.find({close: 100, open: {$gt: 1}})
db.values.find({close: 1, open: 1.01, date: {$gt: "2005-01-01"}})
db.values.find({close: 1, open: 1.01}).sort({date: 1})

// Lub dodać polecenie explain() w celu sprawdzenia użytego indeksu.
// OSTRZEŻENIE - wykonanie tego kodu może zabrać nieco czasu.
db.values.find({}).sort({close: 1}).explain()
db.values.find({close: {$gt: 1}}).explain()
db.values.find({close: 100}).sort({open: 1}).explain()
db.values.find({close: 100, open: {$gt: 1}}).explain()
db.values.find({close: 1, open: 1.01, date: {$gt: "2005-01-01"}}).explain()
db.values.find({close: 1, open: 1.01}).sort({date: 1}).explain()

//**** Indeksy pokrywające.
db.ensureIndex({close: 1, open:1, date: 1})
db.values.find({close: 1}, {open: 1, close: 1, date: 1, _id: 0}).explain()

