[MUSIC]. Okay. So, the next system we're going to look at is CouchDB. Which began in 2005, but is still has undergone a lot of updates and is still pretty popular today. And so, this is an example of one of these document-oriented stores that Rick Cattell talked about. And so here, just a look at the features we're talking about here. You got the scale, you got primary index. Now, now we start to see the requirement for secondary indexes. Meaning that you can look up, not just by the key, but by other kinds of values in the document. And we'll see how that's, how that works, okay? And then transactions, also are a little bit better. We can what I mean by record here is that you can change multiple values within a single document of particular. Which is a set of key values pairs, as opposed to just a single key value pair, okay? And then, there actually is some support for analytics, and we'll see how this works, too. This is all through the notion, this concept of views in CouchDB. But, you can actually run little MapReduce scripts to compute derive new values from existing document source, alright? And then, the others we have here is views, which is somewhat unique. You can see this column is fairly sparsely populated. And I hit the concept of views pretty hard when we were talking about relational databases. And argued that it was pretty fundamental to not only the relational model, but a pretty important concept in general. It gave you this notion of logical data independence. And so whenever you see views, that's a good thing. So, CouchDB has those well. Alright. So, the data model here is document-oriented, as we said, where a document is a set of key value pairs. And so here, in this application, you know, these are perhaps blog post where they have a subject, the subject, you know, the key of subject. And the value is some texturing, and they have an author, and they have a date of which they are posted. And they have a set of tags and this is what we said makes it a DOC model. We said it could be sort of nested so this is okay to have a list of objects here. And then they have a body which is another sting fine, and you'll notice that this is actually Jason compliant. We looked at Jason in the Twitter assignment, and so it's another occurrence of this. And one of the reasons why I want to make sure your working with Jason before, is it does get popular. It's a CouchDB, all data's are presented in Jason, and all the request Macro represented in Jason as well, okay? So, how do updates work in this context? Well, as I mentioned, they you know, you can make, it is fully transactional within, within a single document. So, full consistency within a document, meaning that I can sort of grab hold of the document and logically sort of lock it. And up, make whatever updates I want. Now, it doesn't actually take a lock because it uses what's called Optimistic Concurrency Control. Meaning, that it sort of assumes that, that conflicts aren't going to happen optimistically. And so now, if I, if I check out that document and try to make updates to it, anywhere I want, all throughout it, and then try to commit that change. Somewhere else is doing this same has done this as committed their own team to this. In the meantime, my changes will fail, but we assume that, that doesn't happen that often. So, it's okay to just sort of fail in those, in those cases. And really all you have to do in cases like this his check out the new changes and make whatever changes you want. Fine. But there is no multi-row transactions. What I mean by multi-row here is multi-document. There's no, let's say for example I update my status. I have to update my document that describes my current state of the world. But may be I also want to update all of my friends Walls, right? Their, their pages to, with, that reflects my new status. And you can't guarantee that that happens synchronously in CouchDB. But, you know, in this particular application and in many others, maybe that's okay. All right. You know, you can do it in two separate steps. You update your status, and then you update theirs. And there will be a period of time when their, you know, view of your current status is out of date, but maybe that's all right. Fine. Alright, so this notion of views works like this. A view specification, which is in itself, a CouchDB document, a set of key value pairs. But it's sort of a special one looks like this. There's some metadata information here, and then there's this key views which is, which is a dictionary of things. And so, this this specification has three views in it, one called all, one called by lastname, and one called total purchases. And each one of these views is going to be is implementing a set of key value pairs. I'm just going to be implementing a dictionary. And so the all view, okay? So, fine. So, how are these implemented? Well, you know, it's, speaking of recurring concepts. Views are recurring from logical independence to relational databases. and here, MapReduce is recurring even, outside the context of literally Hadoop, okay? And so here, the map function, reduce function, are actually written in JavaScript. Again, everything in CouchDB is JavaScript, and they look like this. So, the all view has just the map function, no reduce function. And in JavaScript, you can write these anonymous functions like in, in this sort of syntax. So, this function doesn't have a name, it just says, hey, I've, I've got to function with no name, with a single argument called doc. And the body looks like this, it says, if doc.Type equals customer, then emit a key value pair, or the key is null and the value is doc. So, we don't really care about the key in that case, we just care about the doc. Alright, so this is all customers. Fine. The by last name view, you can imagine, the key is going to be last name in this case. And so here, we have another anonymous function. If doc.Type equals customer, then emit the last name, followed by the entire document. And so now, this allows clients to search efficiently by last name, and these views will, are in custody or computed. You know, they materialize sort of eagerly and stored in these distributed BG struct index structures just for various look-ups. And, so this is how they implement those secondary indexes in that column in our, in our table, okay? So now, we can look-up by last name as well as by document ID. And so, you can even go a little further, you don't have to just do simple key-value pairs, you can even do a little bit of computation. So total purchases here, the map function again, takes in a document and says, well, if doc.Type equals purchase. So, I'm not talking about customers anymore, just purchases. Then, emit the key of doc.Customer and the value of doc.Amount. But then, we're also going to find a reduce function and the reduce function adds up all the values of the amounts. And to here, we have given a customer, if I have give you a customer, you can return it's the total amount of all it's purchases, okay? And CouchDB maintains all these views as things change with eventual consistency sort of semantics. And so, we have a lot of things going on here with one concept. We have secondary indexes, we have logical data independents, we have MapReduce computation, okay? So, I had checked the box in the table saying the CouchDB could do joins in analytics. And it's not really quite true there somewhat limited, so let me show you an example of how they do, sort of join. So, they have this concept of view coalition, and what you can do here is write a map function in a view that looks like this. And so, here we're tying to group together all the comments associated with a post. So, it's sort of a join between the comments table, if you will, and, and the post, the blog posts table. And so, this map function is the same kind of thing we did in the MapReduce assignment to do a join. This is what you have to do when you do a join in MapReduce is you take, you pretend like the whole collection of documents. Regardless of type, regardless of source relation Is one big set of objects. And in your map function, you sort out which one's which and make sure to hash on the same key. So here, the ID of the document post and then in this document .docpost refers to some post ID. That's now post ID go to one. And all the comments associated with post id equals one will go together. But they do this funny thing. They say the key here in the key value pair is DOC ID identity followed by the number zero in the one case, and the number one in the other case. And what's happened here is that all, everything in Mac, in CouchDB is sorted. And so, you got things sorted by document ID and then sorted by this exturbate. So, now you have the post ID coming first, then all the comments coming second. And now, which you could, you know, you think you could just do a reduce function to actually compute the join that you might want. But it turns out reduce functions don't quite work that way, and there's some scalability issues. So, what people recommend is to do this view collation trick where you still spit out the data in sorted order, but then you can query it. Say a client application could query it like this where they say, start key is just a post ID without the extra prefix at all. And the end key is post ID with the number two. So, now this gets the full range of the post Id with, which has the key of zero, followed by all the comments for the post ID in one. So, you got everything in one big list. And now, you can process it in order to show a shape say in the application. So, you essentially constructed the join by cheating with the order, okay? So, fine. So perhaps, you could argue that you have some joins and analytics, but it's a bit glib to say so.