Cloudant DB query in Node-RED function - cloudant

I want to load my tweets from the Cloudant DB by ascending order. I thought using sort: "tweet.id" would work but no.
msg.payload = {
"query": "*:*",
limit: 6,
sort: "tweet.id",
};
return msg;
Node-RED flow:

I got this to work by creating a new Cloudant Query index in the Cloudant dashboard:
{
"index": {
"fields": [ "tweet.timestamp_ms" ]
},
"type": "json"
}
to index the tweet.timestamp_ms field. This can then be queried to return the data in timestamp order:
{
"selector": {
"_id": {
"$gt": 0
}
},
"sort": [
{
"tweet.timestamp_ms": "asc"
}
]
}

I solve this issue by adding the type of the variable.
What I was trying to do is to get all the documents with id=1 and then sort them by the attribute "nombre" which is a string.
My search index is:
function (doc) {
index("id", doc.id, {"store": true});
index("nombre", doc.nombre, {"store": true});
}
And the payload in Node-red:

Related

How to query in a nested array and project only the matching items from array?

The structure looks like this:
{
clientName: "client1",
employees: [
{
"employeename": 1,
"configuration": {
"isAdmin": true,
"isManager": false
}
}
{
"employeename": 2,
"configuration": {
"isAdmin": false,
"isManager": false
}
}...
]
},
{
...
}
`
I want to see the employees who are admins inside a specific client, given that, I have the client name. How can I write a query in MongoDB for this? I want to be able to see (project) only employees who match?
Can I combine it to match multiple conditions? for example: someone who is an admin and a manager.
I have tried doing:
db.collection.find({clientName: "client1", "employees.configuration.isAdmin": true}, {"employees.employeename": 1})
This just return all the employees.
I've also tried using $elemMatch, to no avail.
Any help is appreciated.
You can do it with Aggregation framework:
$match - to filter the document based on clientName property
$filter with $eq - to filter only employees that have admins
db.collection.aggregate([
{
"$match": {
"clientName": "client1"
}
},
{
"$set": {
"employees": {
"$filter": {
"input": "$employees",
"cond": {
"$eq": [
"$$this.configuration.isAdmin",
true
]
}
}
}
}
}
])
Working example

adding data to nested document : mongodb

I want to add new record within 'music'. My document looks similar to
{
"username": "erkin",
"email": "erkin-07#hotmail.com",
"password": "b",
"playlists": [
{
"_id": 58,
"name": "asdsa",
"date": "09-01-15",
"musics": {
"song-one":{
"song-one": "INNA - Cola Song (feat. J Balvin)",
"duration": "3.00"
},
"song-two":{
"song-two": "blabla",
"duration": "3.00"
}
}
}
]
}
After navigating to "music" and then using $set to add/update multiple records at once. But new records is getting added in lexicographical manner(behaviour of $set).
I'm using query similar to (so in my case song-four is coming before song-three) :
db.getCollection('myCollection').update({username:"erkin"},{$set:{"playlists.musics.song-three":{...},"playlists.musics.song-four":{...}}})
Is there any way I can add new records to that location in a way my $set query is arranged ?
As playlists is an array:
Option 1: Update the first document in playlists.
Specify the index: 0 for the first document in playlists.
playlists.0.musics.song-three
db.collection.update({
username: "erkin"
},
{
$set: {
"playlists.0.musics.song-three": {
"song-three": "song-three"
},
"playlists.0.musics.song-four": {
"song-four": "song-four"
}
}
})
Sample Demo on Mongo Playground (Option 1)
Option 2: Update all documents in playlists.
With $[] all positional operator.
playlists.$[].musics.song-three
db.collection.update({
username: "erkin"
},
{
$set: {
"playlists.$[].musics.song-three": {
"song-three": "song-three"
},
"playlists.$[].musics.song-four": {
"song-four": "song-four"
}
}
})
Sample Demo on Mongo Playground (Option 2)
Option 3: Update specified document in playlists.
With $[<identifier>] filtered positional operator.
playlists.$[playlist].musics.song-three
db.collection.update({
username: "erkin"
},
{
$set: {
"playlists.$[playlist].musics.song-three": {
"song-three": "song-three"
},
"playlists.$[playlist].musics.song-four": {
"song-four": "song-four"
}
}
},
{
arrayFilters: [
{
"playlist._id": 58
}
]
})
Sample Demo on Mongo Playground (Option 3)

Mongodb aggregate return data conditionally

I am trying to return ONLY data records which email not exist in other collection with mongodb aggregation. Example:
LetterCollection:
[
{
"email": "some#email.com",
"data": "someData"
}, {
"email": "some2#email.com",
"data": "someData2"
},
]
UserCollection:
[
{
"id": "1"
"email": "some#email.com",
}
]
Get all letters which user email not exist in users collection.
Expected result:
[{
"email": "some2#email.com",
"data": "someData2"
}]
How can I achieve that?
Run an aggregate operation on the letters collection in which the pipeline first does a $lookup to the users collection, joined on the email field.
Documents returned from this pipeline stage contain an array field with the joined documents, so you would need a further $match pipeline step to filter documents where this new field does not have any documents. This can be done by checking the length of the array field with $size and filtering using the $expr expression with the $eq comparison operator.
The result can be further $projected to remove the new field in those documents that match to give the final desired output.
The above pipeline can be expressed as:
db.letters.aggregate([
{ '$lookup': {
'from': 'users',
'localField': 'email',
'foreignField': 'email',
'as': 'users'
} },
{ '$match': { '$expr': { '$eq': [ { '$size': '$users' }, 0 ] } } },
{ '$project': { 'users': 0 } }
])

Cloudant find Query with $and and $or elements

I'm using the following json to find results in a Cloudant
{
"selector": {
"$and": [
{
"type": {
"$eq": "sensor"
}
},
{
"v": {
"$eq": 2355
}
},
{
"$or": [
{
"p": "#401000103"
},
{
"p": "#401000114"
}
]
},
{
"t_max": {
"$gte": 1459554894
}
},
{
"t_min": {
"$lte": 1459509591
}
}
]
},
"fields": [
"_id",
"p"
],
"limit": 200
}
If I run this againt my cloudant database I get the following error:
{
"error": "unknown_error",
"reason": "function_clause",
"ref": 3379914628
}
If I remove one the $or elements I get the results for query.
(,{"p":"#401000114"})
Also i get a result if I replace #401000114 with #401000114 I get result.
But when I want to use both element I get the error code above.
Can anybody tell what this error_reason: function_clause mean?
error_reason: function_clause means there was a problem on the server, you should probably reach out to Cloudant Support and see if they can help you with your issue.
I had contact with the Cloudant support.
This is there answer:
The issue affects Cloudant generally
It affects both mult-tenant and dedicated clusters.
There are working on the sollution.
A workaround is in the array to which the $or operator applies has two elements, you can get the correct result by repeating one of the items in the array.

Only one element returned in array

I am trying to find elements from my MongoDB database with meteor.
I managed to filter and go through the structure of my array, but the result is a single element, and not all the elements matching the criteria.
Query :
var json = Tests1VerlIR.find({}, {fields: {entries: {$elemMatch: {'payload.id': {$eq: this.params._id}} } } }).fetch();
this.response.setHeader('Content-Type', 'application/json');
this.response.end(JSON.stringify(json));
Data Structure :
{"entries":
[{"method":"POST",
"source":"ex",
"path":"/ex",
"time":1464615406900,
"payload":
{"slot_frame_number":"4",
"slot_HTUTemp":"2306",
"data":"0400f008561655270209a314",
"slot_BMEPres":"10069",
"slot_HTUHumi":"5283",
"slot_BMETemp":"2288",
"time":"1464615404",
"device":"79",
"slot_BMEHumi":"5718",
"signal":"7.22",
"id":"2"},
"_id":"574c41ee578d01af3664cbaf"},
{"method":"POST",
"source":"ex",
"path":"/ex",
"time":1464615406900,
"payload":
{"slot_frame_number":"4",
"slot_HTUTemp":"2306",
"data":"0400f008561655270209a314",
"slot_BMEPres":"10069",
"slot_HTUHumi":"5283",
"slot_BMETemp":"2288",
"time":"1464615404",
"device":"79",
"slot_BMEHumi":"5718",
"signal":"7.22",
"id":"2"},
"_id":"574c41ee578d01af3664cbaf"}, {...}]}
Response :
[
{
"_id":
{
"_str": "576155d7a605348159cd1f1a"
},
"entries":
[
{
"method": "POST",
"source": "ex",
"path": "/ex",
"time": 1464615406900,
"payload":
{
"slot_frame_number":"4",
"slot_HTUTemp":"2306",
"data":"0400f008561655270209a314",
"slot_BMEPres":"10069",
"slot_HTUHumi":"5283",
"slot_BMETemp":"2288",
"time":"1464615404",
"device":"79",
"slot_BMEHumi":"5718",
"signal":"7.22",
"id":"2"
},
"_id": "574c41ee578d01af3664cbaf"
}
]
}
]
You cannot return multiple elements of an array matching your criteria in any form of a basic .find() query. To match more than one element you need to use the .aggregate() method instead.
refer this link.
Tests1VerlIR.aggregate([
{ "$match": { "entries.payload.id": "2" } },
// Unwind the array to denormalize
{ "$unwind": "$entries" },
// Match specific array elements
{ "$match": { "entries.payload.id": "2" } },
// Group back to array form
{ "$group": {
"_id": "$_id",
"entries": { "$push": "$entries" }
}}
])
Solution :
var json = Tests1VerlIR.aggregate({"$unwind": "$entries"}, {$match: {'entries.payload.id': this.params._id} });

Resources