Наталья Аксёнова
Теорема CAP - эвристическое утверждение о том, что в любой реализации распределённого хранения возможно обеспечить не более двух из трёх следующих свойств: согласованность данных, доступность, устойчивость к разделению.
(англ. consistency) — во всех узлах системы в один момент времени данные не противоречат друг другу
(англ. availability) — каждый клиент всегда может читать и писать, если жив хотя бы один узел системы
(англ. partition tolerance) — расщепление распределенной системы на несколько изолированных секций не приводит к некорректности отклика каждой из секций
Frontend | Backend | Database |
Javascript | Javascript | Javascript |
db.notes.insert({
name: 'Films',
text: 'My films',
owner: 'Наталья'
})
db.notes.insert([
{
name: 'Заметка без владельца',
text: 'Чья это заметка?'
},
{
name: 1,
owner: 'Наталья'
},
{
some: 'field'
}
])
📄 🤷 ❓
db.createCollection("notes", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "owner"],
properties: {
name: { bsonType: "string", description: "Note title" },
text: { bsonType: "string", description: "Note text" },
owner: {
anyOf: [
{ bsonType: "string" },
{ bsonType: "array", items: { bsonType: "string" } }
],
description: "Name of owner"
}
}}}})
db.notes.insert(
{ name: 'Films', text: 'My films', owner: 'Наталья' }
)
// WriteResult({ "nInserted" : 1 })
db.notes.insert({
name: 'Books',
owner: 'Наталья',
version: 2
})
// WriteResult({ "nInserted" : 1 })
db.notes.insert({ name: 1, owner: 'Наталья' })
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
db.notes.find()
{ "_id" : ObjectId("5ab77143f92855790b23a184"), "name" : "Films", "text" : "my films", "owner" : "Наталья" }
{ "_id" : ObjectId("5ab77159f92855790b23a185"), "name" : "Books", "owner" : "Наталья", "version" : 2 }
db.notes.find().pretty()
{
"_id" : ObjectId("5ab77143f92855790b23a184"),
"name" : "Films",
"text" : "My films",
"owner" : "Наталья"
}
{
"_id" : ObjectId("5ab77159f92855790b23a185"),
"name" : "Books",
"owner" : "Наталья",
"version": 2
}
db.notes.find().toArray()
[
{
"_id" : ObjectId("5ab77143f92855790b23a184"),
"name" : "Films",
"text" : "my films",
"owner" : "Наталья"
},
{
"_id" : ObjectId("5ab77159f92855790b23a185"),
"name" : "Books",
"owner" : "Наталья",
"version": 2
}
]
ObjectId("5ab77143f92855790b23a184")
4 байта | timestamp |
3 байта | mid |
2 байта | pid |
3 байта | inc |
db.collection.find(query, projection)
db.notes.find({ name: 'Films' })
{
"_id" : ObjectId("5ab77143f92855790b23a184"),
"name" : "Films",
"text" : "My films",
"owner" : "Наталья"
}
db.notes.find({ owner: 'Наталья' }, { name: 1 })
{
"_id" : ObjectId("5ab77143f92855790b23a184"),
"name" : "Films"
}
{
"_id" : ObjectId("5ab77159f92855790b23a185"),
"name" : "Books"
}
db.notes.find({ owner: 'Наталья' }, { name: 1, _id: 0 })
{
"name" : "Films"
}
{
"name" : "Books"
}
db.notes.find({
version: { $gte: 2 }
})
Список операторов
db.notes.find({
text: { $regex: /^my/i}
})
db.notes.find({
text: /^my/i
})
{
"_id" : ObjectId("5ab77143f92855790b23a184"),
"name" : "Films",
"text" : "My films",
"owner" : "Наталья"
}
Поиск по регулярным выражениям
{
"name" : "Books",
"owner" : "Наталья"
}
{
"name" : "Films for party",
"owner" : [ "Наталья", "Анна" ]
}
{
"name" : "Music",
"owner" : "Вася"
}
db.notes.find(
{ owner: 'Наталья' },
{ _id: 0, name: 1, owner: 1 }
)
{
"name" : "Books",
"owner" : "Наталья"
}
{
"name" : "Films for party",
"owner" : [ "Наталья", "Анна" ]
}
db.notes.find({
'score.likes': { $gte: 1 }
})
{
name: 'Films',
owner: 'Наталья',
score: {
likes: 10,
dislikes: 2
}
}
db.notes.find({}, { _id: 0, owner: 1, name: 1 })
{ "name" : "Music", "owner" : "Вася" }
{ "name" : "Films", "owner" : "Наталья" }
{
"name" : "Films for party",
"owner" : [ "Наталья", "Анна" ]
}
{ "name" : "Books", "owner" : "Наталья" }
db.notes
.find({}, { _id: 0, name: 1, owner: 1 })
.sort({ name: 1 })
{ "name" : "Books", "owner" : "Наталья" }
{ "name" : "Films", "owner" : "Наталья" }
{ "name" : "Films for party", "owner" : [ "Наталья", "Анна" ] }
{ "name" : "Music", "owner" : "Вася" }
db.notes
.find({}, { _id: 0, name: 1, owner: 1 })
.limit(2)
{ "name" : "Films", "owner" : "Наталья" }
{ "name" : "Books", "owner" : "Наталья" }
db.notes
.find({}, { _id: 0, name: 1, owner: 1 })
.skip(2)
{
"name" : "Films for party",
"owner" : [ "Наталья", "Анна" ]
}
{
"name" : "Music",
"owner" : "Вася"
}
db.notes
.find({}, { _id: 0, name: 1, owner: 1 })
.sort({ name: 1 })
.skip(2)
.limit(1)
{
"name" : "Films for party",
"owner" : [ "Наталья", "Анна" ]
}
db.notes.count({ owner: 'Наталья' }) // 3
db.notes.count() // 4
db.collection.update(query, update, options)
Список update операторов
db.notes.update(
{ version: { $exists: false }}, // query
{ $set: { version: 1 }} // update
)
{ "name" : "Films", "version" : 1 }
{ "name" : "Books", "version" : 2 }
{ "name" : "Films for party" }
{ "name" : "Music" }
db.notes.update(
{ version: { $exists: false }},
{ $set: { version: 1 }},
{ multi: true }
)
{ "name" : "Films", "version" : 1 }
{ "name" : "Books", "version" : 2 }
{ "name" : "Films for party", "version" : 1 }
{ "name" : "Music", "version" : 1 }
db.notes.update(
{ name: 'Books' },
{ $inc: { version: 1 }}
)
{ "name" : "Books", "version" : 3 }
db.notes.update(
{ name: 'Films for party' },
{ $push: { owner: 'Катя' }}
)
{
"name" : "Films for party",
"owner" : [ "Наталья", "Анна", "Катя" ]
}
db.collection.remove(query, justOne)
db.notes.remove({})
db.notes.remove({}, true)
db.users.insert({
name: 'Наталья',
notes: ['Films', 'Books', 'Films for party']
})
db.notes.remove(
{ name: 'Films', owner: 'Наталья' }
)
db.users.update(
{ name: 'Наталья' },
{ $pull: { notes: 'Films' }}
)
db.notes.remove(
{ name: 'Films', owner: 'Наталья' }
)
db.users.update(
{ name: 'Наталья' },
{ $pull: { notes: 'Films' }}
)
db.notes.count() // 1 000 004
db.notes.count({ owner: 'Наталья' }) // 3
db.notes
.find({ owner: 'Наталья' })
.explain('executionStats')
{
"nReturned" : 3,
"executionTimeMillis" : 389,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1000004,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"owner" : { "$eq" : "Наталья" }
}
}
}
db.notes.createIndex({owner: 1})
db.notes
.find({ owner: 'Наталья' })
.explain('executionStats')
{
"nReturned" : 3,
"executionTimeMillis" : 19,
"totalKeysExamined" : 3,
"totalDocsExamined" : 3,
"executionStages" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
}
}
}
db.users.createIndex({name: 1}, {unique: true})
db.users.insert({name: 'Наталья'})
WriteResult({ "nInserted" : 1 })
db.users.insert({name: 'Наталья'})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key
error collection:
notes-lecture.notes
index: name_1 dup key: { : \"Наталья\" }"
}
})
db.notes.createIndex(
{
'score.likes': -1,
name: 1
}
)
db.notes
.find()
.sort({ 'score.likes': -1, name: 1 })
.explain()
{
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"score.likes" : -1,
"name" : 1
},
"indexName" : "score.likes_-1_name_1"
}
}
db.notes
.find()
.sort({ 'score.likes': 1, name: 1 })
.explain()
{
"stage" : "SORT",
"sortPattern" : {
"score.likes" : 1,
"name" : 1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "COLLSCAN",
"direction" : "forward"
}
}
}
db.notes.getIndexes()
[
{
"v" : 2,
"key" : { "_id" : 1 },
"name" : "_id_",
"ns" : "notes-lecture.notes"
},
{
"v" : 2,
"key" : { "owner" : 1 },
"name" : "owner_1",
"ns" : "notes-lecture.notes"
}
]
npm install mongoose
const mongoose = require('mongoose');
const URI = 'mongodb://localhost/mongo-lecture';
mongoose.connect(URI).then(
() => { /** ready to use */ },
err => { /** handle initial connection error */ }
)
const Schema = mongoose.Schema;
const noteSchema = new Schema({
name: { type: String, required: true },
text: String,
owner: { type: [String], required: true }
});
Подробнее про схемы
noteSchema.add({
version: { type: Number, default: 1 }
});
String | Number |
Date | Buffer |
Boolean | Array |
ObjectID | Mixed |
const userSchema = new Schema({
name: {
type: String, index: true, unique: true
},
notes: [String]
});
noteSchema.index({ owner: 1, name: 1 });
const Note = mongoose.model('Note', noteSchema);
const films = new Note({
name: 'Films',
owner: 'Наталья',
text: 'My films'
});
console.log(films.name); // "Films"
console.log(films.owner); // ["Наталья"]
console.log(films.version); // 1
noteSchema.virtual('nameAndVersion').get(function () {
return `${this.name}, версия ${this.version}`;
});
const Note = mongoose.model('Note', noteSchema);
const films = new Note({
name: 'Films',
owner: 'Наталья'
});
console.log(films.nameAndVersion); // Films, версия 1
const books = new Note({
name: 'Books',
owner: 'Наталья'
});
books
.save()
.then(function (savedNote) {console.log('Saved')})
.catch(function (err) {console.log('Error:', err)});
const query = Note.find({owner: 'Наталья'});
query.where({version: {$gte: 2}});
query.select({name: 1, owner: 1});
query.exec()
.then(note => { console.log('found note': , note) })
.catch(err => { console.log('error: ', err) });
[ { owner: [ 'Наталья' ],
_id: 5ab77159f92855790b23a185,
name: 'Books' } ]
Note
.find({ version: { $gte: 1 }})
.sort({ owner: 1, name: 1 })
.skip(1)
.limit(20)
.select({ owner: 1, name: 1, version: 1 })
.exec();
note.update({ $inc: { version: 1 }})
Note
.findById(ObjectId("5ab77143f92855790b23a184"))
.then(note => {
note.text += ' new text';
return note.save();
})
.then(saved => {
console.log('saved successfully!', saved);
});
Note
.update(
{},
{ $inc: { version: 1 }},
{ multi: true }
)
.then(() => {console.log('updated'})
Note.remove({name: 'Books'})