How to set a 2D index in Play Morphia? - mongodb

How do I set a 2D index in play morphia?
Example:
db.places.ensureIndex( { loc : "2d" } )
http://www.mongodb.org/display/DOCS/Geospatial+Indexing

I assume you mean play 1.2.x.
You can't do this from the #Indexed annotation yet, it seems: http://code.google.com/p/morphia/issues/detail?id=290
You can do it with this somewhat hacky [untested] code:
MorphiaPlugin.ds()
.getMongo()
.getDB('dbname')
.getCollection('places')
.ensureIndex(BasicDBObject(loc, "2d"));
But you might just want to do it from the shell, as you show. It's a one time thing.

Just to add to this, years later:
#Indexes(
#Index(fields=#Field( value = "location", type= IndexType.GEO2DSPHERE))
)
on the #Entity class (if the member holding the GeoPoint is called location) generates the correct indices for spherical geospatial queries.
Don't forget to set the 4th param of the .near() method to true (spherical).
Also you should ensure the indices were generated by simply calling datastore.ensureIndexes() before querying.

Related

Apply filtering with an array of value instead of one value for a filter in Algolia

I have in my index a list of object, each of them has an objectID value.
On some search, i want to filter OUT a certain number of them, using there objectID.
For the moment it works with one value as a string, i would like to know how to do for multiple value.
filters = 'NOT objectID:' + objectIDToFilter;
This work for one object, what can i do to apply this for an array of ObjectID. because :
filters = 'NOT objectID:' + arrayObjectID;
does not work.
I was thinking of generating a huge string with an arrayId.map with all my 'NOT objectID:1 AND NOT objectID: 2 ...' but i wanted to know if there is a cleaner way to do it.
I unfortunately misunderstood the line in algolia doc :
Array Attributes: Any attribute set up as an array will match the filter as soon as one of the values in the array match.
This apparently refers to the value itself in Algolia and not the filter
So i did not found a solution on algolia doc, i went for the long string, hope there is no limits on how much filter we can add on a query (found nothing about that).
Here is what i did if someone need it :
let filters = `NOT objectID:${userID}`;
blockedByUsers.map((blockedByUser) => {
filters = filters + ` AND NOT objectID:${blockedByUser}`;
});
If you need to add multiple but don't have a starting point like i do, you can't start the query with an AND , a solution i found to bypass that:
let filters = `NOT objectID:${blockedByUsers[0]}`;
blockedByUsers.map((blockedByUser, i) => {
if (i > 0) filters = filters + ` AND NOT objectID:${blockedByUser}`;
});
There is probably a cleaner solution, but this work. If you have found other solution for that problems i'll be happy to see :)

Tinkerpop Frames #Adjacency to Orientdb LINKLIST

Is there a way to map Tinkerpop Frames's #Adjacency annotated property to Orientdb LINKLIST? Right now I've something like this:
interface Person {
#Adjacency(label = "personCars", direction = Direction.OUT)
Iterable<Car> getCars();
#Adjacency(label = "personCars", direction = Direction.OUT)
void addCar(Car car);
}
I want this to be mapped to LINKLIST in Orientdb database to keep an order of added vertices. But this is by default mapped to LINKBAG type. Is there any clean solution to set Orientdb to map adjacencies to LINKLISTs?
OrientDB, by default, uses a set to handle the edge collection. Sometimes it's better having an ordered list to access the edge by an offset. Example:
person.createEdgeProperty(Direction.OUT, "Photos").setOrdered(true);
Every time you access the edge collection the edges are ordered. Below is an example to print all the photos in an ordered way.
for (Edge e : loadedPerson.getEdges(Direction.OUT, "Photos")) {
System.out.println( "Photo name: " + e.getVertex(Direction.IN).getProperty("name") );
}
To access the underlying edge list you have to use the Document Database API. Here's an example to swap the 10th photo with the last.
// REPLACE EDGE Photos
List<ODocument> photos = loadedPerson.getRecord().field("out_Photos");
photos.add(photos.remove(9));
From the official documentation.

Extbase "findBy" with multiple parameters

I got an extension in which i want to include some filters, i know figured out that i can filter the results that are shown of my listAction() by using findBy.
I tested it and it worked like this:
$cars = $this->carRepository->findByCarid("1");
$this->view->assign('cars', $cars);
My problem now is i need to filter the result with more than one Parameter, what if i want to add findByColor("blue") so it gives me all cars wit hid 1 and color blue? What solution does extbase have for that kind of search queries? i can`t find anything good or understandable in the documentation.
You have to extend you repository and code this functionality on your own. Extbase offers you a simple but powerful API to do so.
class whatEverYourRepositoryIsCalled extends \TYPO3\CMS\Extbase\Persistence\Repository {
public function findByFilter($carId, $color) {
// Create empty query = select * from table
$query = $this->createQuery();
// Add query options
return $query->matching(
// ALL conditions have to be met (AND)
$query->logicalAnd(
// table column carId must be euqal to $carId
$query->equals('carId', $carId),
// table column color must be euqal to $color
$query->equals('color', $color)
)
);
}
}
This is a quite simple approach to your problem. In a real world scenario I would probably use an array of filter criteria to do the filtering like array('carId' => 1, 'color' => 'blue'). Inside of findByFilter() those values would be extracted and added to the query.
The key is to build the desired query. A quite comprehensive explanation of how to do that can be found at http://blog.typoplanet.de/2010/01/27/the-repository-and-query-object-of-extbase/. Unfortunately it's not completely up to date but the part about constructing queries is still valid.

How to use array results from orientjs query in another query - array is not an "array"

I want to use an array-like result from a query, but am having trouble.
I have:
class case extends V
class doc extends V
class filedIn extends E
So, a document is filed in a class via an edge of class filedIn.
My first query pulls a set a vertices:
.select().from('case').one().then(function(result){...
I then want to select all the filedIn edges linking to any of those case vertices, but how?
JSON.stringify(result)
{"#type":"d","#class":"matter","title":"my case","in_filedIn":["#17:7","#17:8","#17:9"],"#rid":"#12:3","#version":12}
looks like result['in_filedIn'] is an array,
but
.select().from(result['in_filedIn']).all()
gets me this error from back from the database:
Error on parsing command at position #0: Error parsing query: \nSELECT * FROM [object Object]\nEncountered \
select().from('[#17:7,#17:8,#17:9]')
(hard coded) works.
.select.from("[" + ["#17:1","#17:2].join(',') + "]").all()
also works.
but
select.from("[" + result['in_filedIn'].join(,)+"]").all()
throws
result.in_filedIn.join is not a function
I.e. whatever kind of object it is, it's not inheriting from the Array prototype.
console.log(result['in_filedIn'])
produces:
Bag {
serialized: >'AQAAAAUAEQAAAAAAAAAHABEAAAAAAAAACAARAAAAAAAAAAkAEQAAAAAAAAAKABEAAAAAAAAADwAAAAA>AAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
uuid: null,
_content:
[ { [String: '#17:7'] cluster: 17, position: 7 },
...
So I'm rather puzzled what to do.
I want to select all the edges whose #rid is listed in result.in_filedIn
Or have I misunderstood something?
Hi oliver in_filedIn is not an Array is a structure called RidBag in Orientjs the implementation is done in Bag.js.
If yo want to get the array you should do
result['in_filedIn'].all()
to get the array.
The following worked, though it's a bit dirty.
.from(JSON.stringify(result['in_filedIn']).replace(/"/g,""))
I'm still looking for a better answer!
I had a similar problem actually. When you instantiate your db connection, there's a config field they don't list in their docs called enableRIDBags.
So your config would look like:
{
host: 'localhost',
port: 2424,
username: 'blah',
password: 'blooh',
enableRIDBags: false
}
I find that it's better to just disable RIDBags as they're a bit finicky in node. The .all() trick listed above worked fine for me up until my vertices had more than 40 edges, as then they were all converted to SBTree bags instead of Embedded bags. If you check line 122 here, you'll see that they can't convert the trees to JSON when you call .all()

Multi level MongoDB object querying by key

If you only know the key name (say "nickname"), but not the exact path to that key in the object.
e.g. nickname may be at the first level like:
{"nickname":"Howie"}
or at the second level:
{"user":{"nickname":"Howie"}}
Is it possible to query for nickname equal "Howie" that would return both documents?
Unfortunately there is no wild card that allows you to search for a field at any level in the db. If the position is not relevant and you can modify the document structure you have 2 choices here. You can store your document as
{ fieldname:"nickname", value : "Howie" }
{ fieldname:"user/nickname", value: "Howie" }
You can then query using
db.so.find({fieldname:/nickname/, value:"Howie"})
Alternatively you can store as
db.so.insert({value:"Howie", fieldpath:["nickname"]})
db.so.insert({value:"Howie", fieldpath:["user", "nickname"]})
The advantage with the second approach is that you can now index {fieldpath:1, value:1} and a query on it such as
db.so.find({fieldpath:"nickname", value:"Howie"})
will be an indexed query.