Updating GridFS metadata using Spring Data MongoDB - gridfs

I want to update single field of metadata in GrifFs files collection.
I read the documentation about Spring Data MongoDB but did not find any API for that.
The only solution I have found so far is to use the Mongo API directly to delete the existing file, and store a new one with the same _id. But this is not effective solution. The problem is specific to Spring Data MongoDB . any alternative ?

use mongoOperations.
the metadata is stored in the collection fs.files; if you are only updating the metadata you can access it by using the collection directly and update it:
DBObject yourObjectWithMetadata = mongoOperations.getCollection("fs.files").findOne(<Object Id>);
mongoOperations.getCollection("fs.files").save(<your db object with updated metadata>);

Another solution to add or entirely replace metadata fields.
Map<String,Object> fields=...;
Replacing metadata:
List<GridFSDBFile> files = gfs.find(query);
for (GridFSDBFile file : files) {
file.setMetaData(new BasicDBObject(fields));
file.save();
}
Adding metadata:
List<GridFSDBFile> files = gfs.find(query);
for (GridFSDBFile file : files) {
if (file.getMetaData() == null)
file.setMetaData(new BasicDBObject(fields));
else
file.getMetaData().putAll(fields);
file.save();
}

Related

Unable to Unlock Alfresco Document using CMIS

I'm using CMIS to make changes to alfresco document, I need to add new aspect to document, but I'm facing:
org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException: Update conflict: 06160811 Cannot perform operation since the node (id:88289ea7-16b7-40ff-938b-b2888ef5bca5) is locked.
Below is the code I'm trying to unlock the document, but it's not successful. kindly suggest other alternatives to unlock a locked document using CMIS
for (QueryResult result : results) {
String objectId = result.getPropertyValueByQueryName(PropertyIds.OBJECT_ID);
AlfrescoDocument document = (AlfrescoDocument) session.getObject(session.createObjectId(objectId));
if (document != null) {
if(document.hasAspect("P:cm:lockable")) {
System.out.println(document.getName());
document.removeAspect("P:cm:lockable");
}
} else {
System.out.println("Document is null");
}
}
What version of Alfresco and CMIS are you using? It looks like you might be using the Alfresco CMIS extension JAR, but you should not be using that at all if you are using Alfresco 5.2 (or higher) and CMIS 1.1.
If you are using CMIS 1.1, the way to remove an aspect is to remove the name of the aspect from the array of values in the cmis:secondaryObjectTypeIds array, then update the properties with the trimmed list of aspects.
With all of that said, that would just remove the lockable aspect from the document. You are trying to actually unlock the document, not remove its ability to be locked/unlocked. So instead of trying to directly manipulate the aspect, you should just call cancelCheckout() if you want to unlock the document, like:
Document doc = (Document) getSession().getObjectByPath(filePath);
doc.cancelCheckOut();
Obviously you'll need to use credentials of someone who has the permissions to do this.
Use LockService.
lockService.unlock("nodeRef of the node to unlock")

How to save images stored in assets to Firebase?

I am trying to figure out the best way to save an image (png) that is stored in my assets folder to my firebase database so I can retrieve that image/path for later use. Essentially this is what I want:
// savedPath was stored and then retrieved from database
let savedPath = '../assets/images/example.png'
return (<Image source={require(savedPath)} />)
However, if I just save the path as a string, I can not insert it into the image source like this and it throws an error. I am wondering what my alternative option is to achieve that same thing as the example above?
You can use firebase storage bucket https://firebase.google.com/docs/storage/ to store all your assets
Then you can store the file name/path in your database and access it from there.

Migrating from cfs:gridfs to cfs:s3

In a meteor project I maintain there has been cause to look at moving away from gridfs as the backend to CollectionFS and moving towards s3.
One thing I would be keen to do is migrate images / files currently stored using the gridfs collections.
Has anyone attempted this before? I can't find any guides or even suggestions.
My thinking right now is along the lines of;
Create a new collection backed by s3
Iterate over old collection pushing the data into s3
Update code to point to new collection
Does this seem sound?
I just did this!
You're basically right, here's how I did it. Migration is a pretty easy process. I've gone from GridFS to S3.
1) By adding new FS.Store.S3("store_name",{}), CollectionFS automatically clones the meta data of existing files in the old store for your new store. But, all file sizes are zero in this new store.
Images = new FS.Collection("images", {
stores: [
new FS.Store.S3("s3images", {}),
new FS.Store.GridFS("images", {})
]
});
2) While you have both stores in place, you need to manually migrate the content using the piping as referenced here https://github.com/CollectionFS/Meteor-CollectionFS/wiki/How-to:-Convert-a-file-already-stored.
if(Meteor.isServer) {
Images.find().forEach(function (fileObj) {
var readStream = fileObj.createReadStream('images');
var writeStream = fileObj.createWriteStream('s3images');
readStream.pipe(writeStream);
});
}
Hopefully after this you will now see your new store's file sizes matches the old one!
3) Optionally, remove the old store. If you keep both, inserted files are added to both, with priority given to the first store in the array.
Reference: https://github.com/CollectionFS/Meteor-CollectionFS/issues/747

Can the Path assigned a SQLite DB be an arbitrary value?

In this blog post, some prerequisite code for getting started using SQLite in Windows Store Apps is given, for adding to the OnLaunched method of App.xaml.cs:
// Get a reference to the SQLite database
this.DBPath = Path.Combine(
Windows.Storage.ApplicationData.Current.LocalFolder.Path, "customers.sqlite");
My question is: Can I use any arbitrary value to replace the "customers.sqlite" part, or does it have to match something else in my code, such as the name of my table definition class (in my case "PhotraxCoreData.cs" which, according to Mr. Green's suggestion, I added below a newly-created "Models" folder)?
My understanding is that, once I've got those classes defined (I do), and the code above in App.xaml.cs, along with this there (adapted for my SQLite classes):
using (var db = new SQLite.SQLiteConnection(this.DBPath))
{
// Create the tables if they don't exist
db.CreateTable<PhotraxBaseData>();
db.CreateTable<PhotraxNames>();
db.CreateTable<PhotraxQueries>();
}
...SQLite tables based on those classes I specified will be created, and have the name "customers.sqlite" (provided I don't change it).
So, can I use:
this.DBPath = Path.Combine(
Windows.Storage.ApplicationData.Current.LocalFolder.Path, "platypus.sqlite");
...or must it be something like:
this.DBPath = Path.Combine(
Windows.Storage.ApplicationData.Current.LocalFolder.Path, "PhotraxCoreData.sqlite");
That database name is just a file name.
The directory must be accessible by your app, but the file name can be anything.
AS CL says, the file name can be anything the app has direct access to. Windows Store apps have limited access to the file system, so the sqlite database must be in either the apps install location (read only) or it's app data folder (read write). A common pattern is to ship a seed database in the app package and then copy it from the install location to app data on first use so it can be written to.

Update entity that is not part of the client collection

I am trying to update related entities when deleting an entity. The problem is that the related entities are not part of the collection on the client. Is there a way to do the update only on the server?
Concrete example: When calling 'removeSlack', I want to update all the copies and remove the removed slackId from their copies array. But because the copies are not part of the collection on the client 'Slack.findOne(copyId)' doesn't find anything.
Meteor.methods(
removeSlack: (slackId) ->
slack = Slack.findOne(slackId)
for copyId in _.pluck(slack.copies, 'slackId')
copy = Slack.findOne(copyId)
if copy
Slack.update(copyId, { $set: {copies: _.without(copy.copies, {slackId: slackId, userId: Meteor.userId()})}})
Slack.remove(slackId)
)
You can wrap any code you only want to run on the server in a Meteor.isServer() block: http://docs.meteor.com/#meteor_isserver
Alternatively, you can put code files you only want to run on the server in the /server folder of your project.

Resources