
// *********************  7.2.1 Produkty i kategorie.

// Średnia ocena produktu.

product_id = ObjectId("4c4b1476238d3b4dd5003982")
count = 0
total = 0
db.reviews.find({product_id: product_id}, {rating: 1}).forEach(
  function(review) {
    total += review.rating
    count++
  })
average = total / count
db.products.update({_id: product_id}, 
  {$set: {total_reviews: count, average_review: average}}) 
  
// Wynik: WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

// Sprawdzenie wyniku.
db.products.findOne({_id: product_id},{total_reviews:1,average_review:1})

/* Wynik.
{
        "_id" : ObjectId("4c4b1476238d3b4dd5003982"),
        "total_reviews" : 2,
        "average_review" : 3.5
}
*/

product_id = ObjectId("4c4b1476238d3b4dd5003982")
average = 3.5
total = 7

db.products.update({_id: product_id},
  {
    $set: {
      average_review: average,
      ratings_total: total
    },
    $inc: {
      total_reviews: 1
    }
  })

// Wynik: WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

// Odczyt wyniku.
db.products.findOne({_id: product_id},{total_reviews:1,ratings_total:1,average_review:1})

/* Wynik (wartość total_reviews może być inna).
{
        "_id" : ObjectId("4c4b1476238d3b4dd5003982"),
        "total_reviews" : 3,
        "average_review" : 3.5,
        "ratings_total" : 7
}
*/

// Hierarchia kategorii.
var generate_ancestors = function(_id, parent_id) {
  ancestor_list = []
  var cursor = db.categories.find({_id: parent_id})
  while(cursor.size() > 0) {
    parent = cursor.next()
    ancestor_list.push(parent)
    parent_id = parent.parent_id
    cursor = db.categories.find({_id: parent_id})
  }
  db.categories.update({_id: _id}, {$set: {ancestors: ancestor_list}})
}

// Poniższy kod nie działa bez zdefiniowania parent_id.
// Potrzebne są inne dane aktualnie nie znajdujące się w db.
category = {
  parent_id: parent_id,
  slug: "ogrod",
  name: "ogród",
  description: "Wszystko, co jest niezbędne w ogrodzie - narzędzia, nasiona i ziemia."
}
db.categories.save(category)
generate_ancestors(category._id, parent_id)

// Tutaj również potrzebujemy outdoors_id oraz więcej danych.
db.categories.update({_id: outdoors_id}, {$set: {parent_id: gardening_id}})

db.categories.find({'ancestors.id': outdoors_id}).forEach(
  function(category) {
    generate_ancestors(category._id, outdoors_id)
  })

// ***** Wielokrotne uaktualnienie - użycie outdoors_id w celu przetestowania składni.
outdoors_id = ObjectId("4c4b1476238d3b4dd5003982")
doc = db.categories.findOne({_id: outdoors_id})
doc.name = "Doskonałe na zewnątrz"
db.categories.update({_id: outdoors_id}, doc)
db.categories.update(
  {'ancestors._id': outdoors_id},
  {$set: {'ancestors.$': doc}},
  {multi: true})

  
// *** Uaktualnienie za pomocą operatora '$'.
db.users.update({
      _id: ObjectId("4c4b1476238d3b4dd5003981"),
      'addresses.name': 'work'},
      {$set: {'addresses.$.street': '155 E 31st St.'}})

// Wynik: WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

// ***************** 7.2.2 Opinie o produkcie.

db.reviews.update({_id: ObjectId("4c4b1476238d3b4dd5000041")}, {
    $push: {
      voter_ids: ObjectId("4c4b1476238d3b4dd5000001")
    },
    $inc: {
      helpful_votes: 1
    }
  })

// Wynik: WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

// **** Lepszy sposób przeprowadzenia modyfikacji.
query_selector = {
  _id: ObjectId("4c4b1476238d3b4dd5000041"),
  voter_ids: {
    $ne: ObjectId("4c4b1476238d3b4dd5000001")
  }
}

db.reviews.update(query_selector, {
    $push: {
      voter_ids: ObjectId("4c4b1476238d3b4dd5000001")
    },
    $inc : {
      helpful_votes: 1
    }
  })

// Wynik: WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
// (Ponieważ już dodaliśmy głos).

// ***************** 7.2.3 Zamówienia.

cart_item = {
  _id:  ObjectId("4c4b1476238d3b4dd5003981"),
  slug: "taczka-9092",
  sku:  "9092",
  name: "Bardzo duża taczka",
  pricing: {
    retail: 5897,
    sale:   4897
  }
}

selector = {
  user_id: ObjectId("4c4b1476238d3b4dd5000001"),
  state: 'CART'
}

update = {
  $inc: {
    sub_total: cart_item['pricing']['sale']  
  }
}

db.orders.update(selector, update, {upsert: true}) 

// Wyszukanie zamówienia - użycie find(...) do potwierdzenia, że jest tylko jedno.
db.orders.find(selector).pretty()


// Dodanie produktu, jeśli nie istnieje.
selector = {user_id: ObjectId("4c4b1476238d3b4dd5000001"),
    state: 'CART',
    'line_items._id':
        {'$ne': cart_item._id}
    }
    
update = {'$push': {'line_items': cart_item}}
db.orders.update(selector, update)

// Inkrementacja liczby produktu (już uaktualniono wartość sub_total zamówienia).
selector = {
  user_id: ObjectId("4c4b1476238d3b4dd5000001"),
  state: 'CART',
  'line_items._id': ObjectId("4c4b1476238d3b4dd5003981")
}
update = {
  $inc: {
    'line_items.$.quantity': 1 
  }
}
db.orders.update(selector, update)

// Ponowne wyszukanie zamówienia.
selector = {
  user_id: ObjectId("4c4b1476238d3b4dd5000001"),
  state: 'CART'
}
db.orders.find(selector).pretty()


