CouchDB inner join by document field? - couchdb

I have a question, i have 2 kind of documents, one of them is like this:
{
"type": "PageType",
"filename": "demo"
"content": "zzz"
}
and another one like this:
{
"type": "PageCommentType",
"refFilename": "demo"
"content": "some comment content"
}
i need to emit document that contains .comments field which is array of PageCommentType documents that i link on condition PageType document filename == PageCommentType document refFilename fields.
{
"filename": "demo",
"comments": [{}, {}, {}]
}
Anyone has any suggestions on how to implement it?
Thank you.

You need view collation. Emit both within the same view, using the filename as the key and a type identifier to discriminate between comments and the original content:
function(doc) {
if (doc.type == "PageType") emit([doc.filename,0],doc.content);
if (doc.type == "PageCommentType") emit[doc.refFilename,1],doc.content);
}
When looking for the document demo and its comments, run a query with startkey=["demo",0] and endkey=["demo",1]: you will get the page content followed by all the comments.
Once you have all the data you want, but it's not in the right format, you are almost done. Simply write a _list function to read all the rows and output the final JSON document with the structure/schema that you need.

Related

what is the return value of ArangoJS collection.save()?

The documentation is located here:
Document Manipulation · ArangoDB v3.4.1 Drivers Documentation
I see the documentation for collection.replace() and collection.update(), but nothing for collection.save(). I know the save function exits because I'm using it. But it doesn't return the expected value and I'd like to reference the documentation.
My specific problem is that I want to save a document to the ArangoDB database and get back the saved document in full. Here's what I have so far:
async createDocument(collectionName, data) {
try {
const collection = this.db.collection(collectionName);
return collection.save(data); //I want to return the saved document
} catch(err) {
console.log(err.message, "saving failed")
}
}
The documentation of the save method is found under DocumentCollection:
https://docs.arangodb.com/3.4/Drivers/JS/Reference/Collection/DocumentCollection.html#documentcollectionsave
The answer you look for:
returns an object containing the document's metadata
I admit this isn't very detailed. What it returns are the system attributes _id, _key and _rev. This also applies if you save an edge with a _from and a _to attribute, they are not returned as meta data, nor any user attributes even if their names start with an underscore.
If you want it to return the full document, then set the option returnNew:
collection.save(data, { returnNew: true} );
If set to true, return additionally the complete new documents under the attribute new in the result.
The result looks like this:
{
"_id": "coll/123",
"_key": "123",
"_rev": "_YDWaEaa--B",
"new": {
"_id": "coll/123",
"_key": "123",
"_rev": "_YDWaEaa--B",
"foo": "bar"
}
}

Creating a validation with CouchDB (Fauxton)

I store products in the following way in a CouchDB database:
{
"_id": "1ce330a867a803fd10082c4513000fe5",
"_rev": "4-a5eae6f790ea8b9cedea53db50a13fef",
"type": "Product",
"name": "Apple",
"price": 1
}
I'd like to create a validation to make sure that every new document with the type Product has the field name. The only documentation I found was http://guide.couchdb.org/draft/validation.html After reading it I wrote/copied this validation:
function(newDoc, oldDoc, userCtx) {
function require(field, message) {
message = message || "Document must have a " + field;
if (!newDoc[field]) throw({forbidden : message});
}
if (newDoc.type == "Product") {
require("name");
}
}
Than I use Fauxton to create it:
But it doesn't work. I can create such a document without a name field. What do I do wrong?
You have to create a new design document. You need to specify the language field which will be JavaScript in your case.
Then, you have to add the validate_doc_update field and fill it with your function.
As a reference, you can look into the _replicator database for the _design/_replicator.
Alternative
On the command line it can be done with (beware of escaping the "):
curl -X PUT http://127.0.0.1:5984/shop/_design/product_validation -d '{"validate_doc_update": "function(newDoc, oldDoc, userCtx) { if (newDoc.type == \"product\") { if (!newDoc[\"name\"]) { throw({forbidden: \"missing name\"}) } } }"}'

Editing/Updating nested objects in documents CouchDB (node.js)

I'm trying to add (aka. push to existing array) in couchDB document.
Any feedback is greatly appreciated.
I have a document called "survey" inside my database called "database1".
I have "surveys" as a set of arrays which consists of objects that has information on each survey.
My goal is to update my "survey" document. Not replacing my array, but adding a new object to the existing array. I've used "nano-couchdb" and "node-couchdb", but could not find a way around it. I was able to update my "surveys", but it would replace the whole thing, not keeping the existing objects in array.
1) Using Nano-couchdb:
db.insert({ _id, name }, "survey", function (error, resp) {
if(!error) { console.log("it worked")
} else {
console.log("sad panda")}
})
2) Using couchdb-node:
couch.update("database1", {
_id: "survey",
_rev:"2-29b3a6b2c3a032ed7d02261d9913737f",
surveys: { _id: name name: name }
)
These work well with adding new documents to a database, but doesn't work with adding stuff to existing documents.
{
"_id": "survey",
"_rev": "2-29b3a6b2c3a032ed7d02261d9913737f",
"surveys": [
{
"_id": "1",
"name": "Chris"
},
{
"_id": "2",
"name": "Bob"
},
{
"_id": "1",
"name": "Nick"
}
]
}
I want my request to work as it would for
"surveys.push({_id:"4",name:"harris"})
whenever new data comes in to this document.
Your data model should be improved. In CouchDB it doesn't make much sense to create a huge "surveys" document, but instead store each survey as a separate document. If you need all surveys, just create a view for this. If you use CouchDB 2.0, you can also query for survey documents via Mango.
Your documents could look like this:
{
"_id": "survey.1",
"type": "survey",
"name": "Chris"
}
And your map function would look like that:
function (doc) {
if (doc.type === 'survey') emit(doc._id);
}
Assuming you saved this view as 'surveys' in the design doc '_design/documentLists', you can query it via http://localhost:5984/database1/_design/documentLists/_view/surveys.

Marklogic Node.js API: How to get the document where an embedded triple lives?

I tried to insert the following test document:
db.documents.write(
{
uri: "/test/doc1.json",
contentType: "application/json",
collections: "test",
content: {
name : "Peter",
hobby: "Sleeping",
other: "Some other info",
"triple": {
"subject": {   
"datatype": "http://example.com/name/",  
"value": "Peter"   
},   
"predicate": {     
"datatype": "http://example.com/relation/",  
"value": "livesin"   
},   
"object": {     
"datatype": "http://example.com/location/",  
"value": "Paris"   
}
  }
}
}
).
result(function(response){
console.log("Done loading");
});
Then I queried as follows:
var query = [
'SELECT ?s ?p ?o' ,
'WHERE { ?s ?p ?o }' ,
];
db.graphs.sparql('application/sparql-results+json', query.join('\n')
).result(function (result) {
console.log(JSON.stringify(result, null, 2));
}, function(error) {
console.log(JSON.stringify(error, null, 2));
});
The results showed me the values of the triple, but what if I also want to get the entire document where the triple was embedded? Is it also possible to filter by other fields in the document?
There isn't a way to retrieve the document that contains the result of a SPARQL query, because those results may not be a triple that exists within a particular document (instead, it returns a "solution" consisting of 1 or more values).
If you know you are looking for a particular triple, and you want the document that holds that triple, I would normally say to use a cts:triple-range-query; however, I don't see a way to do that through the Node.js API (or through REST, for that matter). With that in mind, I see two choices:
insert a triple that includes the document's URI as the subject or object, then make a request for that document (as #grtjn suggested)
make a REST API extension (using either JavaScript or XQuery) that calls cts:search with cts:triple-range-query as part of the query; call that extension from Node
I'd recommend doing it in two stages:
Run a sparql that will return document uris.
Run a document search to return those documents, optionally further constrained with extra criteria.
For this you will need to embed triples in your documents listing the document uri of the documents themselves.
HTH!

couchdb doc property based on existing property: bulk update

I have a million documents that I need to transform. Each document looks like this:
{
"_id": "00082786797c0a31ab8b5e67fb0000dc",
"_rev": "3-d67692b1c94b936ae913bf7ea4896bed",
"type": "Feature",
"properties": {
"timestamp": "2015-08-03 21:26:48.000",
"status": "on",
"avstatus": null,
"speed": "38",
"MS_DATE_TI": 1438576728000,
"STR_DATE_T": "1438576728000"
},
"geometry": {
"type": "Point",
"coordinates": [
-8784866.197274148,
4296254.156268783
]
}
}
I'm trying to create a new property based on the "MS_DATE_TI" property for every record. What is the best way to do that?
THanks, Tyler
Either build a little script in Python or use PouchDB directly in your browser.
Here's what the code should look like.
var n; //The number of documents to get for every bulkget. Use it as a limit
var lastKey; //The key used as startkey_docid parameter
while(true){
//AllDocs to get N documents starting from lastkey
//Update the documents locally by doing a loop
//Send the updates to the server
//If response.rows < limit, you probably have updated all the lines so break the loop
}
Thanks Alexis Côté. I ended up leveraging some of my python skills(I have no PouchDB skills(yet)):)
here's what I did:
Load python CouchDB library:
https://pypi.python.org/pypi/CouchDB
Read over docs:
http://pythonhosted.org/CouchDB/
Write a little script
import couchdb
couch = couchdb.Server()
db = couch['avl_multi_doc']
for id in db:
doc = db[id]
print doc['properties']['MS_DATE_TI']
doc['time'] = doc['properties']['MS_DATE_TI']
db[doc.id] = doc
Click run and go watch Matlock

Resources