Fetching only few attributes of a document in couchdb - couchdb

I have a site where I have documents that are around 1MB in size. To avoid any kind of conceptual joins I have put all related data in a single document.
Now I often need to fetch only one or two attributes of a document. Each document has over 10 attributes many of which are pretty large. I can not go on writing views for every single combination of the attributes.
How should I do it ? The only way I see is creating views on the fly and then using those views. OR is there any better method ?

http://wiki.apache.org/couchdb/Document_Update_Handlers
While it seems strange to call a update feature, couch allows you to return information from the document without updating it. See the xml example.
Here might be an example you could extend:
Add jsonpath to your ddoc, ( https://github.com/s3u/JSONPath)
function(doc, req) {
var jsonpath = require('jsonpath');
var path = req.query.path;
var target = jsonpath(doc, path);
var json = JSON.stringify(target);
var resp = { 'headers' : { 'Content-Type' : 'application/json' }, 'body' : json };
return [doc, resp];
}

Related

ravendb NodeJS, load related document and create a nested result in a query

I have an index that returns something like this
Company_All {
name : string;
id : string;
agentDocumentId : string
}
is it possible to load the related agent document and then generate a nested result with selectFields and QueryData like this
ICompanyView {
companyName : 'Warner',
user {
documentId : 'A/1'
firstName : 'john',
lastName : 'paul'
}
}
I need something like the below query that obviously doesn't work as I expect:
const queryData = new QueryData(
["name", "agentDocumentId", "agent.firstName", "agent.lastName"],
["companyName", "user.documentId", "user.lastName", "user.firstName"]);
return await session.query<Company_AllResult>({ index: Company_All })
.whereEquals("companyId", request.companyId)
.include(`agents/${agentDocumentId}`) // ????
.selectFields(queryData,ICompanyView)
.single();
Yes, you can do that using:
https://ravendb.net/docs/article-page/5.4/nodejs/indexes/indexing-related-documents
This is called indexing related documents, and is accessible at indexing time, not query time.
Alternatively, you have the filter clause, which has access to the loaded document, but I wouldn't generally recommend doing this.
Generally:
When you query an index, the results of querying the index are the documents from the collection the index was defined on.
Index-fields defined in the index are used to filter the index-query
but the results are still documents from the original collection.
If you define an index that indexes content from a related-document then when making an index-query you can filter the documents by the indexed-fields from the related documents, but the results are still documents from the original collection.
When making an index-query (or any other query) you can project the query results so that Not the full documents of the original collection are returned but some other object.
Now:
To project/get data from the indexed related-document you have 2 options:
Store the index-fields from the related-document in the index.
(Store all -or- specific fields).
This way you have access to that content when making a projection in your query.
See this code sample.
Don't store the index-fields from the related-document,
then you will be able to use the index-fields to filter by in your query,
but to get content you will need to use 'include' feature in your query,
and then use the session.load, which will Not make another trip to the server.
i.e. https://demo.ravendb.net/demos/nodejs/related-documents/query-related-documents

Is there a way to filter through data based on if a search query is present in the string in mongodb?

I have data that looks like this in my mongoDB atlas database:
object: {
keywords: ['Homelessness', 'Food', 'Poverty']
}
I'm creating a filtering component for my MERN stack website and wanted to add a search feature for keywords like these that are present in each object in the database. If a search query was Homelessness for example, then the object above would show up since it has Homelessness as one of its keywords. But say for example I enter Homeless as a search query, the ones with Homelessness won't pop up because Homeless =/= Homelessness. Is there a way to somehow find if the search query is within a string inside an array which is all inside a json object?
Here is what I tried so far which gets the result I described in the situation above:
const getFilteredProjects = async (req, res) => {
// Initializing request object that will be sent to retrieve DB information
var request = {}
if (req.query.keywords !== '') {
request["keywords"] = req.query.keywords
}
console.log(request)
const projects = await Project.find(request).sort({ assignment_type: 1 })
res.status(200).json(projects)
}
How can I somehow access each string inside the keywords array and see if the search query is present in it? Is that possible with mongodb or would I have to somehow do it through javascript? If that's the case I'm not sure how I could do that, I would appreciate it if I could get some help.

Mongoose: How to update nested fields with fields present in request body only?

Looking to update lookupSchema images nested fields
var lookupSchema = new Schema({
images:{
"img1":String,
"img2":String,
"img3":String,
"img4":String
}
}
As I don't know which fields are available in request body during findOneAndUpdate operation, I am unable to assign like this
$set: {
'images.img1': req.body.img1,
'images.img2': req.body.img2,
'images.img3': req.body.img3
}
If I code like above and specify all fields, already available fields become empty after update due to unavailable fields in request.
Need something like this to update available fields
$set: { "images.$[element]" : req.body }
I have searched a lot but unable to find a solution.
You can simply create a function like below to be able to achieve your result.
function update() {
let temp = {};
for(let field in req.body) {
temp["images."+field] = req.body[field];
}
db.collection.findOneAndUpdate({._id:...},{$set:temp},{upsert:true},function(err,result)
{...});
}

Google Datastore not retrieving entities

I have been working with the google cloud library, and I can successfully save data in DataStore, specifically from my particle electron device (Used their tutorial here https://docs.particle.io/tutorials/integrations/google-cloud-platform/)
The problem I am now having is retrieving the data again.
I am using this code, but it is not returning anything
function getData(){
var data = [];
const query = datastore.createQuery('ParticleEvent').order('created');
datastore.runQuery(query).then(results => {
const event = results[0];
console.log(results);
event.forEach(data => data.push(data.data));
});
console.log(data)
}
But each time it is returning empty specifically returning this :
[ [], { moreResults: 'NO_MORE_RESULTS', endCursor: 'CgA=' } ]
, and I can't figure out why because I have multiple entities saved in this Datastore.
Thanks
In the tutorial.js from the repo mentioned in the tutorial I see the ParticleEvent entities are created using this data:
var obj = {
gc_pub_sub_id: message.id,
device_id: message.attributes.device_id,
event: message.attributes.event,
data: message.data,
published_at: message.attributes.published_at
}
This means the entities don't have a created property. I suspect that ordering the query by such property name is the reason for which the query doesn't return results. From Datastore Queries (emphasis mine):
The results include all entities that have at least one value for
every property named in the filters and sort orders, and whose
property values meet all the specified filter criteria.
I'd try ordering the query by published_at instead, that appears to be the property with a meaning closest to created.

How to return multiple Mongoose collections in one get request?

I am trying to generate a response that returns the same collection sorted by 3 different columns. Here's the code I currently have:
var findRoute = router.route("/find")
findRoute.get(function(req, res) {
Box.find(function(err, boxes) {
res.json(boxes)
}).sort("-itemCount");
});
As you can see, we're making a single get request, querying for the Boxes, and then sorting them by itemCount at the end. This does not work for me because the request only returns a single JSON collection that is sorted by itemCount.
What can I do if I want to return two more collections sorted by, say, name and size properties -- all in the same request?
Crete an object to encapsulate the information and chain your find queries, like:
var findRoute = router.route("/find");
var json = {};
findRoute.get(function(req, res) {
Box.find(function(err, boxes) {
json.boxes = boxes;
Collection2.find(function (error, coll2) {
json.coll2 = coll2;
Collection3.find(function (error, coll3) {
json.coll3 = coll3;
res.json(json);
}).sort("-size");
}).sort("-name");
}).sort("-itemCount");
});
Just make sure to do the appropriate error checking.
This is kind of uggly and makes your code kind of difficult to read. Try to adapt this logic using modules like async or even promises (Q and bluebird are good examples).
If I understand well, you want something like that : return Several collections with mongodb
Tell me if that helps.
Bye.
Have you tried ?
Box.find().sort("-itemCount").exec(function(err, boxes) {
res.json(boxes)
});
Also for sorting your results based on 2 or more fields you can use :
.sort({name: 1, size: -1})
Let me know if that helps.

Resources