Subscribe to a child array of the collection document - javascript

I have a collection which represents the uploaded files for the user with a structure like so:
{
_id : SKHdspjhs92346
files : [ { file_name : "1.txt" , file_path : "/home/test1"/} , { file_name : "2.txt" , file_path : "/home/test2"/} ]
}
I want to subscribe to this collection array changings.
So when client uploads a file im doing a push :
AttachmentsList.update({_id : id},
{ $push: { files : {file_name : fileName, file_path: filePath}}});
And a pull when deleted:
AttachmentsList.update( {"_id": id }, {"$pull": { "files" : {file_name : fileName,file_path: filePath} } } );
I want the elements dinamically change in template. Is it possible to do so? Currently i have this publisher
Meteor.publish("attachments_list_limited", function (count,id) {
var test = AttachmentsList.find({_id : id}, { "files.$": 1 },{limit: count}, {sort: {"files.file_name": -1}});
console.log("changed, gout elements: " + test.count());
return test;
});
But it doesnt work reactively like that.

You could have a look at https://github.com/peerlibrary/meteor-reactive-publish to try to make your publish reactive to the user structure's updates through #autorun.

Related

Store a dataURL in MongoDB to access it via local URL (JS)

So I don't know if my title is clear enough, what I want to do is, in my Meteor App, to have a tool that upload a file into my MongoDB, and output an URL that I could use it for example to display as the src of an
Yet, I create my Collection:
export const Files = new Mongo.Collection('files');
and a addFile function :
export const addFile = (nameArg: String, dataURL: String) => {
Files.insert({
_id: uuid(),
name: nameArg,
url: dataURL
});
console.log("file "+nameArg+" added");
};
Then I use the react-jsonschema-form package to display a file form
<Form
schema={{
type: 'object',
properties: {
file: {
type: 'string',
title: 'Upload an image to get its URI'
}
}
}}
uiSchema={{
file: {
'ui:widget': 'file'
}
}}
onChange={this.onChange}
liveValidate
>
<div />
</Form>
My onChange function :
onChange = (e: { formData: { file: string } }) =>{
const [dataType, nameBis,] = e.formData.file.split(';');
const name = nameBis.split('=')[1];
Promise.resolve().then(addFile(name, e.formData.file));
}
And I'd like to use an address sush as window.location.host+'/file/'+name
to be able to use this image.
I believe it to be possible, but how ?
Thanks for all responses :)
This is very much possible and in a secure way using packages cfs:standard-packages and cfs:filesystem. Frankly speaking, I did not go in depth for your question.
It is a beautiful package. You can read about above here packages in depth.
CODE TO CREATE FILESYSTEM COLLECTION
var imageStore = new FS.Store.FileSystem("YOUR_COLLECTION_NAME");
YOUR_COLLECTION_NAME = new FS.Collection("YOUR_COLLECTION_NAME", {
stores: [imageStore]
});
In Short. The files will be saved at the sibling to bundle/ location at cfs/files/YOUR_COLLECTION_NAME. Information about the file will be saved in the collection cfs.YOUR_COLLECTION_NAME.filerecord and temporary location will be used for internal purpose with collection cfs._tempstore.chunks as below.
If you save any file using above package. The metadata will be saved inside the cfs.YOUR_COLLECTION_NAME.filerecord as below
{
"_id" : "TBmxbsL2cMCM2tEc7",
"original" : {
"name" : "photo.jpg",
"updatedAt" : ISODate("2017-07-06T12:54:50.115Z"),
"size" : 2261,
"type" : "image/jpeg"
},
"uploadedAt" : ISODate("2017-07-08T06:58:32.433Z"),
"copies" : {
"YOUR_COLLECTION_NAME" : {
"name" : "photo.jpg",
"type" : "image/jpeg",
"size" : 2261,
"key" : "YOUR_COLLECTION_NAME-TBmxbsL2cMCM2tEc7-photo.jpg",
"updatedAt" : ISODate("2017-07-08T06:58:32.475Z"),
"createdAt" : ISODate("2017-07-08T06:58:32.475Z")
}
}
}
at Client side, you can get the link to the document file using
YOUR_COLLECTION_NAME.find({"_id" : "TBmxbsL2cMCM2tEc7"}).url();
This url is token based safe link to the file instead of direct location to your server. You can set additional allow/deny settings for download ans stuff just like normal collections. Hope this helps!

How to parse through a json array?

By using node js I generate the array below(2) , by parsing through multiple json files for a particular value.
My json files contains a list of IDs with their status : isAvailable or undefined.
So In my code i parse through all my json files but looking only for the first ID and get the statuts of Availability in the picture bellow. When it's true t means that the ID is available. As you can see the name of the file, it's the date and the hour the json was produced.
So What I want to achieve is write a function or anything simple, where i go through the array you can see in the picture.
Example:
We can see that the status is available for the first file, I wanna recover first file name with status available
("{ fileName: '2017-03-17T11:39:36+01:00',
Status: Available }"
when the status stop being available, in our example that would be here ( { fileName: '2017-04-06T11:19:17+02:00', contents: undefined } )
get:
{ fileName: '2017-04-06T11:19:17+02:00', Status: unavailable }
(2)
So here is part of my code where I generate this array :
Promise.mapSeries(filenames, function(fileName) {
var contents = fs
.readFileAsync("./availibility/" + fileName, "utf8")
.catch(function ignore() {});
return Promise.join(contents, function(contents) {
return {
fileName,
contents
};
});
}).each(function(eachfile) {
if(eachfile.contents){
jsonobject = JSON.parse(eachfile.contents);
if(jsonobject && jsonobject.hasOwnProperty('messages'))
// console.log(jsonobject.messages[0].message.results[2]);
eachfile.contents = jsonobject.messages[0].message.results[1].isAvailable;
}
eachfile.fileName = eachfile.fileName.substring('revision_'.length,(eachfile.fileName.length-5));
console.log(eachfile);
})
May someone help me please
Thank you,
Suppose you have an array:
[
{
filename : "2017-03-23 00:00:00",
contents : true
},
...
{
filename : "2017-03-23 00:00:00",
contents : undefined
},
{
filename : "2017-03-23 00:00:00",
contents : undefined
},
{
filename : "2017-03-23 00:00:00",
contents : true
}
]
where the ... represents a long stream of objects where the contents value is true.
You want to end up with a list of objects without consequent objects with the same contents value, meaning the result would look like:
[
{
filename : "2017-03-23 00:00:00",
contents : true
},
{
filename : "2017-03-23 00:00:00",
contents : undefined
},
{
filename : "2017-03-23 00:00:00",
contents : true
}
]
Im going to use jQuery because this is a javascript framework I am familiar with, but you should be able to translate it with ease to whatever framework you're using.
function doit(dataArray) {
var resultList = [];
var currentContent = "";
$.each(dataArray, function(index, value) {
if(currentContent != value.content) {
resultList.push(value);
currentContent = value.content;
}
});
console.log(resultList);
}
Note that you need an array with the data that looks like the data in your picture, however, you print every row. You might need to add those rows into a new array, and then pass that array to this function.

fetch data in meteor based on sub element

I have issue regarding publishing collection.
I have model of each document in collection.
{
"_id" : "8SwmMoMHTREDNDQTN",
"persons" : [
{
"userId" : "29pr753gmyDxQZzo6",
"lastReadTime":""
},
{
"userId" : "gWKbYKiQsFzdCTwkz",
"lastReadTime":""
}
]
}
Now i want to publish document which persons.userId have current user id
Here is my publish code
Meteor.publish("chatRooms", function(){
return userData.find({persons:{$elemMatch:{userId:this.userId}}});
});
But is it is nothing
i had also try below code
Meteor.publish("chatRooms", function(){
return userData.find({"persons.userId":this.userId});
});
But also getting result data 0
How can i publish this way?

backbone-relational .set() method not updating related models

I've got backbone-relational working fairly well so far. I have relationships and reverse relationships well established (see below). When I initially call .fetch() on my Country model instance, the nominees array is parsed out into nominee models perfectly.
When I call .fetch() again later, however, these related models do not update, even though the nominee data has changed (e.g. the vote count has incremented). Essentially it seems that Backbone's .set() method understands relationships initially but not subsequently.
Country Model
var Country = Backbone.RelationalModel.extend({
baseUrl : config.service.url + '/country',
url : function () {
return this.baseUrl;
},
relations : [
{
type : Backbone.HasMany,
key : 'nominees',
relatedModel : Nominee,
collectionType : Nominee_Collection,
reverseRelation : {
key : 'country',
includeInJSON : false
}
}
]
});
JSON Response on country.fetch()
{
"entrant_count" : 1234,
"vote_count" : 1234,
"nominees" : [
{
"id" : 3,
"name" : "John Doe",
"vote_count" : 1,
"user_can_vote" : true
},
{
"id" : 4,
"name" : "Marty McFly",
"vote_count" : 2,
"user_can_vote" : true
}
]
}
Any help would be greatly appreciated, as always.
So it appears that backbone-relational specifically forgoes updating relations automatically (see the updateRelations method), and simply emits a relational:change:nominees event which your models can target. If, however, you wish to programmatically update your related models, simply modify the updateRelations method as follows:
Backbone.RelationalModel.prototype.updateRelations = function( options ) {
if ( this._isInitialized && !this.isLocked() ) {
_.each( this._relations || [], function( rel ) {
// Update from data in `rel.keySource` if set, or `rel.key` otherwise
var val = this.attributes[ rel.keySource ] || this.attributes[ rel.key ];
if ( rel.related !== val ) {
this.trigger( 'relational:change:' + rel.key, this, val, options || {} );
// automatically update related models
_.each(val, function (data) {
var model = rel.related.get(data.id);
if (model) {
model.set(data);
} else {
rel.related.add(data);
}
});
}
}, this );
}
};
(Note that this does not handle deletion of models from a collection, only updates to existing models, and the addition of new models to a collection)

ExtJS: return total rows/records in json store

I have a json store that returns values in json format. Now I need to get the number of rows/records in the json string but when I use store.getCount() function it returns 0, but the combobox is populated with rows, and when I use store.length I get undefined, probably because its not an array anymore, its returning from store, which is calling php script. Anyways, whats the best approach for this problem?
Try this out:
var myStore = Ext.extend(Ext.data.JsonStore, {
... config...,
count : 0,
listeners : {
load : function(){
this.count = this.getCount();
}
}
Ext.reg('myStore', myStore);
and then use inside panels:
items : [{
xtype : 'myStore',
id : 'myStoreId'
}]
Whenever you need to get the count then you can simply do this:
Ext.getCmp('myStoreId').count
Your Json response from server, can be something like this...
{
"total": 9999,
"success": true,
"users": [
{
"id": 1,
"name": "Foo",
"email": "foo#bar.com"
}
]
}
Then you can use reader: {
type : 'json',
root : 'users',
totalProperty : 'total',
successProperty: 'success'
} in your store object.
As from docs if your data source provided you can call getTotalCount to get dataset size.
If you use ajax proxy for the store, smth like
proxy : {
type : 'ajax',
url : 'YOUR URL',
reader : {
type : 'json',
root : 'NAME OF YOUR ROOT ELEMENT',
totalProperty : 'NAME OF YOUR TOTAL PROPERTY' // requiered for paging
}
}
and then load your store like
store.load();
There will be sent Ajax asynchronous request, so you should check count in callback like this
store.load({
callback : function(records, operation, success) {
console.log(this.getCount()); // count considering paging
console.log(this.getTotalCount()); // total size
// or even
console.log(records.length); // number of returned records = getCount()
}
});

Categories