MongoDB query to push entry from one collection into another - mongodb

Collection 1:
nodeDB : [{
"VARIANTS": [
{"NAME" : Brand},
{"NAME" : Price},
{"NAME" : Colour},
{"NAME" : Size}
]
}]
A form is generated from VARIANTS.The values of this form are to be pushed into New DB called ProductDB
Collection2:
ProductDB [{
{"Brand" : Lee},
{"Price" : 100},
{"Color" : Red},
{"Size" : M}
}]
The values are taken from the user interface.
EDIT
JS File:
Template.dpVar.variant=nodeDB.find({}, { "VARIENTS.NAME": 1, _id : 0 } );
// Wait for a 'submit'
Template.inputDB.events = {
'submit' : function (e, tmpl) {
e.preventDefault();
var NAME= {
NAME: tmpl.find("#NAME").value
};
nodeDB.insert(template_name);
}
}

It seems you are using meteor JS.
You need to perform action onclick of submit button,
<table id="TemplateCreateNewStructure" class=" table table-withborder table-type1">
</table>
Then call ajax and display your data in table then click on submit button, insert your record in new collection like tis way
function createPreviewFormForTemplate(opt){
if VARIANTS.name == 'Brand'
tr = tr='<tr><td>'+VARIANTS.name+'</td><td <input id="dtBoxIN" class="form-control" type="text" placeholder="ENter Brand"/> <div id="dtBox"></div></td></tr>';
$("#TemplateCreateNewStructure").append(tr);
Once you done with all condition then save tables data into a object and that object you need to insert into another collection
you can get your value by using trim method
$("#submit").click(function(){
data = {
"brand": $("#dtBoxIN").val().trim(),
};
you need to send this data object to your backend code
at the backend code you need to run this command
db.collection.insert(data)

Related

Relay/Mongodb Error - Cannot Read Property of Undefined

I have this test relay-starter-kit project with an autocomplete search form that renders quotes to the browser. When I use the search form, I get an error in the browser saying "app.js:8284 Uncaught TypeError: Cannot read property 'edges' of undefined". I cant understand why its populating the search fields the first time but not on typing in the search form. Of note, if you hard code the searchTerm variable, it will render the search results. In other words, It can read the edges when its hard coded. Any guidance on this would be great. Thanks.
The schema is here
This is the component that the valid graphql query for the search term wont render to.
import React from 'react';
import Relay from 'react-relay';
import { debounce } from 'lodash';
import SearchForm from '../search-form';
import Quote from '../quote';
class App extends React.Component {
constructor(props) {
super(props)
this.search = debounce(this.search.bind(this), 300)
}
search(searchTerm) {
this.props.relay.setVariables({ searchTerm });
}
render() {
return (
<div className="quotes-library">
<SearchForm searchAction={this.search} />
<div className="quotes-list">
{this.props.viewer.quotes.edges.map(edge =>
<Quote key={edge.node.id} quote={edge.node} />
)}
</div>
</div>
)
}
}
export default Relay.createContainer(App, {
initialVariables: {
searchTerm: '',
},
fragments: {
viewer: () => Relay.QL`
fragment on User {
quotes(first:100, searchTerm: $searchTerm) {
edges {
node {
id
${Quote.getFragment('quote')}
}
}
}
}
`,
},
});
Update: This is the query as shown in Chrome DevTools network tab. Note the 'p' input to the search form is being queried.
query App_ViewerRelayQL($id_0:ID!) {
node(id:$id_0) {
...F2
}
}
fragment F0 on Quote {
id,
likesCount
}
fragment F1 on Quote {
text,
author,
id,
...F0
}
fragment F2 on User {
_quotes3UfnML:quotes(first:100,searchTerm:"pri") {
edges {
node {
id,
...F1
},
cursor
},
pageInfo {
hasNextPage,
hasPreviousPage
}
},
id
}
Adding console.log to render() shows the searchTerm input:
app.js:17
{
"viewer": {
"__dataID__": "VXNlcjox",
"__status__": 4
},
"relay": {
"pendingVariables": null,
"route": {
"name": "AppHomeRoute",
"params": {},
"queries": {}
},
"variables": {
"searchTerm": "pri"
}
}
}
The following error occurs at line 24 in app.js, which is {this.props.library.quotes.edges.map(edge =>
<Quote key={edge.node.id} quote={edge.node} />
)}:
app.js:8285 Uncaught TypeError: Cannot read property 'edges' of undefined
at App.render (app.js:8285)
at app.js:43197
at measureLifeCyclePerf (app.js:42476)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (app.js:43196)
at ReactCompositeComponentWrapper._renderValidatedComponent (app.js:43223)
at ReactCompositeComponentWrapper._updateRenderedComponent (app.js:43147)
at ReactCompositeComponentWrapper._performComponentUpdate (app.js:43125)
at ReactCompositeComponentWrapper.updateComponent (app.js:43046)
at ReactCompositeComponentWrapper.receiveComponent (app.js:42948)
at Object.receiveComponent (app.js:35341)
UPDATE 2:
So check this out. I'm doing something wrong with my { ObjectID }. I pulled a user and quote from the db and there is an '_id' but no 'id' property on the object. This is the output:
> db.users.find({})
{ "_id" : ObjectId("586253169465191cb812066c"), "name" : "me", "id" : ObjectId("586253169465191cb812066c"), "errors" : [ ] }
> db.quotes.find({})
{ "_id" : ObjectId("586693333ff93f3581c0ca05"), "text" : "Hi Prisc", "author" : "H. Jackson Brown", "likesCount" : 24 }
{ "_id" : ObjectId("586693333ff93f3581c0ca06"), "text" : "If opportunity doesn't knock, build a door", "author" : "Milton Berle", "likesCount" : 2 }
{ "_id" : ObjectId("586693333ff93f3581c0ca07"), "text" : "Try to be a rainbow in...", "author" : "Maya Angelou" }
If I log the id from the globalIdFetcher(), the logged id for the Jackson Brown Quote object show two id's as expected but they are both the same and different from the one in the db. Output in console is:
{
"viewer": {
"__dataID__": "VXNlcjo=",
"quotes": {
"__dataID__": "client:6068631311_first(100),searchTerm()",
"edges": [
{
"__dataID__": "client:client:6068631311:UXVvdGU6NTg2NjkzMzMzZmY5M2YzNTgxYzBjYTA1",
"node": {
"__dataID__": "UXVvdGU6NTg2NjkzMzMzZmY5M2YzNTgxYzBjYTA1",
"id": "UXVvdGU6NTg2NjkzMzMzZmY5M2YzNTgxYzBjYTA1",
"__fragments__": {
"1::client": [
{
"showLikes": false
}
]
}
}
},
Any ideas on fixing this syntax?
It's very difficult to solve the problem with the information provided in question. As you requested guidance, here's my suggestions :)
I cant understand why its populating the search fields the first time but not on typing in the search form.
Because Relay fetches the result for the initial value of searchTerm, which is an empty string in your case. You have to deal with this case on the server side (by checking the input searchTerm) and client side (by checking if the current value of searchTerm is empty, for example).
When you type in search form, search() isn't called and searchTerm is not updated. Check SearchForm component.
When I use the search form, I get an error in the browser saying "app.js:8284 Uncaught TypeError: Cannot read property 'edges' of undefined".
Start debugging what the server side returns for quotes field under viewer GraphQL object type. What's the output of db.collection('quotes').find(findParams).toArray() in your schema? In addition, put a console.log(JSON.stringify(this.props, null, 4)) in render() function of App class. Check what you see. You can also inspect the HTTP request and response on the Chrome DevTools Network tab. Filter by graphql.
Solution was to take the Quote type out of the nodeInterface so only running the top level object through the nodeInterface, let relay generate the id for the objectId from the GraphQLID or fromGlobalId as defined in the individual itemType.

What am I doing wrong when manipulating data in Meteor/MongoDB?

I have this helper
myClub: function(){
var currentUserId = Meteor.userId();
var user = Meteor.users.findOne({_id: currentUserId});
return user;
}
I want it to return user.role
Here is my user in MongoDB
{
"_id" : "RdirmrLG3t8qBk4js",
"createdAt" : ISODate("2016-04-17T19:40:56.877Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$cPe92XR9DT238bH/RanYEu.J6K2ImvAEbWOcVq6j9luI0BH08Qdly"
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2016-04-17T19:51:49.474Z"),
"hashedToken" : "uVKUj/7JEkkOuizXhjl212Z38E47HXCex+D4zRikQ1k="
}
]
}
},
"username" : "worker",
"role" : "worker",
"club" : "hzSKAJfPXo7hSpTYS"
}
The code above works just fine. So it finds the current user and outputs info about it. But when I change user to user.role I get the following errormessage.
TypeError: Cannot read property 'role' of undefined
at Object.myClub
How can it be undefined? Is my syntax incorrect?
Template helpers are reactive, which means they update themselves as the app state changes or new data appears. In your case, the helper is called immediately when the template is rendered and before the Meteor.users collection is filled. Therefore, the .findOne() method returns undefined. It will be corrected in the second pass after new data arrives.
The simple fix here is to check whether the data is present inside the helper:
myClub: function(){
var currenUserId = Meteor.userId();
var user = Meteor.users.findOne({_id: currenUserId});
if(!user) return 'NO DATA';
return user.role;
},
In real life you'll probably want to wait for the basic data to be loaded before you render the template. That is usually done on the controller level.
Try:
myClub: function(){
return Meteor.user() && Meteor.user().role;
}
This is shorthand for return the role if there's a user.
As far as the role field not showing up, make sure that you are publishing that key from the server and subscribing to it. For example:
Meteor.publish('me',function(){
return Meteor.users.find(this.userId,{fields: {role: 1, username: 1, profile: 1, emails: 1}});
});
And on the client:
var me = Meteor.subscribe('me');
if ( me.ready() ) console.log("Ta-da! The role is: "+Meteor.user().role);
make sure that you subscribed to all data you need.
By the way, you can try following:
role: function(){ return (Meteor.user() || {}).role; }
Cheers

Using Dynamic templates correctly in Meteor

Passing values dynamically through templates in meteor fails, whereas doing so statically succeeds. What am I doing wrong? The set-up is as follows
I have the following 2 templates set-up in Meteor
<template name="search">
{{#each cards}}
{{>card}}
{{/each}}
<template name="card">
<div class="card">
{{docName}}
</div>
</template>
Passing values to this like this works perfectly
if (Meteor.isClient) {
Template.search.helpers({
cards: [
{docName: "Dr. Maga" },
{docName: "Dr. Macha" },
]
});
}
However, passing the same values dyamically like this fails
Cards = new Mongo.Collection("cards");
if (Meteor.isClient) {
Template.search.helpers({
cards: function() {
return Cards.find({});
}
});
}
There is data in the mongo collection "Cards". I insert it after the app starts by using
db.Cards.insert({ docName: "Hello world!", createdAt: new Date() });
and verify it using the following command
db.Cards.find()
which returns
{ "_id" : ObjectId("558b0a1394990bf66c75775d"), "docName" : "Hello world!", "createdAt" : ISODate("2015-06-24T19:50:42.996Z") }
What am I doing wrong?
The error was that the Cards collection was defined on the client side only. (Under the Meteor.isClient() Code block).
This means that meteor was trying to read from the Server, couldn't find the item coz it wasn't defined in the server side, and failed.
Solution is to define it in the "both" folder so that both server and client can access the collection.
http://docs.meteor.com/#/basic/filestructure
Of course, don't forget to publish and subscribe to the collection.

Show key value pair in table using meteor and mongo db

In mongodb i have json values like and it is not fixed. Some time it will be only 2 or 3 and sometime it will be very large.
{"_id" : "p83oZAo7fdhNuDD34",
"Active Template Name" : "Windows Mobile",
"ProductId" : "456",
"Subcategory" : "on",
"Size" : "on",
"Material" : "A",
"Price" : "2345",
"Combo Id" : "67u",
"Color" : "red",
"Status" : "Pending"
},
{
"_id" : "p83oZAo7fdhNuDD34",
"Material" : "A",
"Price" : "2345",
"Combo Id" : "67u",
"Color" : "red",
"Status" : "Pending"
}
I want to show all keys like (id, Active Template Name, ProductID .......) as table header and values (p83oZAo7fdhNuDD34,Windows Mobile,456 .......) in tbody.
I am not getting the exact way to perform this in meteor. My collection name is products and Html code is bellow.
<template name="productvalue">
<table>
</table>
</template>
Use a {{#each}} block helper to iterate over your collection products.
<template name="productvalue">
<table>
<thead>
<th>Id</th>
<th>Active Template Name</th>
<th>ProductId</th>
[...]
</thead>
<tbody>
{{#each products}}
<tr>
<td>{{_id}}</td>
<td>{{activeTemplateName}}</td>
<td>{{ProductId}}</td>
[...]
</tr>
{{/each}}
</tbody>
</table>
</template>
You also need to define helpers to rename the problematic keys containing invalid Spacebars characters.
Template.productvalue.helpers({
products: function(){
return Products.find();
},
activeTemplateName: function(){
return this["Active Template Name"];
},
[...]
});
If you want to display a table with all the possible properties in the header, and each row with each column filled or not whether the property is defined or not for the document in that row, then you will need to:
Ahead of time (in onCreated or onRendered), find all possible properties for your dataset, order them, and store them in a "header" object accessible to your helpers. (either in Session or using a reactive variable) Make it reactive if necessary, using this.autorun().
Then, do the same as above, except just returning the stored ordered list for tableHeader
And for rowContent, iterate over your stored header and fill an array with empty strings for each undefined field in the current document
Example:
function getHeader(products) {
var header = {};
for (var key in products) {
for (var property in products[key]) {
header[property] = true;
}
}
return Object.keys(header);
}
Template.productvalue.onRendered(function () {
var products = Products.find().fetch();
Session.set('header', getHeader(products));
this.autorun(function () {
var products = Products.find().fetch();
Session.set('header', getHeader(products));
});
});
Template.productvalue.helpers({
'tableHeader': function () {
return Session.get('header');
},
'rowContent': function (document) {
var row = [];
var header = Session.get('header');
for (var key in header) {
row.push(document[header[key]] || "");
}
return row;
}
});
And in template:
<template name="productvalue">
<table>
<thead>
{{#each tableHeader}}
<th>{{this}}</th>
{{/each}}
</thead>
<tbody>
{{#each products}}
<tr>
{{#each rowContent this}}
<td>{{this}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
</template>
I still recommend using a reactive variable instead of Session, but the demonstration is complicated enough as it is.

mongodb query field in object that is being edited

How can I query a field in an object? My html retrieves all the objects in array called 'postcards'
Meteor.user.profile.postcards [
{
_id: 84fh83f,
field_one: "a name",
field_two: " winter whether",
field_three: " lost more writing"
},
{
_id: 6jsf58s,
field_one: "another name",
field_two: " topical issues ",
field_three: " lost more writing"
}
]
Note: I used random.Id() so each object in the array can be uniquely identified.
Setting a session value to this._id when the user is focused on the input field will retrieve this unique id, however, I would like to query the actual field in focus. The value in these fields are projected within the text input area by using the spacebars syntax within the html.
Can I somehow assign the name within the curly braces of the value attribute to a variable? Then query?
Is there a whole new way to achieve this?
I want to update that specific field in this object instead updating the entire object.
HTML:
{{#with currentUser.profile}}
{{#each postcards}}
<input id="one" value="{{field_one}}" type="text">
<input id="two" value="{{field_two}}" type="text">
<input id="three" value="{{field_three}}" type="text">
{{/each}}
{{/with}}
client.js
Within events, I would like to update the field on focus upon keyup.
Templates.myTemplate.events({
'keyup input[type=text]': _.throttle(function(event) {
Meteor.users.update(this._id, {$set: {**fieldbeingedited**: event.target.value}});
}, 500);
});
What you want to have is an ES6 capability named 'Computed property names'.
This is what is looks like :
var x = 'hello',
obj = {
[x]: 'world'
};
console.log(obj); // Object {hello: "world"}
You have two options :
- you use the meteor harmony package to transpile your es6 to es5 (https://github.com/mquandalle/meteor-harmony)
- you build your object first
To build you object first :
var obj = {};
obj[ this.targetField ] = event.target.value
Meteor.users.update(this._id, {$set: obj});