Dynamoose query by different attributes (Node.js) - node.js

I need to get record (-s) from DynamoDB via Dynamoose by non-key attribute. For example, I need to get all records from the table someModel where the field my_field is equal to 111. I do it by the next way:
const data = await someModel.query("my_field").eq("111").exec();
And this code stops executing! I mean that following code after that is not called.
If I change code to this:
const data = await someModel.query("my_field").eq("111");
my query is working, but data contains:
{
"options": {
"all": {
"delay": 0,
"max": 1
}
},
"query": {
"hashKey": {
"name": "my_field",
"value": "111"
}
},
"filters": {},
"buildState": false,
"validationError": null,
"notState": false,
"success": true
}
I understand that above code is prepared query parameters for query but how can I apply them and execute query to DynamoDB? Of course the query code is placing inside async function - that is why await is written there.
I use also serverless framework for describing DynamoDB schemes. But all models I write via dynamoose.
Where am I mistaking?

As mentioned in the documentation here, Dynamoose query returns the value in the callback and not as a promise. Therefore, your response is actually returned in a callback that should come inside the exec part of your query. async/await is valid for promises and not callbacks.
someModel.query("my_field").eq("111").exec((err, data) => {
// Do whatever you wish to with your data
});

Related

How to filter object by their child in Google Cloud Realtime Database?

So, I've Google Cloud Firebase Realtime Database, where objects stored and identified by their unique IDs. I need to filter them by their child property, for example, called surname where it would be exact match and get result of the whole object from promise. How to do that?
Example of how database looks like:
{
"uniqueID123": {
"surname": "some surname",
"data": "123"
},
"anotheruniqueID": {
"surname": "some another surname",
"data": "info"
}
}
To order and filter data you can use a query, like this:
const ref = db.ref('theParentNodeOfYourJSON');
ref.orderByChild('surname').equalTo("some surname").on('value', (snapshot) => {
snapshot.forEach((child) => {
console.log(snapshot.key, snapshot.child("surname").val());
})
});

MongoDb Bulkwrite does not seem to throw any Error

I have been trying to execute a Bulkwrite query in Mongoose, and I don't know for what reasons It doesn't throw error
let input = [
{
"variantId": "5e1760fbdfaf28038242d676",
"quantity": 5
},
{
"variantId": "5e17e67b73a34d53160c7252",
"quantity": 13
}
]
try{
let bulkArr = [];
for (const i of input) {
bulkArr.push({
updateOne: {
"filter": { "_id": Mongoose.Types.ObjectId(i.variantId) },
"update": { $inc: { "stocks": - i.quantity } }
}
})
}
await Variant.bulkWrite(bulkArr)
}
catch(e){
console.log(e);
}
I have tried to update values not present in the database,
as well as I have tried to update stocks to negative values which is explicitly set to min:0
both of the following query should have thrown an error. But no error was thrown.
Updating non-existing document is not considered as write error. You can console.log the result to see that it simply informs you about the number of matched elements:
let result = await Test.bulkWrite(bulkArr);
console.log(result);
which prints:
...
nMatched: 0,
...
Running $inc with a negative value is still valid - you can do that and even if you have a validation rule like min:0 it will not be applied since $inc gets executed on database server and mongoose doesn't know if your field's value will get negative after this operation or not. The min rule will be applied when you want to insert a new document or replace existing one using .save() method.
How to get an error then ? Try to violate unique key by inserting the same value into unique index - that situation throws an exception explicitly.

Mongo DB query in Node.js

I want to create a query that finds the last insert that I have found.
Here is my dataset in Infos collection.
{
"_id": "5c7114339624d8dd041bae18",
"user_id": "AHK",
"gps": "gps information",
"timestamp": "2010-05-30T20:07:35.000Z",
"__v": 0
},
{
"_id": "5c7114bde3075ae0b38ec0bc",
"user_id": "AHK",
"gps": "gps information2",
"timestamp": "2010-05-30T20:07:35.000Z",
"__v": 0
},
{
"_id": "5c7114c2e3075ae0b38ec0bd",
"user_id": "AHK",
"gps": "gps information3",
"timestamp": "2010-05-30T20:07:35.000Z",
"__v": 0
}
For example, I want to select the data which gps value is "gps information3".
It is the last inserted query In this DB. So I create query like below to select this.
router.get('/infos/gps/:userid/recent',function(req,res){
var temp = Info.find({user_id: req.params.userid}, function(err, info){
if(err) return res.status(500).json({error: err});
if(!info) return res.status(404).json({error: 'user not found in Info collections.'});
}).sort( {"_id": -1} ).findOne(function(err2,info2){
if(err2) return res.status(500).json({error: err2});
if(!info2) return res.status(404).json({error: 'findOne error'});
console.log(info2.user_id +" "+info2.gps+" "+info2.timestamp);
res.json(info2);
});
});
It worked.
But I don't understand the flow. I know that Nodejs is asynnchronous. And it has callback function.
As I guess, First, the find function is called, then sort function is called when the result of find function returned , and finally findOne function is called when the sort function is returned.
But I think that it isn't asynchronous.
Because I thought sort function would proceed before the results of the find function were returned.
Could you tell me what is the answer?
In addition, let me know if there is a way to make this query better.
Last, Can mongodb's _id attribute be the reference point when sorting with time?
I'm a beginner so I have too many questions. I'm sorry.
in mongoose you either:
use a query with a callback, if you pass in a callback function, Mongoose will execute the query asynchronously and pass the results to the callback
Info.find({},callbackFunc);
use a query without a callback and this allows you to chain multiple queries. At the end of the chain you add .exec(callbackFunc) to execute and pass the results to the callback
Info.find({user_id: req.params.userid}).sort({"_id": -1}).findOne().exec(callbackFunc)
the callback functions are something like this:
function callbackFunc (err,docs) {
if (err) {
console.log(err); // do something
}
if (!doc) {
// do something else
}
console.log(doc); //do the main thing
}
Frankly, I have no idea how the code you posted works, but if it does, it's definitely not supported.
https://mongoosejs.com/docs/queries.html
As to why you can sort by id and get it sorted in chronological order, that's because in MongoDB we get a timestamp for free if we define our primary key as an ObjectId. This is because the 12 byte ObjectId type contains a 4 byte time component.
http://www.syntaxsuccess.com/viewarticle/sorting-by-objectid-in-mongodb

IBM Bluemix Discovery - query parameter

I have created a Discovery service on my bluemix account. I want to query my documents from a nodejs application.
I have built a query with some aggregation, tested it using the bluemix online tool and it's working well.
Now when I query the collection from my code, whatever my parameters are, I always receive all of my documents with the enriched text and so on. I think I am missing how to send the query attributes to the service (like filters and aggregations).
Here is my code:
var queryParams = {
query:'CHLOE RICHARDS',
return:'title',
count:1,
aggregations:'nested(enriched_text.entities).filter(enriched_text.entities.type:Person).term(enriched_text.entities.text, count:5)'
};
discovery.query({environment_id:that.environment_id, collection_id:that.collection_id, query_options:queryParams }, function(error, data) {
if(error){
console.error(error);
reject(error);
}
else{
console.log(JSON.stringify(data, null, 2));
resolve(data.matching_results);
}
});
And the result is always:
{
"matching_results": 28,
"results": [
{
"id": "fe5e2a38e6cccfbd97dbdd0c33c9c8fd",
"score": 1,
"extracted_metadata": {
"publicationdate": "2016-01-05",
"sha1": "28434b0a7e2a94dd62cabe9b5a82e98766584dd412",
"author": "Richardson, Heather S",
"filename": "whatever.docx",
"file_type": "word",
"title": "no title"
},
"text": "......
Independantly of the value of the query_optionparameter. Can you help me?
EDIT
Instead of the query_options:queryParams, I have used query:"text:CHLOE RICHARDS" and it's working well. Now my problem still remains to find the right parameter format to add the aggregations I want
EDIT 2
So I have looked at IBM's example on Github more carefully, and the parameters are now formatted like this:
const queryParams = {
count: 5,
return: 'title,enrichedTitle.text',
query: '"CHLOE RICHARDS"',
aggregations: [ 'nested(enriched_text.entities).filter(enriched_text.entities.type:Person).term(enriched_text.entities.text, count:5)' ],
environment_id: '1111111111',
collection_id: '11111111111'
};
It works well if I use only the query attribute. Now if I only use the aggregations one, all the documents are sent back as a result (which is understandable) but I have no aggregation part, so I can not access the list of proper name in my documents.
Your query does not look right. I you are going to use query then you will need to construct a query search like text:"CHLOE RICHARDS"
If you want to perform a natural language query then you should be setting the parameter natural_language_query.

Using an arbitrary number of query params to filter results in mongoose

I'm building an API using node express and mongodb, with mongoose.
I have a post resource that handles user posts, and would like to be able to perform various queries on the post resource.
For instance I have a functions as that returns all posts as follows:
// Gets a list of Posts
exports.index = function(req, res) {
console.log(req.query);
Post.findAsync()
.then(mUtil.responseWithResult(res))
.catch(mUtil.handleError(res));
};
I looking for a good way of processing any additional query params that might come with the request.
/posts will return all posts, but /posts?user=12 will return posts by user with id 12 and /posts?likes=12 will return posts with 12 or more likes.
How can I check for and apply the these query params to filter and return the results since they may or may not be present.
Thanks ;)
If user=12 means "users with id 12", how does likes=12 mean "likes greater than 12"? You need to be more descriptive with your queries. You can do that by passing an array of objects. Send your query in a way that can be interpreted like this:
var filters = [
{
param: "likes",
type: "greater"
value: 12
},
{
param: "user",
type: "equal",
value: "12"
}]
var query = Post.find();
filters.forEach(function(filter) {
if (filter.type === "equal") {
query.where(filter.param).equals(filter.value);
}
else if (filter.type === "greater") {
query.where(filter.param).gt(filter.value);
}
// etc,,,
})
query.exec(callback);

Resources