Attach attributes in a separate table to a layer on GeoServer - django-models

I have an Occurrence model, which is represented by a polygon, and has a one-to-many relationship to an attribute table. The models are stored in a PostGIS database.
class Occurrence(models.Model):
"""Model representing an archaeological occurrence within a site."""
designation = models.CharField(max_length=254)
bounding_polygon = models.PolygonField(null=True, blank=True)
#...
class AttributeOccurrence(models.Model):
"""Model representing an attribute of an occurrence."""
value = models.ForeignKey(AttributeChoice, on_delete=models.PROTECT)
occurrence = models.ForeignKey(Occurrence, on_delete=models.CASCADE)
I have created a Store in GeoServer to publish the layer for the Occurrences.
How can I associate these attributes that are in the table so that they can be visible through GeoServer?

You will need to use the application schema extension:
The application schema support (app-schema) extension provides support for Complex Features in GeoServer WFS.

Related

Entity relation criteria in Doctrine2

I have the AdminFiles entity which holds files for all project entities (news, pages, events etc.). It is structured (abridged) like this:
id int(11) Auto Increment
entity varchar(255) // this holds the entity name, e.g. Page or News
entity_id int(11) NULL // this holds the entity ID
filename varchar(1000) // this holds the path to the file
I would love to access the files in the entities (Page, News etc.) with something like $entity->getFiles(). But I'm having trouble creating the relation, since it is not only constrained by the ID, but also the entity name. Is there any way to join this inside the Doctrine2 entity, or do I have to do this in the service?
This can be handled by Doctrine by using discriminator map feature. In your case there will be multiple entities inherited from base AdminFiles entity, each one will be specific for single type of files (e.g. PageFiles, NewsFiles and so on). You will need to establish mapping between entity column and these entities into #DiscriminatorMap annotation, then you will be able to fetch just one particular type of file by fetching (or using in association mapping) entity that represents some specific type of file.
You will also be able to even have entity properties that are specific to some particular type of file by using this feature.

NDB query with projection on an attribute used in .IN()

Let's say I have a model:
class Pet(ndb.Model):
age = ndb.IntegerProperty(indexed=False)
name = ndb.StringProperty(indexed=True)
owner = ndb.KeyProperty(indexed=True)
And I have a list of keys named owners. To do a query for Pets I would do:
pets = Pets.query(Pets.owner.IN(owners)).fetch()
The problem is that this query returns the whole entity.
How can I do a projected query and get just the owner and the name?
Or how should I structure the data to just get the name and the owner.
I can do a projection for the name but I loose reference from the pet to the owner. And owner can't be in the projection.
As you have noticed, you can't do that with the exact context you mentioned, because you hit one of the Limitations on projections:
Properties referenced in an equality (=) or membership (IN) filter cannot be projected.
Since owner is used in a IN filter it can't be projected. Since you need the owner and you can't project it you'll have to drop the projection and thus you'll always get the entire entity.
One alternative would be to split your entity into 2 peer entities, always into a 1:1 relationship, using the same entity IDs:
class PetA(ndb.Model):
name = ndb.StringProperty(indexed=True)
owner = ndb.KeyProperty(indexed=True)
class PetB(ndb.Model):
age = ndb.IntegerProperty(indexed=False)
This way you can do the same query, except on PetA kind instead of the original Pet and the result you'd get would be the equivalent of the original projection query you were seeking.
Unfortunately this will only work with one or a very few such projection queries for the same entity, otherwise you'd need to split the entity in too many pieces. So you may have to compromise.
You can find more details about the entity splitting in re-using an entity's ID for other entities of different kinds - sane idea?

Google App Engine Entity Ownership

I am writing an app for GAE in Python which stores recipes for different users. I have an entity called User in the datastore and an entity called Recipe. I want to be able to set the owner of each Recipe to the User who created it. Also, I want each User entity to contain a list of all Recipes belonging to that User as well as being able to query the Recipe database to find all Recipes owned by a particular User.
What is the best way to go about creating this parent/child type relationship?
Thanks
There are two main ways. (I am going to assume your using python which defines examples)
Option 1. Make the User the ancestor of all of their recipes
recipe = Recipe(parent=user.key)
Option 2. Use key property
class Recipe(ndb.Model):
owner = ndb.KeyProperty()
recipe = Recipe(owner=user.key)
all recipes for user with option 1
recipes = Recipe.query(ancestor=user.key)
all recupes for user with option 2
recipes = Recipe.query().filter(Recipe.owner == user.key)
Which one you use really depends a lot on what you plan to do with the data after creation, transaction patterns etc.... You should elaborate on your use cases. Both will work.
Also you should read up on transactions entity groups and understand them to really determine if you want to use ancestors https://developers.google.com/appengine/docs/java/datastore/transactions?hl=en .
If you use db.Model, to model one-to-many relationship, you can use the RefernenceProperty constructor and specify a collection_name. For example, one book may have many reviews.
class Book(db.Model):
title = db.StringProperty()
author = db.StringProperty()
class BookReview(db.Model):
book = db.ReferenceProperty(Book, collection_name='reviews')
b = Book()
b.put()
br = BookReview()
br.book = b # sets br's 'book' property to b's key
for review in b.reviews:# use collection_name to retrieve all reviews for a book
....
see https://developers.google.com/appengine/docs/python/datastore/datamodeling#references
Alternatively, you can use ndb's KeyProperty as in Tim's answer.
Also see
db.ReferenceProperty() vs ndb.KeyProperty in App Engine

de-normalizing data model: django/sql -> app engine

I'm just starting to get my head around non-relational databases, so I'd like to ask some help with converting these traditional SQL/django models into Google App Engine model(s).
The example is for event listings, where each event has a category, belongs to a venue, and a venue has a number of photos attached to it.
In django, I would model the data like this:
class Event(models.Model)
title = models.CharField()
start = models.DatetimeField()
category = models.ForeignKey(Category)
venue = models.ForeignKey(Venue)
class Category(models.Model):
name= models.CharField()
class Venue (models.Model):
name = models.CharField()
address = models.CharField()
class Photo(models.Model):
venue = models.ForeignKey(Venue)
source = models.CharField()
How would I accomplish the equivalent with App Engine models?
There's nothing here that must be de-normalized to work with App Engine. You can change ForeignKey to ReferenceProperty, CharField to StringProperty and DatetimeField to DateTimeProperty and be done. It might be more efficient to store category as a string rather than a reference, but this depends on usage context.
Denormalization becomes important when you start designing queries. Unlike traditional SQL, you can't write ad-hoc queries that have access to every row of every table. Anything you want to query for must be satisfied by an index. If you're running queries today that depend on table scans and complex joins, you'll have to make sure that the query parameters are indexed at write-time instead of calculating them on the fly.
As an example, if you wanted to do a case-insensitive search by event title, you'd have to store a lower-case copy of the title on every entity at write time. Without guessing your query requirements, I can't really offer more specific advice.
It's possible to run Django on App Engine
You need a trio of apps from here:
http://www.allbuttonspressed.com/projects
Django-nonrel
djangoappengine
djangotoolbox
Additionally, this module makes it possible to do the joins across Foreign Key relationships which are not directly supported by datastore methods:
django-dbindexer
...it denormalises the fields you want to join against, but has some limitations - doesn't update the denormalised values automatically so is only really suitable for static values
Django signals provide a useful starting point for automatic denormalisation.

Use database view in Django

I saw the question can i use a database view as a model in django and tried it in my app, but that didn't work.
I created a view named "vi\_topics" manually and it had "id" column but I kept getting an error, even if I added "id" field explicitly, saying
"no such column: vi_topics.id"
Here is the definition of my model named Vitopic:
from django.db import models
class Vitopic(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author_name = models.CharField(max_length=200)
author_email = models.CharField(max_length=200)
view_count = models.IntegerField(default=0)
replay_count = models.IntegerField(default=0)
tags = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'vi_topics'
Note: I use sqlite3.
Try this:
http://docs.djangoproject.com/en/dev/ref/models/options/#managed
managed
Options.managed
New in Django 1.1: Please, see the release notes
Defaults to True, meaning Django will create the appropriate database tables in syncdb and remove them as part of a reset management command. That is, Django manages the database tables' lifecycles.
If False, no database table creation or deletion operations will be performed for this model. This is useful if the model represents an existing table or a database view that has been created by some other means. This is the only difference when managed is False. All other aspects of model handling are exactly the same as normal. This includes
Adding an automatic primary key field to the model if you don't declare it. To avoid confusion for later code readers, it's recommended to specify all the columns from the database table you are modeling when using unmanaged models.
If a model with managed=False contains a ManyToManyField that points to another unmanaged model, then the intermediate table for the many-to-many join will also not be created. However, a the intermediary table between one managed and one unmanaged model will be created.
If you need to change this default behavior, create the intermediary table as an explicit model (with managed set as needed) and use the ManyToManyField.through attribute to make the relation use your custom model.
For tests involving models with managed=False, it's up to you to ensure the correct tables are created as part of the test setup.
id = models.IntegerField(primary_key=True)

Resources