When a document is associated with another document (e.g. as address connected to a customer), how does notes stores the information? Does it create a new document to represent the association or does it tags the linked document as a response document?
I'm guessing you're asking because you are reviewing someone else's database, but in case you're starting from scratch and want to know the best approach I'll answer that too.
The short answer:
Notes isn't relational. I'd bet the address is stored in the same document as the customer.
The long answer:
If there are separate customer and address documents, there are usually some loose connections between the documents, perhaps based on a UniqueID field or perhaps just a name. For instance, the customer form might look up to an address view and pick that address based on the customer's name, meaning the address documents have the customer's name stored on them.
Sometimes a link can be created via the parent/child relationship of documents and responses, but that's more often used in discussion thread databases or very special cases.
Ultimately it's up to the developer of the Notes application to decide how to link the data. My suggestion, especially if you come from a relational db background, is to use the #UniqueID formula in a hidden text field that is computed on compose. That will stamp a GUID on your document and you can use that for referencing the document like you would a foreign key to a table. That helps to keep data somewhat normalized.
There is no automatic way that Notes associates one document with another, except for response documents, which when created get set with a $REF item that include the GUID of the parent document. Again, this isn't an ideal way to relate documents like customers and addresses because the relationship can't be leverage to make development easier. The document/response hierarchy is mostly just useful for organizing documents within a view.
Related
I'm currently trying to learn Node.js and Mongoodb by building the server side of a web application which should manage insurance documents for the insurance agent.
So let's say i'm the user, I sign in, then I start to add my customers and their insurances.
So I have 2 collection related, Customers and Insurances.
I have one more collection to store the users login data, let's call it Users.
I don't want the new users to see and modify the customers and the insurances of other users.
How can I "divide" every user related record, so that each user can work only with his data?
I figured out I can actually add to every record, the _id of the one user who created the record.
For example I login as myself, I got my Id "001", I could add one field with this value in every customer and insurance.
In that way I could filter every query with this code.
Would it be a good idea? In my opinion this filtering is a waste of processing power for mongoDB.
If someone has any idea of a solution, or even a link to an article about it, it would be helpful.
Thank you.
This is more a general permissions problem than just a MongoDB question. Also, without knowing more about your schemas it's hard to give specific advice.
However, here are some approaches:
1) Embed sub-documents
Since MongoDB is a document store allowing you to store arbitrary JSON-like objects, you could simply store the customers and licenses wholly inside each user object. That way querying for a user would return their customers and licenses as well.
2) Denormalise
Common practice for NoSQL databases is to denormalise related data (ie. duplicate the data). This might include embedding a sub-document that is a partial representation of your customers/licenses/whatever inside your user document. This has the similar benefit to the above solution in that it eliminates additional queries for sub-documents. It also has the same drawbacks of requiring more care to be taken for preserving data integrity.
3) Reference with foreign key
This is a more traditionally relational approach, and is basically what you're suggesting in your question. Depending on whether you want the reference to be bi-directional (both documents reference each other) or uni-directional (one document references the other) you can either store the user's ID as a foreign user_id field, or store an array of customer_ids and insurance_ids in the user document. In relational parlance this is sometimes described to as "has many" or "belongs to" (the user has many customers, the customer belongs to a user).
I have two forms, Company and Client. A company can have any number of clients, and a client can be a client of any number of companies. I want to be able to do things like list a given company's clients, or list the companies that a given client employs. What is the best way to deal with this using the Domino database structure?
That's no problem.
Create categorized views for companies and for clients. Then, store the company names on each client document and client names on each company document. Use a single-category embedded view to list them on each form. Clicking on the name in the embedded view opens the document.
Or, create a third form type for company-client relationships and use that to populate the embedded view.
First a question: what's the difference between a Client and a Company? A relation could then simply be represented by a multi-value field ClientOf that stores the keys of one or more other companies. If you want to find all clients of company X, you need a categorized view with the ClientOf field in the first column.
I suppose your problem is not (going to be) so much the creation of the relationship as well the maintenance. You have to maintain everything yourself, i.e. when a company is removed, you have to remove all references to the company yourself, from the ClientOf field. When you use keys created using #Unique, you won't have to worry about a name change of the Company. On the other hand, you always have to do an extra lookup to find its real name.
We're looking into using CouchDB/CouchCocoa to replicate data to our mobile app.
Our system has a large number of users. Part of the database is private to each user -- for example their tasks. These I've been able to replicate without problem using filtered replication.
Here's the catch... The database also includes shared information only some of which pertains to a given user. How do I selectively replicate that shared information? For example a user's task might reference specific shared documents. Is there a way to make sure those documents are included in the replication without including all the shared documents?
From the documentation it seems that adding doc_ids to the replication (or adding another replication with those doc ids) might be one solution. Has any one tried this? Are there other solutions?
EDIT: Given the number of users it seems impractical to tag each shared document with all the users sharing it but perhaps that's the only way to do this?
Final solution mostly depends on your documents structure, but currently I see two use-cases:
As you keep everything within single database, probably you have some fields set to recognize, that document is shared or document is private, right? Example:
owner: "Mike"
participants: [] // if there is nobody mentioned, document looks like as private(?)
So you just need some filter that would handle only private documents and only shared ones: by tags, number of participants, references or somehow.
Also, if you need to replicate some documents only for specific user (e.g. only for Mike), than you need special view to handle all these documents and, yes, use replication by document ids, but this wouldn't be an atomic request: you need some service script to handle these steps. If shared documents are defined by references to them, than the only solution is the same: some service script, view that generated document reference tree and replication by doc._id's.
Review your architecture. Having per user database is normal use-case for CouchDB and follows way of data partitioning and isolation. So you may create per user database that would be private only for that user. For shared documents you may create additional databases playing with database members of security options. Each "shared" database will handle only certain number of participants by names or by groups, so there couldn't be any data leaks unless that was not a CouchDB bug(:
This approach looks too weird from first sight, but everything you've needed there is to create some management script that would handle database creation and publication, replications would be easy as possible and users data is in safe.
P.S. I've supposed that "sharing" operation makes document visible not for every one, but for some set of users. If I was wrong and "shared" state means "public" state than p2. will be more simpler: N users databases + 1 public one.
Just what it says on the tin. I have a bunch of (say) Member documents, I want each user to be able to set the Email field on his document to whatever he wants, example an Email that exists on another document. If I just do a check-insert, I'm vulnerable to a race condition. Is there some idiom for "locking" or inserting-then-checking?
The only sure way is to create a doc with the unique value as doc id.
As the other answer notes, the only field guaranteed to be unique in CouchDB is _id.
You might borrow a trick from the replicator here. In order to fast-forward a second replication between the same two hosts, it writes a checkpoint document which records the update sequence it last reached. But how does it find the checkpoint document in the future? Like so;
"_id": md5(source.host + source.port + target.host + target.port)
A general pattern can be extracted where your unique fields form part of the id itself. Running them through md5 guarantees a fixed length identifier.
In your case, you could just use email address as your id.
Changing one of these fields is a two step process, but one that still maintains the uniqueness property.
Copy the document to its new id (http://wiki.apache.org/couchdb/HTTP_Document_API#COPY)
If successful, delete the old one (http://wiki.apache.org/couchdb/HTTP_Document_API#DELETE)
A crash between steps 1 and 2 will leave the old document it place, so you may wish to add a reference to the old document in the new document. You can then create a view of those back references and perform a clean up sweep periodically.
All that said, CouchDB deliberately only supports only one unique field, as opposed to a typical RDBMS which can support elaborate relational constraints, in order for a solution to scale up cleanly in a cluster (c.f, BigCouch). In your case, where email address must be unique, much of what I've said should work (email addresses don't change that often), but obviously this is swimming upstream to a degree.
HTH,
B.
I haven't really seen any examples, but I assume that they are saved inside the containing entity table within the database.
Ie. If I have a Person entity/aggregate root and a corresponding Person table, if it had a Value Object called Address, Address values would be saved inside this Person table!
Does that make sense for a domain where I have other entities such as Companies etc. that have an Address?
(I'm currently writing a project management application and trying to get into DDD)
It's ok to store Value Objects in a separate table, for the very reasons you've described. However, I think you're misunderstanding Entities vs VOs - it's not a persistence related concern.
Here's an example:
Assume that a Company and Person both have the same mail Address. Which of these statements do consider valid?
"If I modify Company.Address, I want
Person.Address to automatically get
those changes"
"If I modify Company.Address, it
must not affect Person.Address"
If 1 is true, Address should be an Entity, and therefore has it's own table
If 2 is true, Address should be a Value Object. It could be stored as a component within the parent Entity's table, or it could have its own table (better database normalisation).
As you can see, how Address is persisted has nothing to do with Entity/VO semantics.
Most developers tend to think in the database first before anything else. DDD does not know about how persistence is handled. That's up to the repository to deal with that. You can persist it as an xml, sql, text file, etc etc. Entities/aggregates/value objects are concepts related to the domain.
Explanation by Vijay Patel is perfect.