Inserting documents to MongoDB using node.js and mongoshell - node.js

I havee this Json format:
{
"AAPL": {
"cname": "Apple inc",
"symbol": "AAPL",
"logo": "apple.png",
"price": 0
},
"NVDA": {
"cname": "Nvidia Corporation",
"symbol": "NVDA",
"logo": "nvidia.png",
"price": 0
},
"GOOG": {
"cname": "Google inc",
"symbol": "GOOG",
"logo": "google.png",
"price": 0
}
}
I'd like to keep the same format while inserting to the mongoDB.
How can i do that using mongoDB native driver for node.js and using the mongo shell.

You have a single JSON object here. When you want each of its keys to be a separate document, you need to transform the object into an array first. While you do that, you also need to move the stock-symbol which is the key of each sub-object into the object itself so it doesn't get lost in the process. You can do this with a Javascript for-in loop:
jsonObject = ... // that JSON code you posted above
var docs = [];
for (var key in jsonObject) {
var doc = jsonObject[key];
doc.symbol = key;
docs.push(doc);
}
You can then pass the whole array to db.collection.insert to make a batch-insert of all documents in that array.

Related

How To Change Datatype String To Number of particular field in collection of mongo using nodejs

[{
"id": 5f6af7bd3f06d50018f28680,
"image": "https://images-na.ssl-images-amazon.com/images/I/51FQpz-zY1L._SL1024_.jpg",
"name": "Mac book",
"price": "150",
"description": "Apple MacBook Air",
"rating": 4,
},
{
"id": 5f6af7bd3f06d50018f28682,
"image": "https://static.acer.com/up/Resource/Acer/Laptops/Swift_7",
"name": "Dell Laptop",
"price": "250",
"description": "Find solace in your love for riding when you cruise",
"rating": 4,
}]
In This I want to Change Datatype Of All Object of json Mongodb which is price.
Actually Price is String But i want to convert it to Number dynamically.
db.my_collection.find({price: {$exists: true}}).forEach(function(obj) {
obj.price = new NumberInt(obj.price);
db.my_collection.save(obj);
});
let data = my_schema.find();
data.map((item) => {
my_schema.findOneAndUpdate({_id: item._id}, {price: Number(item.price)}})
})
If i understand you correctly , you retrieve array of object from db where pricing field is string and after it you need convert it to numbers ?
Why just not store it as number ?
You can convert it use .map function just after retrieve or if you use mongoose you can do it in post hook in same way.

How to include fields in api server and remove it before returning to results to client in Graphql

I have a Node.js GraphQL server. From the client, I am trying get all the user entries using a query like this:
{
user {
name
entries {
title
body
}
}
}
In the Node.js GraphQL server, however I want to return user entries that are currently valid based on publishDate and expiryDate in the entries object.
For example:
{
"user": "john",
"entries": [
{
"title": "entry1",
"body": "body1",
"publishDate": "2019-02-12",
"expiryDate": "2019-02-13"
},
{
"title": "entry2",
"body": "body2",
"publishDate": "2019-02-13",
"expiryDate": "2019-03-01"
},
{
"title": "entry3",
"body": "body3",
"publishDate": "2020-01-01",
"expiryDate": "2020-01-31"
}
]
}
should return this
{
"user": "john",
"entries": [
{
"title": "entry2",
"body": "body2",
"publishDate": "2019-02-13",
"expiryDate": "2019-03-01"
}
]
}
The entries is fetched via a delegateToSchema call (https://www.apollographql.com/docs/graphql-tools/schema-delegation.html#delegateToSchema) and I don't have an option to pass publishDate and expiryDate as query parameters. Essentially, I need to get the results and then filter them in memory.
The issue I face is that the original query doesn't have publishDate and expiryDate in it to support this. Is there a way to add these fields to delegateToSchema call and then remove them while sending them back to the client?
You are looking for transformResult
Implementation details are:
At delegateToSchema you need to define transforms array.
At Transform you need to define transformResult function for filtering results.
If you have ability to send arguments to remote GraphQL server, then you should use
transformRequest

Filter doc in DynamoDb by nested object list item using node.js

I have a document that has what Dynamodb calls a list.
"sites": [
{
"active": true,
"address": "212 Grand Ave",
"city": "Billings",
"device_id": "161674",
I would like to filter out by the device_id. Mongodb allows this by doing.var query = {"sites.device_id":device_id};
I currently have this:
var params = {
TableName : "customer",
"FilterExpression": "#k_sites[0].#k_device_id = :v_device_id",
"ExpressionAttributeNames": {
"#k_sites": "sites",
"#k_device_id": "device_id"
},
"ExpressionAttributeValues": {
":v_device_id": "161674"
}
However, I don't want to be limited by the first item in the list. Not sure if this is the best way if not would an index be the way to search this item? How would I set up that index?

Not Getting the Shape Right in DocumentDb Select

I'm trying to get only the person's membership info i.e. ID, name and committee memberships in a SELECT query. This is my object:
{
"id": 123,
"name": "John Smith",
"memberships": [
{
"id": 789,
"name": "U.S. Congress",
"yearElected": 2012,
"state": "California",
"committees": [
{
"id": 444,
"name": "Appropriations Comittee",
"position": "Member"
},
{
"id": 555,
"name": "Armed Services Comittee",
"position": "Chairman"
},
{
"id": 678,
"name": "Veterans' Affairs Comittee",
"position": "Member"
}
]
}
]
}
In this example, John Smith is a member of the U.S. Congress and three committees in it.
The result that I'm trying to get should look like this. Again, this is the "DESIRED RESULT":
{
"id": 789,
"name": "U.S. Congress",
"committees": [
{
"id": 444,
"name": "Appropriations Committee",
"position": "Member"
},
{
"id": 555,
"name": "Armed Services Committee",
"position": "Chairman"
},
{
"id": 678,
"name": "Veterans' Affairs Committee",
"position": "Member"
}
]
}
Here's my SQL query:
SELECT m.id, m.name,
[
{
"id": c.id,
"name": c.name,
"position": c.position
}
] AS committees
FROM a
JOIN m IN a.memberships
JOIN c IN m.committees
WHERE a.id = "123"
I'm getting the following results which is correct but the shape is not right. I'm getting the same membership 3 times. Here's what I'm getting which is NOT the desired result:
[
{
"id": 789,
"name": "U.S. Congress",
"committees":[
{
"id": 444,
"name": "Appropriations Committee",
"position": "Member"
}
]
},
{
"id": 789,
"name": "U.S. Congress",
"committees":[
{
"id": 555,
"name": "Armed Services Committee",
"position": "Chairman"
}
]
},
{
"id": 789,
"name": "U.S. Congress",
"committees":[
{
"id": 678,
"name": "Veterans' Affairs Committee",
"position": "Member"
}
]
}
]
As you can see here, the "U.S. Congress" membership is repeated 3 times.
The following SQL query gets me exactly what I want in Azure Query Explorer but when I pass it as the query in my code -- using DocumentDb SDK -- I don't get any of the details for the committees. I simply get blank results for committee ID, name and position. I do, however, get the membership data i.e. "U.S. Congress", etc. Here's that SQL query:
SELECT m.id, m.name, m.committees AS committees
FROM c
JOIN m IN c.memberhips
WHERE c.id = 123
I'm including the code that makes the DocumentDb call. I'm including the code with our internal comments to help clarify their purpose:
First the ReadQuery function that we call whenever we need to read something from DocumentDb:
public async Task<IEnumerable<T>> ReadQuery<T>(string collectionId, string sql, Dictionary<string, object> parameterNameValueCollection)
{
// Prepare collection self link
var collectionLink = UriFactory.CreateDocumentCollectionUri(_dbName, collectionId);
// Prepare query
var query = getQuery(sql, parameterNameValueCollection);
// Creates the query and returns IQueryable object that will be executed by the calling function
var result = _client.CreateDocumentQuery<T>(collectionLink, query, null);
return await result.QueryAsync();
}
The following function prepares the query -- with any parameters:
protected SqlQuerySpec getQuery(string sql, Dictionary<string, object> parameterNameValueCollection)
{
// Declare query object
SqlQuerySpec query = new SqlQuerySpec();
// Set query text
query.QueryText = sql;
// Convert parameters received in a collection to DocumentDb paramters
if (parameterNameValueCollection != null && parameterNameValueCollection.Count > 0)
{
// Go through each item in the parameters collection and process it
foreach (var item in parameterNameValueCollection)
{
query.Parameters.Add(new SqlParameter($"#{item.Key}", item.Value));
}
}
return query;
}
This function makes async call to DocumentDb:
public async static Task<IEnumerable<T>> QueryAsync<T>(this IQueryable<T> query)
{
var docQuery = query.AsDocumentQuery();
// Batches gives us the ability to read data in chunks in an asyc fashion.
// If we use the ToList<T>() LINQ method to read ALL the data, the call will synchronous which is why we prefer the batches approach.
var batches = new List<IEnumerable<T>>();
do
{
// Actual call is made to the backend DocumentDb database
var batch = await docQuery.ExecuteNextAsync<T>();
batches.Add(batch);
}
while (docQuery.HasMoreResults);
// Because batches are collections of collections, we use the following line to merge all into a single collection.
var docs = batches.SelectMany(b => b);
// Return data
return docs;
}
I just write a demo to test with your query and I can get the expected result, check the snapshot below. So I think that query is correct, you've mentioned that you don't seem to get any data when you make the call in my code, would you mind share your code? Perhaps there are some mistakes in you code. Anyway, here is my test just for your reference and hope it helps.
Query used:
SELECT m.id AS membershipId, m.name AS membershipNameName, m.committees AS committees
FROM c
JOIN m IN c.memberships
WHERE c.id = "123"
Code here is very simple, sp_db.innerText represents a span which I used to show the result in my test page:
var docs = client.CreateDocumentQuery("dbs/" + databaseId + "/colls/" + collectionId,
"SELECT m.id AS membershipId, m.name AS membershipName, m.committees AS committees " +
"FROM c " +
"JOIN m IN c.memberships " +
"WHERE c.id = \"123\"");
foreach (var doc in docs)
{
sp_db.InnerText += doc;
}
I think maybe there are some typos in the query you specified in client.CreateDocumentQuery() which makes the result to be none, it's better to provide the code for us, then we can help check it.
Updates:
Just tried your code and still I can get the expected result. One thing I found is that when I specified the where clause like "where c.id = \"123\"", it gets the result:
However, if you didn't make the escape and just use "where c.id = 123", this time you get nothing. I think this could be a reason. You can verify whether you have ran into this scenario.
Just updated my original post. All the code provided in the question is correct and works. I was having a problem because I was using aliases in the SELECT query and as a result some properties were not binding to my domain object.
The code provided in the question is correct.

ElasticSearch: access document nested value in groovy script

I have a document stored in ElasticSearch as below.
_source:
{
"firstname": "John",
"lastname": "Smith",
"medals":[
{
"bucket": 100,
"count": 1
},
{
"bucket": 150,
"count": 2
}
]
}
I can access the string type value inside a document using doc.firstname for scripted metric aggregation http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html.
But I am not able to get the field value using doc.medals[0].bucket.
Can you please help me out and let me know how to access the values inside nested fields?
Use _source for nested properties.
Doc holds fields that are loaded in memory. Nested documents may not be loaded and should be accessed with _source.
For instance:
GET index/type
{
"aggs": {
"NAME": {
"scripted_metric": {
"init_script": "_agg['collection']=[]",
"map_script": "_agg['tr'].add(_source.propertry1.prop);",
"combine_script": "return _agg",
"reduce_script": "return _aggs"
}
}
},
"size": 0
}

Resources