I'm using a model tree structure for my collection. As references I'm using parent-fields. I need to get attributes from the current object and all its parents. The last element in a path has a field 'target'. So I start with
var result = parent = Articles.findOne({target: this.params._id});
do {
parent = Articles.findOne({_id: parent.parent}).parent;
for (var attrname in parent) { result[attrname] = parent[attrname]; }
}
while (parent.parent === null);
That seems to be very inefficient to me. Isn't it possible to do that with one line to get an object with all elements? Then I could process that object.
Example documents
{
"_id" : "LD6h5ZcDuJjexfKfx",
"title" : "title",
"publisher" : "public",
"author" : "author"
}
{
"_id" : "KSiyh8zHRq8RZQ2E6",
"edition" : "edition",
"year" : "2020",
"parent" : "LD6h5ZcDuJjexfKfx"
}
{
"_id" : "5yCk4y25wrLBLZhyY",
"pageNumbers" : "1-10",
"target" : "9sjhzPhyTuQ5Kbh6v",
"parent" : "KSiyh8zHRq8RZQ2E6"
}
So starting with "target" : "9sjhzPhyTuQ5Kbh6v" I would like to get the two parent documents (in this example).
At least I need the dataset
"title" : "title",
"publisher" : "public",
"author" : "author",
"edition" : "edition",
"year" : "2020",
"pageNumbers" : "1-10"
If you want to do this in a single query then you need to follow the array of ancestors pattern in Mongodb. Otherwise you need to recursively traverse the branches above the leaf node as you are doing. For hierarchies with low depth such as yours this is not a big penalty.
With an array of ancestors your doc tree would look like:
{
"_id" : "LD6h5ZcDuJjexfKfx",
"title" : "title",
"publisher" : "public",
"author" : "author",
}
{
"_id" : "KSiyh8zHRq8RZQ2E6",
"edition" : "edition",
"year" : "2020",
"ancestors" : ["LD6h5ZcDuJjexfKfx"],
"parent" : "LD6h5ZcDuJjexfKfx"
}
{
"_id" : "5yCk4y25wrLBLZhyY",
"pageNumbers" : "1-10",
"target" : "9sjhzPhyTuQ5Kbh6v",
"ancestors" : ["LD6h5ZcDuJjexfKfx","KSiyh8zHRq8RZQ2E6"],
"parent" : "KSiyh8zHRq8RZQ2E6"
}
To get the doc and its parents:
Articles.find({ $or: [ { target: target },
_id: { $in: Articles.findOne({ target: target }).ancestors }]});
Related
I am trying to filter firebase data using startAt and/or endAt.
My data is structured as below.
{
"notes" : {
"-LOs0Ikx4ydM5RatREM1" : {
"data" : {
"dueDate" : 1561629600000,
"description" : "Korewa nan desuka?!",
"createdAt" : 1539611900000,
"title" : "First "
},
"members" : {
"author" : "1212121212121212121212121212"
}
},
"-LOs0Ikx4ydM5RatREM2" : {
"data" : {
"dueDate" : 4004870448000,
"description": "Test"
"createdAt" : 1539611900000,
"title" : "Second"
},
"members" : {
"author" : "1212121212121212121212121212"
}
},
"-LhBt9msLFKqUQ-koI9W" : {
"data" : {
"dueDate" : 1564653600000,
"description" : "abc",
"createdAt" : 1560363158279,
"title" : "August 1"
},
"members" : {
"author" : "3434343434343434343434343434"
}
},
"-LhBtKdDrQv9eKuYdfCi" : {
"data" : {
"dueDate" : 1564653600000,
"description" : "abcdef",
"createdAt" : 1560363158279,
"title" : "August 2"
},
"members" : {
"author" : "3434343434343434343434343434"
}
}
}
}
What I wish is to fetch all "notes" where dueDate has passed.
const now = moment().valueOf() //Eg. 1561629500000
database.ref('notes/')
.orderByChild("dueDate")
.endAt(now)
.once("value", (snapshot) => {
console.log('Process expired notes')
snapshot.forEach( (data) => {
const obj = data.val()
console.log('Date comparison:', (now >= obj.data.alertDate))
...
The code above does not work, it returns all the objects from the example JSON. The console.log logs "False" for three out of four returned objects.
I could do a comparison and only process the objects that meets my criteria, but that would defeat the purpose.
I have indexed the database on ["notes\data\alertDate"].
What am I missing? I must have misinterpreted the documentation somehow. :)
Your dueDate property is nested under data, so you need to address is as data/dueDate:
database.ref('notes')
.orderByChild("data/dueDate")
You might want to include both a startAt() and endAt() clause, with just a reasonable value for startAt() and the specific value you're already using for endAt().
I am new to javascript.
I would like to check whether the specific nested property is present or not in an array of items, ex)
[{
"_id" : ObjectId("5c4ec057e21b840001968d31"),
"status" : "ACTIVE",
"customerId" : "sample-book",
"bookInfo" : {
"bookChunks" : [
{
"key" : "Name",
"value" : "test"
},
{
"key" : "Surname1",
"value" : "testtt"
},
{
"key" : "user-contact",
"value" : "sample-value",
"ContactList" : {
"id" : "sample-id",
"timeStamp" : "Tue, 20 Sep 2016 07:49:25 +0000",
"contacts" : [
{
"id" : "contact-id1",
"name" : "Max Muller",
"phone_number" : "+XXXXXXX"
},
{
"id" : "contact-id2",
"name" : "Max Muller",
"phone_number" : "+XXXXXXX"
}
]
}
}
]
}
},
{
"_id" : ObjectId("5c4ec057e21b840001968d32"),
"status" : "ACTIVE",
"customerId" : "sample-book1",
"bookInfo" : {
"bookChunks" : [
{
"key" : "Name",
"value" : "test"
},
{
"key" : "Surname1",
"value" : "testtt"
}
]
}
}]
Here, I would like to find whether any item has ContactList or contacts present. If it is present take the item and put it in a separate list.
I am using ember-lodash. Using normal javascript or lodash would be fine for me. Any help will be really appreciated.
You could use filter and some. This returns all the objects which have at least one object with ContactList property inside bookInfo.bookChunks array.
const input=[{"_id":"5c4ec057e21b840001968d31","status":"ACTIVE","customerId":"sample-book","bookInfo":{"bookChunks":[{"key":"Name","value":"test"},{"key":"Surname1","value":"testtt"},{"key":"user-contact","value":"sample-value","ContactList":{"id":"sample-id","timeStamp":"Tue, 20 Sep 2016 07:49:25 +0000","contacts":[{"id":"contact-id1","name":"Max Muller","phone_number":"+XXXXXXX"},{"id":"contact-id2","name":"Max Muller","phone_number":"+XXXXXXX"}]}}]}},{"_id":"5c4ec057e21b840001968d32","status":"ACTIVE","customerId":"sample-book1","bookInfo":{"bookChunks":[{"key":"Name","value":"test"},{"key":"Surname1","value":"testtt"}]}}]
const output = input.filter(o =>
o.bookInfo.bookChunks.some(c => "ContactList" in c)
)
console.log(output)
If you just want to check if any of the objects have ContactList, you could replace filter with another some
(Note: This assumes that bookInfo.bookChunks will not be undefined. Otherwise you'd have to add a undefined check before using the nested property)
I have a collection that consists of posts. Inside those post objects are properties about the post, one of which being an array of tags associated with the post. Inside the array of tags are more objects, each of which are the tags with a name property. I would like to get back all the posts from this collection which have a given tag in them based on the name of the tag.
Here is an example of a post object within the collection:
{
"_id" : ObjectId("5c6a0478cba09c148b497fc6"),
"tags" : [
{
"_id" : "5c69d974e05511106048780e",
"name" : "Food",
"text_color" : "#ffffff",
"bg_color" : "#02569b",
"createdAt" : "2019-02-17T22:00:20.143Z",
"updatedAt" : "2019-02-17T22:00:20.143Z",
"__v" : 0
},
{
"_id" : "5c69d95de05511106048780d",
"name" : "Drinks",
"text_color" : "#ffffff",
"bg_color" : "#0175c2",
"createdAt" : "2019-02-17T21:59:57.758Z",
"updatedAt" : "2019-02-17T21:59:57.758Z",
"__v" : 0
}
],
"title" : "Title of the post",
"body" : "body of the post",
"author_id" : ObjectId("5c5e0d3b647f12e949cbea1e"),
"author_name" : "garrett",
"likes_count" : 1,
"createdAt" : ISODate("2019-02-18T01:03:52.497Z"),
"updatedAt" : ISODate("2019-02-28T00:25:21.969Z"),
"__v" : 0,
"dislikes_count" : 0
}
Of course I have other post objects in this collection, some of which may have different tags. How can I get all posts with the food tag to be returned?
A basic find query will do the job here. Here's how it looks
const tagName = 'food;
db.posts.find({ 'tags.name': tagName }).then(console.log);
My collection looks like this:
> db.projects_columns.find()
{ "_id" : "5b28866a13311e44a82e4b8d", "checkbox" : true }
{ "_id" : "5b28866a13311e44a82e4b8e", "field" : "_id", "title" : "ID", "sortable" : true }
{ "_id" : "5b28866a13311e44a82e4b8f", "field" : "Project", "title" : "Project", "editable" : { "title" : "Project", "placeholder" : "Project" } }
{ "_id" : "5b28866a13311e44a82e4b90", "field" : "Owner", "title" : "Owner", "editable" : { "title" : "Owner", "placeholder" : "Owner" } }
{ "_id" : "5b28866a13311e44a82e4b91", "field" : "Name #1", "title" : "Name #1", "editable" : { "title" : "Name #1", "placeholder" : "Name #1" } }
{ "_id" : "5b28866a13311e44a82e4b92", "field" : "Name #2", "title" : "Name #2", "editable" : { "title" : "Name #2", "placeholder" : "Name #2" } }
{ "_id" : "5b28866a13311e44a82e4b93", "field" : "Status", "title" : "Status", "editable" : { "title" : "Status", "type" : "select", "source" : [ { "value" : "", "text" : "Not Selected" }, { "value" : "Not Started", "text" : "Not Started" }, { "value" : "WIP", "text" : "WIP" }, { "value" : "Completed", "text" : "Completed" } ], "display" : "function (value, sourceData) { var colors = { 0: 'Gray', 1: '#E67C73', 2: '#F6B86B', 3: '#57BB8A' }; var status_ele = $.grep(sourceData, function(ele){ return ele.value == value; }); $(this).text(status_ele[0].text).css('color', colors[value]); }", "showbuttons" : false } }
You can see that in the very last document that I have stored a function as text.Now the idea is that I will request this data and will be in an Javascript Array format.
But I want to be able to have my function without the quotes! You can see that simply evaluating it will not work because I need to have it still needs to be inside of the object ready to be executed when the array is used.
How can I achieve this?
Thanks for any help!
There are two possible solutions, but neither particularly safe and you should strongly consider why you need to store functions as strings in the first place. That being said, you could do two things.
The simplest is to use eval. To do so, you would have to first parse the object like normal, and then set the property that you want to the result of eval-ing the function string, like so:
// Pass in whatever JSON you want to parse
var myObject = JSON.parse(myJSONString);
// Converts the string to a function
myObject.display = eval("(" + myObject.display + ")");
// Call the function with whatever parameters you want
myObject.display(param1, param2);
The additional parentheses are to make sure that evaluation works correctly. Note, that this is not considered safe by Mozilla and there is an explicit recommendation not to use eval.
The second option is to use the Function constructor. To do so, you would need to restructure your data so that you store the parameters separately, so you could do something like this:
var myObject = JSON.parse(myJSONString);
// displayParam1 and displayParam2 are the stored names of your parameters for the function
myObject.display = Function(myObject.displayParam1, myObject.displayParam2, myObject.display)
This method definitely takes more modification, so if you want to use your existing structure, I recommend eval. However, again, make sure that this is absolutely necessary because both are considered unsafe since outside actors could basically inject code into your server.
My current doc is like this
{
"_id" : ObjectId("55ece69df332eb0000d34e12"),
"parent" : "P1",
"hierarchy" : {},
"hidden" : false,
"type" : "xyz",
"name" : "Mike",
"code" : "M110",
"date" : ISODate("2015-09-07T01:21:33.965Z"),
"__v" : 3,
"job_id" : "ca50fdf0-6904-11e6-b9af-1b0ea5d7f792"
}
now i want to have job_id as array instead. So i changed the field type to array in model schema. Now when I try to update the existing docs with some changes.
Document before saving looks like this
{
"_id" : ObjectId("55ece69df332eb0000d34e12"),
"parent" : "P1",
"hierarchy" : {},
"hidden" : false,
"type" : "xyz",
"name" : "Mike",
"code" : "M110",
"date" : ISODate("2015-09-07T01:21:33.965Z"),
"__v" : 3,
"job_id" : ["ca50fdf0-6904-11e6-b9af-1b0ea5d7f792",
"f1f04a95-42fa-41e5-a2c6-89c52c9c63f2"
]
}
so when i call model.save() method i'm getting following error:
{ [MongoError: The field 'job_id' must be an array but is of type String in document {_id: ObjectId('55ece69df332eb0000d34e12')}]
name: 'MongoError',
code: 16837,
err: 'The field \'job_id\' must be an array but is of type String in document {_id: ObjectId(\'55ece69df332eb0000d34e12\')}' }
What is the best way to handle this??