How to fetch results from mongodb aggregate with two matching fields - json

I am trying to get the sum ratings of user admin from this JSON object:
{
"_id": "5a7ef9a0ce8b5c00147c1ef3",
"assessed_by": "admin",
"rating": "Sad",
"assessment_date": "2018-02-10T13:54:53.303Z"
},
{
"_id": "5a7efe6083fec3001465b369",
"assessed_by": "admin",
"rating": "Sad",
"assessment_date": "2018-02-10T14:15:01.485Z"
}
Expected output:
{
"_id" : "admin",
"count" : 2.0
}
I also wanted to sort the assessment_date by range so I used the $and operator but it doesn't seem to work on Node. I have my code here:
const now = moment().utc();
const endDate = moment().utc().subtract(9, 'days');
model.aggregate({
$match: {
$and: [
{rating: "Sad"},
{assessment_date: {$lte: now}},
{assessment_date: {$gte: endDate}}
]
}
}, { $group:
{ _id: "admin",
count: {
$sum: 1 }
}
}, function(err, results){
console.log(results)
})
Mongo syntax seemed to work on Robomongo, but it doesn't work when trying on Node.

Your aggregation pipeline stages need to be in an array.
model.aggregate( [ { <stage> }, ... ] )

Related

Access nested JSON in React table

I want to display nested JSON data in a react-table.
I tried it like this:
render() {
const columns = [{
//Not Displaying
Header: 'Owner ID',
id: 'ownerid',
accessor: '_links.customer.href.ownerid', // <- i think this is wrong
Cell: this.renderEditable
},
{
//Displaying
Header: 'Price',
accessor: 'price',
Cell: this.renderEditable
}, {
The data i am getting back and have bound to the table is structured as follows:
[
{
"id": 1,
"date": "20.07.2019",
"price": 3.2,
"customer": {
"ownerid": 1,
"firstname": "John",
"lastname": "Johnson"
}
}
]
Here i am using the columns array:
import ReactTable from "react-table";
<ReactTable data={this.state.offers} columns={columns}
filterable={true} pageSize={10}/>
Binding the data:
fetchOffers = () => {
const token = sessionStorage.getItem("jwt");
fetch(SERVER_URL + 'api/offers',
{
headers : {'Authorization':token}
})
.then((response) => response.json())
.then((responsteData) => {
this.setState({
offers: responsteData._embedded.offers,
});
console.log(this.state);
})
.catch(err=> console.error(err));
}
The data i am using after binding:
Check the Accessors documentation. It has several examples for complex data structure.
I don't see _links or href in your sample data. So I think that you need just:
accessor: 'customer.ownerid'
The data structure from the console screenshot doesn't match your sample data. And it doesn't seem to contain ownerid. Try accessor: '_links.customer.href' to check whether it outputs anything to the table.
I figured it out.
I called the endpoint "localhost:8080/api/offers" and saved the following response:
"offers": [
{
"date": "20.07.2019",
"price": 3.2,
"_links": {
"self": {
"href": "http://localhost:8080/api/offers/1"
},
"offer": {
"href": "http://localhost:8080/api/offers/1"
},
"customer": {
"href": "http://localhost:8080/api/offers/1/customer"
}
}
}
]
there is no customer object
But when i call "localhost:8080/offers" i get:
[
{
"id": 1,
"date": "20.07.2019",
"price": 3.2,
"customer": {
"ownerid": 1,
"firstname": "John",
"lastname": "Johnson"
}
}
]
i changed the URI in my project and now the number is displaying.
I still don't know why i get data from "../api/offers" but i will research.
I had to access a nested object and display it with some styling, and this ended up working for me:
(Note: I was using typescript, so some of the typing might not be necessary)
{
Header: 'Thing To Display',
accessor: 'nested.thing.to.display',
Cell: ({ row }: { row: Row }) => (
<p>{row.values['nested.thing.to.display']}</p>
),
}

Return selected JSON object from mongo find method

Here is the sample JSON
Sample JSON:
[
{
"_id": "123456789",
"YEAR": "2019",
"VERSION": "2019.Version",
"QUESTION_GROUPS": [
{
"QUESTIONS": [
{
"QUESTION_NAME": "STATE_CODE",
"QUESTION_VALUE": "MH"
},
{
"QUESTION_NAME": "COUNTY_NAME",
"QUESTION_VALUE": "IN"
}
]
},
{
"QUESTIONS": [
{
"QUESTION_NAME": "STATE_CODE",
"QUESTION_VALUE": "UP"
},
{
"QUESTION_NAME": "COUNTY_NAME",
"QUESTION_VALUE": "IN"
}
]
}
]
}
]
Query that am using :
db.collection.find({},
{
"QUESTION_GROUPS.QUESTIONS.QUESTION_NAME": "STATE_CODE"
})
My requirement is retrive all QUESTION_VALUE whose QUESTION_NAME is equals to STATE_CODE.
Thanks in Advance.
If I get you well, What you are trying to do is something like:
db.collection.find(
{
"QUESTION_GROUPS.QUESTIONS.QUESTION_NAME": "STATE_CODE"
},
{
"QUESTION_GROUPS.QUESTIONS.QUESTION_VALUE": 1
})
Attention: you will get ALL the "QUESTION_VALUE" for ANY document which has a QUESTION_GROUPS.QUESTIONS.QUESTION_NAME with that value.
Attention 2: You will get also the _Id. It is by default.
In case you would like to skip those issues, you may need to use Aggregations, and unwind the "QUESTION_GROUPS"-> "QUESTIONS". This way you can skip both the irrelevant results, and the _id field.
It sounds like you want to unwind the arrays and grab only the question values back
Try this
db.collection.aggregate([
{
$unwind: "$QUESTION_GROUPS"
},
{
$unwind: "$QUESTION_GROUPS.QUESTIONS"
},
{
$match: {
"QUESTION_GROUPS.QUESTIONS.QUESTION_NAME": "STATE_CODE"
}
},
{
$project: {
"QUESTION_GROUPS.QUESTIONS.QUESTION_VALUE": 1
}
}
])

sql subqueries to mongodb

I am new to MongoDB and I am trying to turn SQL queries into MongoDB queries. But can't seem to find any way to turn a SQL query with a subquery to mongoDB.
for example:
SELECT article, dealer, price
FROM shop
WHERE price=(SELECT MAX(price) FROM shop);
I tried the following, but it doesn't seem to work.
db.shop.group({
"initial": {},
"reduce": function(obj, prev) {
prev.maximumvalueprice = isNaN(prev.maximumvalueprice) ? obj.price :
Math.max(prev.maximumvalueprice, obj.price);
}}).forEach(
function(data){
db.shop.find({
"price": data
},
{
"article": 1,
"dealer": 1,
"price": 1
})
})
How do I convert this SQL query into a MongoDB query?
If you are using MongoDB v. 3.2 or newer you can try to use $lookup.
Try to use aggregation:
$sort your collection by price by DESC;
set $limit to 1 (it will take a first document, which will be with biggest price);
then use $lookup to select the documents from the same collection by max price and set it to tmpCollection element;
$unwind tmpCollection;
$replaceRoot - change document root to $tmpCollection
Example:
db.getCollection("shop").aggregate([
{$sort: {"price":-1}},
{$limit: 1},
{$lookup: {
from: "shop",
localField: "price",
foreignField: "price",
as: "tmpCollection"
}},
{$unwind: "$tmpCollection"},
{$replaceRoot: {newRoot:"$tmpCollection"}}
]);
Looks like you need the aggregation framework for this task using $first within a $group pipeline stage on ordered documents. The initial pipeline step for ordering the documents in the collection is $sort:
db.shop.aggregate([
{ "$sort": { "price": -1 } }, // <-- sort the documents first in descending order
{
"$group": {
"_id": null,
"article": { "$first": "$article" },
"dealer": { "$first": "$dealer" },
"price": { "$first": "$price" }
}
}
])
or using $last
db.shop.aggregate([
{ "$sort": { "price": 1 } }, // <-- note the sort direction
{
"$group": {
"_id": null,
"article": { "$last": "$article" },
"dealer": { "$last": "$dealer" },
"price": { "$last": "$price" }
}
}
])

Finding element in array within a document

I'm new to MongoDB/Mongoose, I'm trying to find all documents that their usersInvited array contains a certain UID.
Example:
a search through this collection with UID=123 should return id1, id2
[
{
"_id": "id1",
"usersInvited": [
{
"UID": "123"
}
]
},
{
"_id": "id2",
"usersInvited": [
{
"UID": "123"
}
]
},
{
"_id": "id3",
"usersInvited": [
{
"UID": "abc"
}
]
}
]
You can use $elemMatch for this:
db.myCollection.find({
usersInvited: {
$elemMatch: {
UID: "123"
}
}
})
https://docs.mongodb.org/v3.0/reference/method/db.collection.find/#query-an-array-of-documents
You can directly query against the UID field within the usersInvited array elements using dot notation:
MyModel.find({'usersInvited.UID': '123'}, (err, docs) => {...});
If any of the elements of the array has a UID value of '123', the document will be included.
var query = FriendHittups.find({
usersInvited: {
$elemMatch: {
"UID": "123"
}
}
});
query.exec(function (err, results){
});

evaluating json object returned from controller and attaching it to prepopulate attribute of tokeninput

I am using loopjs tokeninput in a View. In this scenario I need to prePopulate the control with AdminNames for a given Distributor.
Code Follows :
$.getJSON("#Url.Action("SearchCMSAdmins")", function (data) {
var json=eval("("+data+")"); //doesnt work
var json = {
"users": [
eval("("+data+")") //need help in this part
]
}
});
$("#DistributorCMSAdmin").tokenInput("#Url.Action("SearchWithName")", {
theme: "facebook",
preventDuplicates: true,
prePopulate: json.users
});
There is successful return of json values to the below function. I need the json in the below format:
var json = {
"users":
[
{ "id": "1", "name": "USER1" },
{ "id": "2", "name": "USER2" },
{ "id": "3", "name": "USER3" }
]
}