Storing binary objects in Neo4j - neo4j

Neo4j doesn't seem to allow me to store binary objects. Does this mean I must used Neo4j in conjuntion with another data store, such as the filesystem., Oracle, etc?

Daniel already answered that it's possible to store binary objects in Neo4J.
But i would suggest you not to do so. You can do nothing interesting with binary objects in database. You cannot search them. The only thing you will achieve by storing binary objects - grow the file size of your database. Mind you, Neo4J is not scalable horizontally. It does not have automatic sharding. So if your db grows too big, you are in trouble. By storing binaries in a file system or external distributed key-value store like riak, cassandra, hadoop etc, you are keeping your database small, which is good for performance, backups and avoiding horizontal scaling problems.

If you look in the API here: http://api.neo4j.org/1.2/org/neo4j/graphdb/PropertyContainer.html#setProperty(java.lang.String, java.lang.Object), you see that byte arrays are allowed.
Using byte-arrays you can store your binary objects. When you store binary objects (using Java) in Oracle, you load in the data as byte[] as well.

You can store binary objects as byte[] or encoded in a String, but I would recommend to store larger (e.g. > 1,000 bytes) blobs as separate files, and only keep a reference to the file in your database.
We do this in Structr (http://structr.org) as well.

As mentioned doing this is highly disadvantageous.
However if you decide to do so, you could do it like this in C#:
using Neo4jClient;
using Neo4jClient.Cypher;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Neo4JBlob
{
class Program
{
static void Main(string[] args)
{
try
{
GraphClient client = new GraphClient(new Uri("http://localhost:7474/db/data"));
client.Connect();
byte[] image = File.ReadAllBytes("image.jpg");
BlobNode blob = new BlobNode(){Blob = image, name = "An image: " + DateTime.Now.ToShortDateString()};
client.Cypher.Create("(blob:Blob {category})").WithParam("category", blob).ExecuteWithoutResults();
var res = client.Cypher.Match("(b:Blob)").Return<BlobNode>(b => b.As<BlobNode>()).Limit(1).Results;
BlobNode BlobReturned = res.First();
File.WriteAllBytes("image_returned.jpg", BlobReturned.Blob);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
class BlobNode
{
public byte[] Blob
{
get;
set;
}
public string name
{
get;
set;
}
}
}
}

Related

Possible to initialise Consul Key Value store at startup?

I can initialise the Consul services at startup using the /consul/config directory. I would like to be able to initialise my application settings into the Consul kv store when I start the Consul container. Is this possible?
There are several projects which might be interesting for this scenario:
https://github.com/zerotens/consul-kv-bootstrap
https://github.com/cimpress-mcp/git2consul
https://github.com/cimpress-mcp/fsconsul
I wanted a simple approach to set application settings in Consul for a microservice project. I'm sure there are a number of existing tools but I wanted something that was lightweight and suits my development process. So rather than try to work with some of #mgyongyosi's suggestions I wrote a quick dotnet console application to do the (not so) heavy lifting. Under the project root directory I've created a directory structure Consul/kv. The child directories under that path represent keys in the Consul KV store and a json file at a leaf represents the application settings. Note there is only expected to be a single json file per leaf directory. The application uses the Consul.NET nuget package for communicating with Consul.
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Consul;
namespace ConfigureConsulKv
{
class Program
{
private static readonly string _basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"Projects", "MyProject", "Consul", "kv");
static void Main(string[] args)
{
RecurseDirectory(_basePath);
}
static void RecurseDirectory(string path)
{
foreach (var dir in Directory.EnumerateDirectories(path)) RecurseDirectory(dir);
var file = Directory.EnumerateFiles(path, "*.json").FirstOrDefault();
if (!string.IsNullOrWhiteSpace(file))
{
var key = path.Substring(_basePath.Length + 1);
var json = File.ReadAllBytes(file);
Console.WriteLine($"key {key} file {file}");
using (var client = new ConsulClient())
{
var attempt = client.KV.Put(new KVPair(key) { Value = json }).Result;
Console.WriteLine($"status {attempt.StatusCode}");
}
}
}
}
}

How to write to Excel using MVC and EF Code First - Best Practices

Vs'12 asp.net C# MVC, Internet Application Template, Kendo UI, EF Code First
What I am trying to do is use all my dataModels together and Build an Excel file, nicely formatted and all that good stuff - placing certain data into certain fields.These files would be fairly complex, - adding and checking checkboxes In Excel, creating boxes around fields other formatting
Now from what i can tell were exporting data from HTML into excel, however this is not something i would want, the only other way I can think of is to run C# code from a controller through a class, and then make it downloadable / and or export it?
Is this a "Best Practice" and if not what is?
You need to create your Excel to a byte[] or a Stream using a library like EPPlus. Then you can serve this using the FileActionResult:
public ActionResult CreateExcel()
{
var data=_repository.GetExcelData();
byte[] excel=CreateExcelAsByteArray(data);
return File(excel, "application/vnd.ms-excel", "excel.xlsx");
}
With this method you can serve a dinamically created Excel file.
Update: To create the excel file you can use EPPlus:
public byte[] CreateExcelAsByteArray(IEnumerable<int> elems)
{
using(var ms=new MemoryStream())
using(var package=new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("worksheet");
int i=1;
foreach(var elem in elems)
{
ws.Cells("A"+i).Value=elem;
i++;
}
package.SaveAs(ms);
return ms.ToArray();
}
}

db4o - how do I get a distinct list of classes contained in a .db4o DB file?

Say I open a .db4o file. What would be the Java code (psuedo) that would generate a list of unique Java CLASSES/TYPES contained in the database?
I am sure I could write the code to do it, but I am afraid it could be quite slow. Is there a good way to do this without querying for every object in the database? Could I use some sort of index?
I'd rather not rely on stored metadata about the database, I'd rather rely on the true information about what objects are actually stored within.
You can use something like (C# but it can be easily converted to Java :)
const string DatabaseFileName = "c:\\temp\\Learning.odb";
static void Main(string[] args)
{
using (var db = Db4oEmbedded.OpenFile(DatabaseFileName))
{
var classes = db.Ext().StoredClasses();
foreach (var #class in classes)
{
Console.WriteLine();
Console.WriteLine(#class.GetName());
foreach (var field in #class.GetStoredFields())
{
Console.WriteLine("\t{1} {0}", field.GetName(), field.GetStoredType().GetName());
}
}
}
}
Note that you have more interesting methods in ExtObjectContainer interface.
Hope this helps.

ASP.NET MVC: dealing with Version field

I have a versioned model:
public class VersionedModel
{
public Binary Version { get; set; }
}
Rendered using
<%= Html.Hidden("Version") %>
it gives:
<input id="Version" name="Version" type="hidden" value=""AQID"" />
that looks a bit strange. Any way, when the form submitted, the Version field is always null.
public ActionResult VersionedUpdate(VersionedModel data)
{
...
}
How can I pass Version over the wire?
EDIT:
A naive solution is:
public ActionResult VersionedUpdate(VersionedModel data)
{
data.Version = GetBinaryValue("Version");
}
private Binary GetBinaryValue(string name)
{
return new Binary(Convert.FromBase64String(this.Request[name].Replace("\"", "")));
}
Related posts I found.
Link
Suggests to turn 'Binary Version' into 'byte[] Version', but some commenter noticed:
The problem with this approach is that
it doesn't work if you want to use the
Table.Attach(modified, original)
overload, such as when you are using a
disconnected data context.
Link
Suggests a solution similar to my 'naive solution'
public static string TimestampToString(this System.Data.Linq.Binary binary)
{ ... }
public static System.Data.Linq.Binary StringToTimestamp(this string s)
{ ... }
http://msdn.microsoft.com/en-us/library/system.data.linq.binary.aspx
If you are using ASP.Net and use the
SQL Server "timestamp" datatype for
concurrency, you may want to convert
the "timestamp" value into a string so
you can store it (e.g., on a web
page). When LINQ to SQL retrieves a
"timestamp" from SQL Server, it stores
it in a Binary class instance. So you
essentially need to convert the Binary
instance to a string and then be able
to convert the string to an equivalent
Binary instance.
The code below provides two extension
methods to do this. You can remove the
"this" before the first parameter if
you prefer them to be ordinary static
methods. The conversion to base 64 is
a precaution to ensure that the
resultant string contains only
displayable characters and no escape
characters.
public static string ConvertRowVersionToString(this Binary rowVersion) {
return Convert.ToBase64String(rowVersion.ToArray());
}
public static Binary ConvertStringToRowVersion(this string rowVersion) {
return new Binary(Convert.FromBase64String(rowVersion));
}
I think the problem with not seeing it in the bound model on form submission is that there is no Convert.ToBinary() method available to the model binary to restructure the data from a string to it's binary representation. If you want to do this, I think that you'll need to convert the value by hand. I'm going to guess that the value you are seeing is the Base64 encoding of the binary value -- the output of Binary.ToString(). In that case, you'll need to convert it back from Base64 to a byte array and pass that to the Binary() constructor to reconstitute the value.
Have you thought about caching the object server-side, instead? This could be a little tricky as well as you have to detach the object from the data context (I'm assuming LINQ) or you wouldn't be able to reattach it to a different data context. This blog entry may be helpful if you decide to go that route.
You may need to use binding to get a strongly-typed parameter to your action method.
Try rendering using:
<%=Html.Hidden("VersionModel.Version")%>
And defining your action method signature as:
public ActionResult VersionedUpdate([Bind(Prefix="VersionModel")] VersionedModel data)
{
...
}
This post http://forums.asp.net/p/1401113/3032737.aspx#3032737 suggests to use
LinqBinaryModelBinder from http://aspnet.codeplex.com/SourceControl/changeset/view/21528#338524.
Once registered
protected void Application_Start()
{
ModelBinders.Binders.Add(typeof(Binary), new LinqBinaryModelBinder());
}
the binder will automatically deserialize Version field
public ActionResult VersionedUpdate(VersionedModel data)
{ ... }
rendered this way:
<%= Html.Hidden("Version") %>
(See also http://stephenwalther.com/blog/archive/2009/02/25/asp.net-mvc-tip-49-use-the-linqbinarymodelbinder-in-your.aspx)
There are many ways like here
byte[] b = BitConverter.GetBytes(DateTime.Now.Ticks);//new byte [(DateTime.Now).Ticks];
_store.Version = new System.Data.Linq.Binary(b)
(make sure you bind exclude your version),
But the best way is to let the DB handle it...
There are many ways like here
byte[] b = BitConverter.GetBytes(DateTime.Now.Ticks);//new byte [(DateTime.Now).Ticks]; _store.Version = new System.Data.Linq.Binary(b)
(make sure you bind exclude your version),
But the best way is to let the DB handle it...

ASP.NET MVC, MVVM and file uploads

I'm big fan of the MVVM pattern, in particular while using the ASP.NET MVC Framework (in this case v2 preview 2).
But I'm curious if anyone knows how to use it when doing file uploads?
public class MyViewModel
{
public WhatTypeShouldThisBe MyFileUpload { get; set; }
}
I have a production asp.net mvc site running with a jQuery multi-file uploader that i wrote. This answer has most of the code included in it so that should get you started with uploads in MVC. The question actually asks about storing the uploaded file in a Stream and i use a byte[], but you'll see in the answer how my code can apply to both scenarios.
Usually HttpFileCollection is enough if you are using the standard component (System.IO.Path).
take note that HttpFileCollection is a collection of HttpPostedFile, i.e. you can upload many files at once.
I would think byte[] would be enough to store the uploaded file, for example in my upload action, I would do sth like this:
foreach (string file in Request.Files)
{
HttpPostedFileBase hpf = Request.Files(file) as HttpPostedFileBase;
if (hpf.ContentLength == 0)
{
continue;
}
//This would be the part to get the data and save it to the view
byte[] origImageData = new byte[(int)hpf.ContentLength - 1 + 1];
hpf.InputStream.Read(origImageData, 0, (int)hpf.ContentLength);
}
Hope it helps some how.

Resources