Creation of compund unique contraint in neo4j 2.0 - indexing

i'm using neo4j to create a versioned graph database, and i'm having some troubles to implement unique constraints in the database.
I want to know if is possible to do something like
CREATE CONSTRAINT ON (u:CaliopeUser) ASSERT u.timestampt+u.name IS UNIQUE
Or any other idea about how to implenment the uniqueness constraint in neo4j for a versioned database.

In 2.0 compound schema indexes are not possible. The recommended workaround is to create another property holding the compound value (maybe a transactionEventHandler might help with automating this) and use a index on that property.
I expect support for indexes on compound properties in some future release.

Related

What is the core differences between constraints like PK vs Indexes

What is the core differences between a table that is created with constraints like PK vs a table created or added indexes created on it only (that don't have PK) when it comes which route would anyone prefer to implement when creating a table? I have work on them but I am just curious to know what separate them Thank you
They are quite different.
Constraints check the data that is being inserted and updated meet some criteria (for example "not null"). If the data does not meet the criteria, the INSERT or UPDATE is rejected, and fails. Constraints help you to maintain the quality of the data.
Indexes improve (most of the time) the speed of a query, and are usually beneficial to SELECT, UPDATE, and DELETE operations. Indexes improve database performance.
An index has no effect on how a query behaves nor the schema definition. It only effects performance. Although some SQL servers implement features using indexes, particularly the unique constraint. The SQL standard doesn't even mention them because they're considered an implementation issue.
A primary key constraint very much does have an effect on behavior and schema definition. It says this column must be unique and not null. Most databases also happen to index it for obvious performance reasons.
Declaring primary key rather than manually saying unique not null also lets the person reading your schema know that this is the primary key. They will know what its purpose it. It also lets the database know this is the primary key which might allow it to do some extra optimizations.

Does neo4j auto index work for MATCH clause?

We have turned on auto indexing for both nodes and relationship. By default NEO4J will create an index named "node_auto_index" for nodes and "relationship_auto_index" for relationships. But the MATCH queries seem to be under performing (comparing to a similar data set in Elasticsearch). Looks like they are not using the indexes.
Is there a way to make the MATCH clause use the auto_index ?
We also tried looking at the schema index. Looks like it can only create node indexes. Our queries use some properties on relationships and hence even after using the schema index the queries are unacceptable in performance.
Is there a way to create schema relationship indexes ?
The node_auto_index is not used for match, you would have to use the start clause to access that legacy index.
e.g.
START user=node:node_auto_index(name="Siddarth")
MATCH (user)-[:KNOWS]->(friend)
RETURN friend
In Neo4j 2.0 you can create an index or unique constraint instead
create index on :User(name);
and then use it in MATCH
MATCH (user:User {name:"Siddarth"})-[:FRIEND]->(friend)
RETURN friend
See also the manual: http://docs.neo4j.org/chunked/milestone/query-schema-index.html
and the cypher refcard: http://neo4j.org/resources/cypher

Fluent Nhibernate mapping Legacy DB with composite key

I am using Fluent NHibernate (which I am fairly new to) in an application I am developing using a legacy Oracle DB. The DB has composite keys which are comprised of foreign keys and database generated columns. The generated columns are supplied by calling a DB function with the table name, and one of the other foreign key parts. The generated composite key parts are not unique, and I cannot change this. The generated key parts are often used as foreign keys on other tables too.
If I create entity mapping which specifies the composite key as it is in the database, then we cannot use any identity generation strategies, which breaks unit of work
If I create entity mapping which specifies only the generated column as the primary key, then I can use trigger-identity to generate the ids, and I get unit of work, but I then have a problem when I want to update, or access a child collection: The other parts of the key are not included in the WHERE statement.
Can anyone give me any advice on how to proceed?
If I stick with mapping composite keys, can I extend nhibernate to output the SQL to use trigger-identity? If so, can you suggest a starting point?
If I map a single column key, can I include other properties in a WHERE clause for HasMany mapping and Updates?
Unfortunately, as you have already found out, there is no support at all for this setup.
My suggestion is to do INSERTS manually (using custom SQL, for example). And yes, this breaks the UoW, but that is true of identity too.

SQL Server View Primary Key

Is there a way to give a view a primary key in sql server. I know it is possible in oracle.
I am not concerned about updates its a read only view but someone else is using it in ms access so I would like the constraint that I know to be correct to be shown.
Yes, you can create an indexed view, which must have a primary key. Note, this will persist the view data to disk, which may or may not be what you are looking for.
Also, creation of indexed views can also impact performance, both positively and negatively. Make sure you read up on the pros, cons, and limitations thoroughly before implementing.
Indexed view is the correct choice but a primary key as RedFilter said is not actually required. Though there are many requirements that you will be forced to have such as a clustered index.
Within MS Access you can create a Primary-key on the linked view using the SQL statement:
ALTER TABLE [TableName] ADD CONSTRAINT [PrimaryKeyName] PRIMARY KEY ([FieldName1, FieldName2, ...])
That said, using an Indexed View is the better solution.

How can you create Clustered Indexes with Fluent NHibernate?

I am using Fluent-NHibernate (with automapping) to generate my tables but would like to choose a different clustered index than the ID field which is used by default. How can you create clustered indexes with Fluent NHibernate on a field other than the default Primary Key field?
The primary reasoning behind this is simple. I am using Guids for my primary key fields. By default, NHibernate creates clustered indexes on the primary key fields. Since Guids are usually not sequential, clustering on the primary key field causes a performance issue.
As we all know, appending records at the end of a table is a much cheaper operation than inserting records within the table. Also, the records in the table are physically stored in the order of the items in the clustered index. Since Guids are somewhat "random" and are not sequential, new Guids may be generated that are less than the value of other Id Guids already in the table--resulting in table inserts rather than appends.
To minimize this, I have a column called CreatedOn which is of type DateTime. I need for the table to be clustered on this CreatedOn column so that all new records are appended rather than inserted.
Any ideas for how to accomplish this are welcome!!!
Note: I realize that I could use Sequential Guids but prefer not to go down that path for security reasons.
Note: I still do not have an answer for this post but I have a few ideas I am pondering at the moment.
Using NHibernate without Fluent, I think it may be possible to created clustered indexes directly in NHibernate. I don't yet know enough about NHibernate to know how to do this. I am just pretty (as in almost absolutely) sure it can be done.
Fluent-NHibernate used to include a way to set attributes (e.g. like a clustered index) on a SQL object before the recent rewrite. Now that option appears to have gone away. I will probably post a question somewhere to see if that option is still available. If so, I could probably use that to set the clustered index.
Fluent-NHibernate provides the ability to expose a configuration for manual editing once it has been fluently built. I have not tried this functionality but expect it may offer the level of granularity that is needed to set clustered indexes.
Worst case scenario, I can write a SQL script to change the clustered indexes on all my tables once they are generated. However, I have a couple of questions regarding this approach. A. Since I am using automatic schema generation, will NHibernate "undo" my clustered index changes the next time it evaluates the configuration? 2. Will NHibernate error if it detects the clustered index has been changed? I need to test this but have not done so just yet. I really hate this solution though. I am testing my DB against SQLServer2008 and MySQL. Part of the beauty of NHibernate is that it is database agnostic. Once we introduce scripts, all bets are off.
There is an interface that is used in fluent conventions called IPropertyInstance Classes which inherit from this interface have an Index property which allows an Index to be created on the field. The problem is that there is no flag or other option to allow the index to be created as clustered. The simplest solution would be to add a property to this method to allow for clustered indexes to be created. I think I may suggest this to the Fluent-NHibernate developers.
This is an old post, but I hope could help someone else. This come from my experience on MS SQL Server. I believe different platforms require different solutions, but this should be a good starting point.
NHibernate doesn't set the CLUSTERED index on the primary key. It's the SQL Server default behavior. As there can be only one CLUSTERED per table, we need first to avoid the CLUSTERED creation on the primary key.
The only way I found to accomplish this is to create a custom Dialect, overriding the propery PrimaryKeyString. NHibernate's default comes from Dialect.cs:
public virtual string PrimaryKeyString
{
get { return "primary key"; }
}
For SQL Server
public override string PrimaryKeyString
{
get { return "primary key nonclustered"; }
}
This will force SQL Server to create a NONCLUSTERED primary key.
Now you can add your own CLUSTERED index on your favorite column through the tag in the XML mapping file.
<database-object>
<create>
create clustered index IX_CustomClusteredIndexName on TableName (ColumnName ASC)
</create>
<drop>
drop index IX_CustomClusteredIndexName ON TableName
</drop>
</database-object>
I can't answer that specifically, but I'll give you some database info since I'm here.
You'll need to tell NHibernate to create the primary key at a non-clustered index. There can only be only clustered index per table, so you need to create the table as a heap, and then put a clustered index on it.
As you said yourself, another option is to switch to the guid.comb ID generation strategy where PK uids are based on a part which is a Guid and a part which ensures that the generated IDs are sequential.
Check out more info in a post by Jeffrey Palermo here.
But you mention that do not want to do that for security reasons - why is that?
Just like #abx78 told, this is an old post, but I would like to share my knowledgde on a solution for this problem as well. I built the solution for idea 3 "Fluent NHibernate exposes mappings":
After the configuration has been build (thus the mappings are parsed), Fluent NHibernate gives us the oppertunity to look into the actual mappings with configuration.ClassMappings and configuration.CollectionMappings. The latter is used in the example below to set a composite primary key resulting in a clustered index in Sql Server (as #abx78 points out):
foreach (var collectionMapping in configuration.CollectionMappings) {
// Fetch the columns (in this example: build the columns in a hacky way)
const string columnFormat = "{0}_id";
var leftColumn = new Column(string.Format(
columnFormat,
collectionMapping.Owner.MappedClass.Name));
var rightColumn = new Column(string.Format(
columnFormat,
collectionMapping.GenericArguments[0].Name));
// Fetch the actual table of the many-to-many collection
var manyToManyTable = collectionMapping.CollectionTable;
// Shorten the name just like NHibernate does
var shortTableName = (manyToManyTable.Name.Length <= 8)
? manyToManyTable.Name
: manyToManyTable.Name.Substring(0, 8);
// Create the primary key and add the columns
// >> This part could be changed to a UniqueKey or to an Index
var primaryKey = new PrimaryKey {
Name = string.Format("PK_{0}", shortTableName),
};
primaryKey.AddColumn(leftColumn);
primaryKey.AddColumn(rightColumn);
// Set the primary key to the junction table
manyToManyTable.PrimaryKey = primaryKey;
// <<
}
Source: Fluent NHibernate: How to create a clustered index on a Many-to-Many Join Table?