I have a data object as below
var data = {
"name" : "Gopal",
"Age" : "29",
"Phone" : "982926272"
}
Once I pass this "data" Object to create a function to the user model, it omits the "phone" and updates this data object as below.
Users.create(data).then(function (){
console.log("Data Object after create call ",data);
//Here I am expecting to use "phone" property of "data" object
});
////Here is console
data {
name : Gopal,
Age : 29,
createdAt: 2021-02-16T18:52:36.420Z,
updatedAt: 2021-02-16T18:52:36.420Z,
}
Note: My user model doesn't have "phone" property.
I know I can save data in some other object and can use it, but my project is big and migrated from sails 0.12 to 1+.
So if anyone has an idea how I can preserve the "phone" property without creating another object.
Related
In mongodb I have many collection like below
boys_fashion
girls_fashion
gents_fashion
ladies_fashion
girls_accessories
gents_accessories
ladies_accessories
based on some fields I need to use different collection. So for that I thought to create a collection which will map to a specific collection. Below is the collection I have created for that.
{
"type" : "Fashion",
"gender" : "Gents",
"kids" : "true",
"collection" : "boys_fashion"
}
{
"type" : "Accessories",
"gender" : "Ladies",
"kids" : "false",
"collection" : "ladies_accessories"
}
{
"type" : "Fashion",
"gender" : "Gents",
"kids" : "false",
"collection" : "gents_fashion"
}
{
"type" : "Accessories",
"gender" : "Ladies",
"kids" : "true",
"collection" : "girls_accessories"
}
{
"type" : "Accessories",
"gender" : "Gents",
"kids" : "true",
"collection" : "gents_accessories"
}
{
"type" : "Accessories",
"gender" : "Gents",
"kids" : "false",
"collection" : "gents_accessories"
}
Is this is the right way to do this? or please suggest me some other ways
If I stored like below(the above option is similar to RDBMS. Since its mongo I guess I used this way). How can I write a query for fetching the collection?
{
"fashion" : {
"gents" : {
"true" : "boys_fashion",
"false" : "gents_fashion"
}
},
"accessories" : {
"ladies" : {
"true" : "girls_accessories",
"false" : "ladies_accessories"
}
}
}
Assumptions:
There were one collection before and you split them into multiple collections as they are getting large and you want to solve it without sharing.
I would not even create a collection for the following data. This data is static reference data and will act as a router. On start up, application loads this data and creates a router.
{
"type" : "Fashion",
"gender" : "Gents",
"kids" : "true",
"collection" : "boys_fashion"
}
{
"type" : "Accessories",
"gender" : "Ladies",
"kids" : "false",
"collection" : "ladies_accessories"
}
...
What do I mean by creating a kind of router by that static configuration file? Lets say you receive a query fashionable items for baby girls. This router will tell you, hey you need to search girls_accessories collection. And you send the query to girls_accessories collection and return the result.
Lets take another example, you receive a query for fashionable items for female. This router will tell you hey you need to search, ladies_accessories and girls_accessories. You send the query to both collections and combine the result and send it back.
Conclusion
If my assumptions are correct, you don't need a collection to store the reference data. What you have done is manual sharding by splitting the data across different collections, the reference data will act as router to tell you where to search and combine
Update based on comments
Query does not involve multiple collections
Administrator can add new collection and application should query it without modifying code.
Solution 1
You create a collection for the reference data too
Downside to this is that every query involves two calls to database. First to fetch the static data and second to the data collection
Solution 2
You create a collection for the reference data too
You also build a Dao on top of that which uses #Cacheable for the method that return this data.
You also add a method in Dao to clear the cache with #CacheEvict and have a rest endpoint like /refresh-static-data that will call this method`
Downside to this method is that whenever administrator add new collection, you need to call the endpoint.
Solution 3
Same as solution 2 but instead of having an endpoint to clear the cache, you combine it with scheduler
#Scheduled(fixedRate = ONE_DAY)
#CacheEvict(value = { CACHE_NAME })
public void clearCache() {
}
Downside to this solution is that you have to come up with a period for fixedRate which is acceptable to your business
I added the collection like below.
/* 1 */
{
"type" : "fashion",
"category" : [
{
"value" : "gents",
"true" : "boys_fashion",
"false" : "gents_fasion"
}
]
}
/* 2 */
{
"type" : "accessories",
"category" : [
{
"value" : "ladies",
"true" : "girls_accessories",
"false" : "ladies_accessories"
}
]
}
and will fetch the data using the below query
findOne({"type":type,"category.value":cvalue},{"_id": 0, "category": {"$elemMatch": {"value": cvalue}}})
Try to make subdocuments in MongoDB, instead of nested objects
https://mongoosejs.com/docs/subdocs.html
I have a double nested array in my MongoDB schema and I'm trying to add an entirely new array element to a second-level nested array using $push. I'm getting the error cannot use the part (...) to traverse the element
A documents have the following structure
{
"_id" : ObjectId("5d8e37eb46c064790a28a467"),
"org-name" : "Manchester University NHS Foundation Trust",
"domain" : "mft.nhs.uk",
"subdomains" : [ {
"name" : "careers.mft.nhs.uk",
"firstSeen" : "2017-10-06 11:32:00",
"history" : [
{
"a_rr" : "80.244.185.184",
"timestamp" : ISODate("2019-09-27T17:24:57.148Z"),
"asn" : 61323,
"asn_org" : "Ukfast.net Limited",
"city" : null,
"country" : "United Kingdom",
"shodan" : {
"ports" : [
{
"port" : 443,
"versions" : [
"TLSv1",
"-SSLv2",
"-SSLv3",
"TLSv1.1",
"TLSv1.2",
"-TLSv1.3"
],
"cpe" : "cpe:/a:apache:http_server:2.4.18",
"product" : "Apache httpd"
}
],
"timestamp" : ISODate("2019-09-27T17:24:58.538Z")
}
}
]
}
]
}
What I'm attempting to do is refresh the details held in the history array and add another entire array entry to represent the most recently collected data for the subdomain.name
The net result is that I will have multiple entries in the history array, each one timestamped the the date that the data was refreshed. That way I have a historical record of changes to any of the data held.
I've read that I can't use $push on a double-nested array but the other advice about using arrayfilters all appear to be related to updating an entry in an array rather than simply appending an entirely new document - unless I'm missing something!
I'm using PyMongo and would simply like to build a new dictionary containing all of the data elements and simply append it to the history.
Thanks!
Straightforward in pymongo:
record = db.mycollection.find_one()
record['subdomains'][0]['history'].append({'another': 'record'})
db.mycollection.replace_one({'_id': record['_id']}, record)
I have a simple Ember Data app to list and show various objects.
My /servers.json API (for example) return this kind of format:
[
{
"hosted_domain" : "example.com",
"status" : 1,
"name" : "srv0443",
"id" : 443
},
{
"id" : 392,
"status" : 1,
"name" : "srv0392",
"hosted_domain" : "example.com"
},
{
"hosted_domain" : "example.com",
"id" : 419,
"name" : "srv0419",
"status" : 1
}
]
But I got the following error:
Assertion Failed: The response from a findAll must be an Array, not undefined
Ember Data expects this kind of format:
{
"servers" : [
{
"name" : "srv0443",
"status" : 1,
"id" : 443,
"hosted_domain" : "example.com"
},
{
"status" : 1,
"name" : "srv0392",
"id" : 392,
"hosted_domain" : "example.com"
},
{
"status" : 1,
"name" : "srv0419",
"hosted_domain" : "example.com",
"id" : 419
},
]
}
I know I can override the payload with the extractArray of the RESTSerializer.
It's works by doing payload = { servers: payload } but how get it working in a generic way?
How can I do to catch the needed key of an model type?
In a more general way, what is the good REST format, by convention?
Thanks.
Ember Data works by having the data follow a certain convention ({servers: payload}). So the data either needs to conform, or you have to extend the serializer as you mentioned (or some other customization like overriding the model's findAll() method). There isn't anyway around it, if you want to use Ember Data. Of course, you don't have to use Ember Data. Here is a good article about not using it: http://eviltrout.com/2013/03/23/ember-without-data.html
To customize the serializer you can extend it like this:
App.ServerSerializer = DS.RESTSerializer.extend({
extractArray: function(store, type, payload) {
this._super(store, type, {servers: payload});
},
});
Extract array is automatically called by ember after it gets a response from the server. This will put in the format ember data expects, then pass it on to continue processing as usual. But you will have to do that for each type of model. If you override App.ApplicationSerializer instead you might be able to use the type paramter to figure out which key should go in the modified payload, so it will work for any model, but I can't check it right now.
Finally found a solution by using primaryType.typeKey and ember-inflector tool on the RESTSerializer:
App.ApplicationSerializer = DS.RESTSerializer.extend
extractArray: (store, primaryType, payload) ->
# Payload reload with { type.pluralize: hash }
payloadKey = Ember.Inflector.inflector.pluralize primaryType.typeKey
payloadReloaded = []
payloadReloaded[payloadKey] = payload
#_super store, primaryType, payloadReloaded
In a nutshell:
Get the type key (e.g. server)
Pluralize it (e.g. servers)
Add it as payload master key (e.g. { servers: payload }
And that's it!
Please feel free to comment this solution if you have a better proposition.
I have a lastModified attribute in my games collection. At the moment I have to manually update the lastModified attribute on every change (current timestamp).
Is it possible to update this attribute automatically when other attributes of the document will be changed?
I use Meteor 1.0.
EDIT:
Sample document:
{ "controllerId" : "ACycCfrQuTtuMwjuJ", "body" : "ABC", "userId" : "5iE4P8HPoRCSHe6k8", "lastModified" : ISODate("2015-01-06T15:48:49.346Z"), "_id" : "CQbL49FP9rZkSF7yh" }
When changing attribute body it should be like this:
{ "controllerId" : "ACycCfrQuTtuMwjuJ", "body" : "XYZ", "userId" : "5iE4P8HPoRCSHe6k8", "lastModified" : ISODate("2015-01-06T19:41:19.888Z"), "_id" : "CQbL49FP9rZkSF7yh" }
lastModified should automatically be updated when one of the other attributes changes.
As explained here, you can abuse the deny mechanism to do this for you:
Games.deny({update: function(userId, doc) {
doc.lastModified = new Date();
return false;
}})
Alternatively you can use collection hooks. Your exact use case is the example for before.update.
The date field when save to mongodb is in the format of:
{ "_id" : ObjectId("4f03283e1d4ee82215000002"), "name" : "nano3",
"category_id" : ObjectId("4f022b411d4ee8105700001c"), "price" : 20,
"production_date(3i)" : "1", "production_date(2i)" : "1",
"production_date(1i)" : "2011", "description" : "a music player with
video play function" }
when I try to get the date using #product.production_date from my model it failed. I am using Mongoid mapper
It fails because you don't have any fields named "production_date".
What you do have is fields named "production_date(3i)", "production_date(2i)", and "production_date(1i)".
You should be saving instances of the time class which can be properly serialized by the ruby driver.
Time.now or Time.utc(2011,1,1) will probably do what you want.